blob: 33f612e090704682bd619ce27930d9365f37cc24 [file] [log] [blame]
Andrew Sapperstein8f1c01e2012-06-18 18:15:30 -07001/*
2 * Copyright (C) 2012 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070018package com.android.mail.browse;
19
Mark Wei1aee17e2013-01-14 14:47:16 -080020
Paul Westbrook8081df42012-09-10 15:43:36 -070021import android.app.DialogFragment;
22import android.app.Fragment;
23import android.app.FragmentManager;
24import android.app.FragmentTransaction;
Andrew Sapperstein532f4822012-06-14 12:48:35 -070025import android.content.ActivityNotFoundException;
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070026import android.content.ContentValues;
27import android.content.Context;
Andrew Sapperstein532f4822012-06-14 12:48:35 -070028import android.content.Intent;
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070029import android.net.Uri;
Paul Westbrook8081df42012-09-10 15:43:36 -070030import android.os.Handler;
Andrew Sapperstein532f4822012-06-14 12:48:35 -070031import android.os.Parcelable;
Andrew Sapperstein381c3222014-04-20 12:23:57 -070032import android.view.View;
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070033
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070034import com.android.mail.providers.Attachment;
Andy Huang4f347e82014-02-25 17:32:28 -080035import com.android.mail.providers.Message;
Mark Wei1aee17e2013-01-14 14:47:16 -080036import com.android.mail.providers.UIProvider;
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070037import com.android.mail.providers.UIProvider.AttachmentColumns;
Mark Wei1aee17e2013-01-14 14:47:16 -080038import com.android.mail.providers.UIProvider.AttachmentContentValueKeys;
Andrew Sapperstein4cb51db2012-07-20 15:54:27 -070039import com.android.mail.providers.UIProvider.AttachmentDestination;
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070040import com.android.mail.providers.UIProvider.AttachmentState;
Paul Westbrookb334c902012-06-25 11:42:46 -070041import com.android.mail.utils.LogTag;
Andrew Sapperstein532f4822012-06-14 12:48:35 -070042import com.android.mail.utils.LogUtils;
43import com.android.mail.utils.Utils;
44
45import java.util.ArrayList;
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070046
Paul Westbrook8081df42012-09-10 15:43:36 -070047public class AttachmentActionHandler {
48 private static final String PROGRESS_FRAGMENT_TAG = "attachment-progress";
49
Andy Huang4f347e82014-02-25 17:32:28 -080050 private String mAccount;
51 private Message mMessage;
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070052 private Attachment mAttachment;
53
54 private final AttachmentCommandHandler mCommandHandler;
55 private final AttachmentViewInterface mView;
56 private final Context mContext;
Paul Westbrook8081df42012-09-10 15:43:36 -070057 private final Handler mHandler;
58 private FragmentManager mFragmentManager;
Martin Hibdon519c2182013-09-20 17:27:57 -070059 private boolean mViewOnFinish;
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070060
Paul Westbrookb334c902012-06-25 11:42:46 -070061 private static final String LOG_TAG = LogTag.getLogTag();
Andrew Sapperstein532f4822012-06-14 12:48:35 -070062
Andy Huang4f347e82014-02-25 17:32:28 -080063 private static OptionHandler sOptionHandler = new OptionHandler();
64
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070065 public AttachmentActionHandler(Context context, AttachmentViewInterface view) {
66 mCommandHandler = new AttachmentCommandHandler(context);
67 mView = view;
68 mContext = context;
Paul Westbrook8081df42012-09-10 15:43:36 -070069 mHandler = new Handler();
Martin Hibdon519c2182013-09-20 17:27:57 -070070 mViewOnFinish = true;
Paul Westbrook8081df42012-09-10 15:43:36 -070071 }
72
73 public void initialize(FragmentManager fragmentManager) {
74 mFragmentManager = fragmentManager;
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070075 }
76
Andy Huang4f347e82014-02-25 17:32:28 -080077 public void setAccount(String account) {
78 mAccount = account;
79 }
80
81 public void setMessage(Message message) {
82 mMessage = message;
83 }
84
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070085 public void setAttachment(Attachment attachment) {
86 mAttachment = attachment;
87 }
88
Martin Hibdon519c2182013-09-20 17:27:57 -070089 public void setViewOnFinish(boolean viewOnFinish) {
90 mViewOnFinish = viewOnFinish;
91 }
92
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -070093 public void showAttachment(int destination) {
Mark Wei7bed4bc2013-01-22 22:56:22 -080094 if (mView == null) {
95 return;
96 }
97
Paul Westbrooka25b65e2012-09-25 09:21:52 -070098 // If the caller requested that this attachments be saved to the external storage, we should
99 // verify that the it was saved there.
100 if (mAttachment.isPresentLocally() &&
101 (destination == AttachmentDestination.CACHE ||
102 mAttachment.destination == destination)) {
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700103 mView.viewAttachment();
104 } else {
Scott Kennedy9e2d4072013-03-21 21:46:01 -0700105 showDownloadingDialog();
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700106 startDownloadingAttachment(destination);
107 }
108 }
109
Mark Wei7bed4bc2013-01-22 22:56:22 -0800110 /**
111 * Start downloading the full size attachment set with
112 * {@link #setAttachment(Attachment)} immediately.
113 */
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700114 public void startDownloadingAttachment(int destination) {
Mark Wei26745352013-01-17 21:40:34 -0800115 startDownloadingAttachment(destination, UIProvider.AttachmentRendition.BEST, 0, false);
Andrew Sapperstein4cb51db2012-07-20 15:54:27 -0700116 }
117
Mark Wei26745352013-01-17 21:40:34 -0800118 public void startDownloadingAttachment(
119 int destination, int rendition, int additionalPriority, boolean delayDownload) {
120 startDownloadingAttachment(
121 mAttachment, destination, rendition, additionalPriority, delayDownload);
Mark Wei1aee17e2013-01-14 14:47:16 -0800122 }
123
Mark Wei26745352013-01-17 21:40:34 -0800124 private void startDownloadingAttachment(
125 Attachment attachment, int destination, int rendition, int additionalPriority,
126 boolean delayDownload) {
Andrew Sapperstein7434e802013-06-21 11:26:49 -0700127 final ContentValues params = new ContentValues(5);
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700128 params.put(AttachmentColumns.STATE, AttachmentState.DOWNLOADING);
129 params.put(AttachmentColumns.DESTINATION, destination);
Mark Wei1aee17e2013-01-14 14:47:16 -0800130 params.put(AttachmentContentValueKeys.RENDITION, rendition);
Mark Wei26745352013-01-17 21:40:34 -0800131 params.put(AttachmentContentValueKeys.ADDITIONAL_PRIORITY, additionalPriority);
132 params.put(AttachmentContentValueKeys.DELAY_DOWNLOAD, delayDownload);
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700133
Andrew Sapperstein4cb51db2012-07-20 15:54:27 -0700134 mCommandHandler.sendCommand(attachment.uri, params);
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700135 }
136
137 public void cancelAttachment() {
138 final ContentValues params = new ContentValues(1);
139 params.put(AttachmentColumns.STATE, AttachmentState.NOT_SAVED);
140
141 mCommandHandler.sendCommand(mAttachment.uri, params);
142 }
143
Mark Wei47ca4e22012-10-17 16:20:15 -0700144 public void startRedownloadingAttachment(Attachment attachment) {
145 final ContentValues params = new ContentValues(2);
146 params.put(AttachmentColumns.STATE, AttachmentState.REDOWNLOADING);
147 params.put(AttachmentColumns.DESTINATION, attachment.destination);
148
149 mCommandHandler.sendCommand(attachment.uri, params);
150 }
151
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700152 /**
153 * Displays a loading dialog to be used for downloading attachments.
154 * Must be called on the UI thread.
155 */
Mark Weice9db802013-08-08 14:57:29 -0700156 public void showDownloadingDialog() {
Paul Westbrook8081df42012-09-10 15:43:36 -0700157 final FragmentTransaction ft = mFragmentManager.beginTransaction();
158 final Fragment prev = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG);
159 if (prev != null) {
160 ft.remove(prev);
161 }
162 ft.addToBackStack(null);
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700163
Paul Westbrook8081df42012-09-10 15:43:36 -0700164 // Create and show the dialog.
165 final DialogFragment newFragment = AttachmentProgressDialogFragment.newInstance(
Scott Kennedy9e2d4072013-03-21 21:46:01 -0700166 mAttachment);
Paul Westbrook8081df42012-09-10 15:43:36 -0700167 newFragment.show(ft, PROGRESS_FRAGMENT_TAG);
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700168 }
169
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700170 /**
171 * Update progress-related views. Will also trigger a view intent if a progress dialog was
172 * previously brought up (by tapping 'View') and the download has now finished.
173 */
Paul Westbrook8081df42012-09-10 15:43:36 -0700174 public void updateStatus(boolean loaderResult) {
Mark Wei7bed4bc2013-01-22 22:56:22 -0800175 if (mView == null) {
176 return;
177 }
178
Andrew Sapperstein4cb51db2012-07-20 15:54:27 -0700179 final boolean showProgress = mAttachment.shouldShowProgress();
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700180
Paul Westbrook8081df42012-09-10 15:43:36 -0700181 final AttachmentProgressDialogFragment dialog = (AttachmentProgressDialogFragment)
182 mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG);
183 if (dialog != null && dialog.isShowingDialogForAttachment(mAttachment)) {
184 dialog.setProgress(mAttachment.downloadedSize);
Paul Westbrookbedcad92012-08-22 00:33:04 -0700185
186 // We don't want the progress bar to switch back to indeterminate mode after
187 // have been in determinate progress mode.
Paul Westbrook8081df42012-09-10 15:43:36 -0700188 final boolean indeterminate = !showProgress && dialog.isIndeterminate();
189 dialog.setIndeterminate(indeterminate);
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700190
Mark Weibbe74ae2012-11-19 11:20:09 -0800191 if (loaderResult && mAttachment.isDownloadFinishedOrFailed()) {
Paul Westbrook8081df42012-09-10 15:43:36 -0700192 mHandler.post(new Runnable() {
193 @Override
194 public void run() {
195 dialog.dismiss();
196 }
197 });
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700198 }
199
Martin Hibdon519c2182013-09-20 17:27:57 -0700200 if (mAttachment.state == AttachmentState.SAVED && mViewOnFinish) {
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700201 mView.viewAttachment();
202 }
203 } else {
204 mView.updateProgress(showProgress);
205 }
206
Andrew Sapperstein532f4822012-06-14 12:48:35 -0700207 // Call on update status for the view so that it can do some specific things.
208 mView.onUpdateStatus();
209 }
210
Andrew Sappersteina95161c2012-07-31 16:00:21 -0700211 public boolean isProgressDialogVisible() {
Paul Westbrook8081df42012-09-10 15:43:36 -0700212 final Fragment dialog = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG);
213 return dialog != null && dialog.isVisible();
Andrew Sappersteina95161c2012-07-31 16:00:21 -0700214 }
215
Andrew Sapperstein532f4822012-06-14 12:48:35 -0700216 public void shareAttachment() {
Sara Tingd2f279f2012-09-26 11:01:05 -0700217 if (mAttachment.contentUri == null) {
218 return;
219 }
220
Andrew Sapperstein532f4822012-06-14 12:48:35 -0700221 Intent intent = new Intent(Intent.ACTION_SEND);
222 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
223 | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
224
225 final Uri uri = Utils.normalizeUri(mAttachment.contentUri);
226 intent.putExtra(Intent.EXTRA_STREAM, uri);
Mark Wei87500662013-02-20 14:29:53 -0800227 intent.setType(Utils.normalizeMimeType(mAttachment.getContentType()));
Andrew Sapperstein532f4822012-06-14 12:48:35 -0700228
229 try {
230 mContext.startActivity(intent);
231 } catch (ActivityNotFoundException e) {
232 // couldn't find activity for SEND intent
233 LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e);
234 }
235 }
236
237 public void shareAttachments(ArrayList<Parcelable> uris) {
238 Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
239 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
240 | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
241
242 intent.setType("image/*");
243 intent.putParcelableArrayListExtra(
244 Intent.EXTRA_STREAM, uris);
245
246 try {
247 mContext.startActivity(intent);
248 } catch (ActivityNotFoundException e) {
249 // couldn't find activity for SEND_MULTIPLE intent
250 LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e);
251 }
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700252 }
Andy Huang4f347e82014-02-25 17:32:28 -0800253
254 public static void setOptionHandler(OptionHandler handler) {
255 sOptionHandler = handler;
256 }
257
258 public boolean shouldShowExtraOption1() {
259 return (sOptionHandler != null) && sOptionHandler.shouldShowExtraOption1();
260 }
261
262 public void handleOption1() {
263 if (sOptionHandler == null) {
264 return;
265 }
266 sOptionHandler.handleOption1(mContext, mAccount, mMessage, mAttachment, mFragmentManager);
267 }
268
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700269 public static boolean shouldShowAboveBarAttachmentLayout(Context context) {
270 return (sOptionHandler != null) &&
271 sOptionHandler.shouldShowAboveBarAttachmentLayout(context);
272 }
273
274 public static void setupAboveBarAttachmentLayout(View view) {
275 if (sOptionHandler != null) {
276 sOptionHandler.setupAboveBarAttachmentLayout(view);
277 }
278 }
279
280 public static void onOverflowOpened(Context context) {
281 if(sOptionHandler != null) {
282 sOptionHandler.onOverflowOpened(context);
283 }
284 }
285
286 public static void registerDismissListener(Uri conversationUri,
287 AboveAttachmentLayoutDismissedListener listener) {
288 if (sOptionHandler != null) {
289 sOptionHandler.registerDismissListener(conversationUri, listener);
290 }
291 }
292
293 public static void unregisterDismissListeners(Uri conversationUri) {
294 if(sOptionHandler != null) {
295 sOptionHandler.unregisterDismissListeners(conversationUri);
296 }
297 }
298
299
Andy Huang4f347e82014-02-25 17:32:28 -0800300 /**
301 * A default, no-op option class. Override this and set it globally with
302 * {@link AttachmentActionHandler#setOptionHandler(OptionHandler)}.<br>
303 * <br>
304 * Subclasses of this type will live pretty much forever, so really, really try to avoid
305 * keeping any state as member variables in them.
306 */
307 public static class OptionHandler {
308
309 public boolean shouldShowExtraOption1() {
310 return false;
311 }
312
Andy Huang4f347e82014-02-25 17:32:28 -0800313 public void handleOption1(Context context, String account, Message message,
314 Attachment attachment, FragmentManager fm) {
315 // no-op
316 }
317
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700318 public boolean shouldShowAboveBarAttachmentLayout(Context context) {
319 return false;
320 }
321
322 public void setupAboveBarAttachmentLayout(View view) { /* no-op */ }
323
324 public void onOverflowOpened(Context context) { /* no-op */ }
325
326 public void registerDismissListener(Uri conversationUri,
327 AboveAttachmentLayoutDismissedListener listener) {
328 // no-op
329 }
330
331 public void unregisterDismissListeners(Uri conversationUri) {
332 // no-op
333 }
334 }
335
336 public interface AboveAttachmentLayoutDismissedListener {
337 void onOtherLayoutDismissed();
Andy Huang4f347e82014-02-25 17:32:28 -0800338 }
339
Andrew Sapperstein4aa1c132012-06-08 17:53:41 -0700340}