1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.messaging.ui; 18 19 import android.app.AlertDialog; 20 import android.app.Dialog; 21 import android.app.DialogFragment; 22 import android.app.Fragment; 23 import android.app.FragmentTransaction; 24 import android.content.Context; 25 import android.content.DialogInterface; 26 import android.content.res.Resources; 27 import android.os.Bundle; 28 import android.view.LayoutInflater; 29 import android.view.View; 30 import android.view.View.OnClickListener; 31 import android.view.ViewGroup; 32 import android.widget.ArrayAdapter; 33 import android.widget.ListView; 34 import android.widget.TextView; 35 36 import com.android.messaging.R; 37 import com.android.messaging.datamodel.action.HandleLowStorageAction; 38 import com.android.messaging.sms.SmsReleaseStorage; 39 import com.android.messaging.sms.SmsReleaseStorage.Duration; 40 import com.android.messaging.sms.SmsStorageStatusManager; 41 import com.android.messaging.util.Assert; 42 import com.google.common.collect.Lists; 43 44 import java.util.List; 45 46 /** 47 * Dialog to show the sms storage low warning 48 */ 49 public class SmsStorageLowWarningFragment extends Fragment { SmsStorageLowWarningFragment()50 private SmsStorageLowWarningFragment() { 51 } 52 newInstance()53 public static SmsStorageLowWarningFragment newInstance() { 54 return new SmsStorageLowWarningFragment(); 55 } 56 57 @Override onCreate(final Bundle savedInstanceState)58 public void onCreate(final Bundle savedInstanceState) { 59 super.onCreate(savedInstanceState); 60 final FragmentTransaction ft = getFragmentManager().beginTransaction(); 61 final ChooseActionDialogFragment dialog = ChooseActionDialogFragment.newInstance(); 62 dialog.setTargetFragment(this, 0/*requestCode*/); 63 dialog.show(ft, null/*tag*/); 64 } 65 66 /** 67 * Perform confirm action for a specific action 68 * 69 * @param actionIndex 70 */ confirm(final int actionIndex)71 private void confirm(final int actionIndex) { 72 final FragmentTransaction ft = getFragmentManager().beginTransaction(); 73 final ConfirmationDialog dialog = ConfirmationDialog.newInstance(actionIndex); 74 dialog.setTargetFragment(this, 0/*requestCode*/); 75 dialog.show(ft, null/*tag*/); 76 } 77 78 /** 79 * The dialog is cancelled at any step 80 */ cancel()81 private void cancel() { 82 getActivity().finish(); 83 } 84 85 /** 86 * The dialog to show for user to choose what delete actions to take when storage is low 87 */ 88 private static class ChooseActionDialogFragment extends DialogFragment { newInstance()89 public static ChooseActionDialogFragment newInstance() { 90 return new ChooseActionDialogFragment(); 91 } 92 93 @Override onCreateDialog(final Bundle savedInstanceState)94 public Dialog onCreateDialog(final Bundle savedInstanceState) { 95 final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 96 97 final LayoutInflater inflater = getActivity().getLayoutInflater(); 98 final View dialogLayout = inflater.inflate( 99 R.layout.sms_storage_low_warning_dialog, null); 100 final ListView actionListView = (ListView) dialogLayout.findViewById( 101 R.id.free_storage_action_list); 102 final List<String> actions = loadFreeStorageActions(getActivity().getResources()); 103 final ActionListAdapter listAdapter = new ActionListAdapter(getActivity(), actions); 104 actionListView.setAdapter(listAdapter); 105 106 builder.setTitle(R.string.sms_storage_low_title) 107 .setView(dialogLayout) 108 .setNegativeButton(R.string.ignore, new DialogInterface.OnClickListener() { 109 @Override 110 public void onClick(DialogInterface dialog, int id) { 111 dialog.cancel(); 112 } 113 }); 114 115 final Dialog dialog = builder.create(); 116 dialog.setCanceledOnTouchOutside(false); 117 return dialog; 118 } 119 120 @Override onCancel(final DialogInterface dialog)121 public void onCancel(final DialogInterface dialog) { 122 ((SmsStorageLowWarningFragment) getTargetFragment()).cancel(); 123 } 124 125 private class ActionListAdapter extends ArrayAdapter<String> { ActionListAdapter(final Context context, final List<String> actions)126 public ActionListAdapter(final Context context, final List<String> actions) { 127 super(context, R.layout.sms_free_storage_action_item_view, actions); 128 } 129 130 @Override getView(final int position, final View view, final ViewGroup parent)131 public View getView(final int position, final View view, final ViewGroup parent) { 132 TextView actionItemView; 133 if (view == null || !(view instanceof TextView)) { 134 final LayoutInflater inflater = LayoutInflater.from(getContext()); 135 actionItemView = (TextView) inflater.inflate( 136 R.layout.sms_free_storage_action_item_view, parent, false); 137 } else { 138 actionItemView = (TextView) view; 139 } 140 141 final String action = getItem(position); 142 actionItemView.setText(action); 143 actionItemView.setOnClickListener(new OnClickListener() { 144 @Override 145 public void onClick(final View view) { 146 dismiss(); 147 ((SmsStorageLowWarningFragment) getTargetFragment()).confirm(position); 148 } 149 }); 150 return actionItemView; 151 } 152 } 153 } 154 155 private static final String KEY_ACTION_INDEX = "action_index"; 156 157 /** 158 * The dialog to confirm user's delete action 159 */ 160 private static class ConfirmationDialog extends DialogFragment { 161 private Duration mDuration; 162 private String mDurationString; 163 newInstance(final int actionIndex)164 public static ConfirmationDialog newInstance(final int actionIndex) { 165 final ConfirmationDialog dialog = new ConfirmationDialog(); 166 final Bundle args = new Bundle(); 167 args.putInt(KEY_ACTION_INDEX, actionIndex); 168 dialog.setArguments(args); 169 return dialog; 170 } 171 172 @Override onCancel(final DialogInterface dialog)173 public void onCancel(final DialogInterface dialog) { 174 ((SmsStorageLowWarningFragment) getTargetFragment()).cancel(); 175 } 176 177 @Override onCreateDialog(final Bundle savedInstanceState)178 public Dialog onCreateDialog(final Bundle savedInstanceState) { 179 mDuration = SmsReleaseStorage.parseMessageRetainingDuration(); 180 mDurationString = SmsReleaseStorage.getMessageRetainingDurationString(mDuration); 181 182 final int actionIndex = getArguments().getInt(KEY_ACTION_INDEX); 183 if (actionIndex < 0 || actionIndex > 1) { 184 return null; 185 } 186 final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 187 builder.setTitle(R.string.sms_storage_low_title) 188 .setMessage(getConfirmDialogMessage(actionIndex)) 189 .setNegativeButton(android.R.string.cancel, 190 new DialogInterface.OnClickListener() { 191 @Override 192 public void onClick(final DialogInterface dialog, 193 final int button) { 194 dismiss(); 195 ((SmsStorageLowWarningFragment) getTargetFragment()).cancel(); 196 } 197 }) 198 .setPositiveButton(android.R.string.ok, 199 new DialogInterface.OnClickListener() { 200 @Override 201 public void onClick(final DialogInterface dialog, 202 final int button) { 203 dismiss(); 204 handleAction(actionIndex); 205 getActivity().finish(); 206 SmsStorageStatusManager.cancelStorageLowNotification(); 207 } 208 }); 209 return builder.create(); 210 } 211 handleAction(final int actionIndex)212 private void handleAction(final int actionIndex) { 213 final long durationInMillis = 214 SmsReleaseStorage.durationToTimeInMillis(mDuration); 215 switch (actionIndex) { 216 case 0: 217 HandleLowStorageAction.handleDeleteMediaMessages(durationInMillis); 218 break; 219 220 case 1: 221 HandleLowStorageAction.handleDeleteOldMessages(durationInMillis); 222 break; 223 224 default: 225 Assert.fail("Unsupported action"); 226 break; 227 } 228 } 229 230 /** 231 * Get the confirm dialog text for a specific delete action 232 * @param index The action index 233 * @return 234 */ getConfirmDialogMessage(final int index)235 private String getConfirmDialogMessage(final int index) { 236 switch (index) { 237 case 0: 238 return getString(R.string.delete_all_media_confirmation, mDurationString); 239 case 1: 240 return getString(R.string.delete_oldest_messages_confirmation, mDurationString); 241 case 2: 242 return getString(R.string.auto_delete_oldest_messages_confirmation, 243 mDurationString); 244 } 245 throw new IllegalArgumentException( 246 "SmsStorageLowWarningFragment: invalid action index " + index); 247 } 248 } 249 250 /** 251 * Load the text of delete message actions 252 * 253 * @param resources 254 * @return 255 */ loadFreeStorageActions(final Resources resources)256 private static List<String> loadFreeStorageActions(final Resources resources) { 257 final Duration duration = SmsReleaseStorage.parseMessageRetainingDuration(); 258 final String durationString = SmsReleaseStorage.getMessageRetainingDurationString(duration); 259 final List<String> actions = Lists.newArrayList(); 260 actions.add(resources.getString(R.string.delete_all_media)); 261 actions.add(resources.getString(R.string.delete_oldest_messages, durationString)); 262 263 // TODO: Auto-purging is disabled for Bugle V1. 264 // actions.add(resources.getString(R.string.auto_delete_oldest_messages, durationString)); 265 return actions; 266 } 267 } 268