summaryrefslogtreecommitdiffstats
path: root/src/com/android/mail/browse/AttachmentActionHandler.java
blob: ee569a6504c2a73277719192029b5fc30937c34d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/*
 * Copyright (C) 2012 Google Inc.
 * Licensed to The Android Open Source Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.mail.browse;


import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.ActivityNotFoundException;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Parcelable;

import com.android.mail.providers.Attachment;
import com.android.mail.providers.Message;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.AttachmentColumns;
import com.android.mail.providers.UIProvider.AttachmentContentValueKeys;
import com.android.mail.providers.UIProvider.AttachmentDestination;
import com.android.mail.providers.UIProvider.AttachmentState;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;

import java.util.ArrayList;

public class AttachmentActionHandler {
    private static final String PROGRESS_FRAGMENT_TAG = "attachment-progress";

    private String mAccount;
    private Message mMessage;
    private Attachment mAttachment;

    private final AttachmentCommandHandler mCommandHandler;
    private final AttachmentViewInterface mView;
    private final Context mContext;
    private final Handler mHandler;
    private FragmentManager mFragmentManager;
    private boolean mViewOnFinish;

    private static final String LOG_TAG = LogTag.getLogTag();

    private static OptionHandler sOptionHandler = new OptionHandler();

    public AttachmentActionHandler(Context context, AttachmentViewInterface view) {
        mCommandHandler = new AttachmentCommandHandler(context);
        mView = view;
        mContext = context;
        mHandler = new Handler();
        mViewOnFinish = true;
    }

    public void initialize(FragmentManager fragmentManager) {
        mFragmentManager = fragmentManager;
    }

    public void setAccount(String account) {
        mAccount = account;
    }

    public void setMessage(Message message) {
        mMessage = message;
    }

    public void setAttachment(Attachment attachment) {
        mAttachment = attachment;
    }

    public void setViewOnFinish(boolean viewOnFinish) {
        mViewOnFinish = viewOnFinish;
    }

    public void showAttachment(int destination) {
        if (mView == null) {
            return;
        }

        // If the caller requested that this attachments be saved to the external storage, we should
        // verify that the it was saved there.
        if (mAttachment.isPresentLocally() &&
                (destination == AttachmentDestination.CACHE ||
                        mAttachment.destination == destination)) {
            mView.viewAttachment();
        } else {
            showDownloadingDialog();
            startDownloadingAttachment(destination);
        }
    }

    /**
     * Start downloading the full size attachment set with
     * {@link #setAttachment(Attachment)} immediately.
     */
    public void startDownloadingAttachment(int destination) {
        startDownloadingAttachment(destination, UIProvider.AttachmentRendition.BEST, 0, false);
    }

    public void startDownloadingAttachment(
            int destination, int rendition, int additionalPriority, boolean delayDownload) {
        startDownloadingAttachment(
                mAttachment, destination, rendition, additionalPriority, delayDownload);
    }

    private void startDownloadingAttachment(
            Attachment attachment, int destination, int rendition, int additionalPriority,
            boolean delayDownload) {
        final ContentValues params = new ContentValues(5);
        params.put(AttachmentColumns.STATE, AttachmentState.DOWNLOADING);
        params.put(AttachmentColumns.DESTINATION, destination);
        params.put(AttachmentContentValueKeys.RENDITION, rendition);
        params.put(AttachmentContentValueKeys.ADDITIONAL_PRIORITY, additionalPriority);
        params.put(AttachmentContentValueKeys.DELAY_DOWNLOAD, delayDownload);

        mCommandHandler.sendCommand(attachment.uri, params);
    }

    public void cancelAttachment() {
        final ContentValues params = new ContentValues(1);
        params.put(AttachmentColumns.STATE, AttachmentState.NOT_SAVED);

        mCommandHandler.sendCommand(mAttachment.uri, params);
    }

    public void startRedownloadingAttachment(Attachment attachment) {
        final ContentValues params = new ContentValues(2);
        params.put(AttachmentColumns.STATE, AttachmentState.REDOWNLOADING);
        params.put(AttachmentColumns.DESTINATION, attachment.destination);

        mCommandHandler.sendCommand(attachment.uri, params);
    }

    /**
     * Displays a loading dialog to be used for downloading attachments.
     * Must be called on the UI thread.
     */
    public void showDownloadingDialog() {
        final FragmentTransaction ft = mFragmentManager.beginTransaction();
        final Fragment prev = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG);
        if (prev != null) {
            ft.remove(prev);
        }
        ft.addToBackStack(null);

         // Create and show the dialog.
        final DialogFragment newFragment = AttachmentProgressDialogFragment.newInstance(
                mAttachment);
        newFragment.show(ft, PROGRESS_FRAGMENT_TAG);
    }

    /**
     * Update progress-related views. Will also trigger a view intent if a progress dialog was
     * previously brought up (by tapping 'View') and the download has now finished.
     */
    public void updateStatus(boolean loaderResult) {
        if (mView == null) {
            return;
        }

        final boolean showProgress = mAttachment.shouldShowProgress();

        final AttachmentProgressDialogFragment dialog = (AttachmentProgressDialogFragment)
                mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG);
        if (dialog != null && dialog.isShowingDialogForAttachment(mAttachment)) {
            dialog.setProgress(mAttachment.downloadedSize);

            // We don't want the progress bar to switch back to indeterminate mode after
            // have been in determinate progress mode.
            final boolean indeterminate = !showProgress && dialog.isIndeterminate();
            dialog.setIndeterminate(indeterminate);

            if (loaderResult && mAttachment.isDownloadFinishedOrFailed()) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        dialog.dismiss();
                    }
                });
            }

            if (mAttachment.state == AttachmentState.SAVED && mViewOnFinish) {
                mView.viewAttachment();
            }
        } else {
            mView.updateProgress(showProgress);
        }

        // Call on update status for the view so that it can do some specific things.
        mView.onUpdateStatus();
    }

    public boolean isProgressDialogVisible() {
        final Fragment dialog = mFragmentManager.findFragmentByTag(PROGRESS_FRAGMENT_TAG);
        return dialog != null && dialog.isVisible();
    }

    public void shareAttachment() {
        if (mAttachment.contentUri == null) {
            return;
        }

        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);

        final Uri uri = Utils.normalizeUri(mAttachment.contentUri);
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        intent.setType(Utils.normalizeMimeType(mAttachment.getContentType()));

        try {
            mContext.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            // couldn't find activity for SEND intent
            LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e);
        }
    }

    public void shareAttachments(ArrayList<Parcelable> uris) {
        Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);

        intent.setType("image/*");
        intent.putParcelableArrayListExtra(
                Intent.EXTRA_STREAM, uris);

        try {
            mContext.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            // couldn't find activity for SEND_MULTIPLE intent
            LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e);
        }
    }

    public static void setOptionHandler(OptionHandler handler) {
        sOptionHandler = handler;
    }

    public boolean shouldShowExtraOption1(final String accountType, final String mimeType) {
        return (sOptionHandler != null) && sOptionHandler.shouldShowExtraOption1(
                accountType, mimeType);
    }

    public void handleOption1() {
        if (sOptionHandler == null) {
            return;
        }
        sOptionHandler.handleOption1(mContext, mAccount, mMessage, mAttachment, mFragmentManager);
    }

    /**
     * A default, no-op option class. Override this and set it globally with
     * {@link AttachmentActionHandler#setOptionHandler(OptionHandler)}.<br>
     * <br>
     * Subclasses of this type will live pretty much forever, so really, really try to avoid
     * keeping any state as member variables in them.
     */
    public static class OptionHandler {

        public boolean shouldShowExtraOption1(String accountType, String mimeType) {
            return false;
        }

        public void handleOption1(Context context, String account, Message message,
                Attachment attachment, FragmentManager fm) {
            // no-op
        }
    }
}