Home | History | Annotate | Download | only in browse
      1 /*
      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 
     18 package com.android.mail.browse;
     19 
     20 import android.app.FragmentManager;
     21 import android.content.ActivityNotFoundException;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.graphics.Bitmap;
     25 import android.net.Uri;
     26 import android.util.AttributeSet;
     27 import android.view.LayoutInflater;
     28 import android.view.View;
     29 import android.view.View.OnClickListener;
     30 import android.view.ViewGroup;
     31 import android.view.ViewParent;
     32 
     33 import com.android.ex.photo.util.ImageUtils;
     34 import com.android.mail.R;
     35 import com.android.mail.analytics.Analytics;
     36 import com.android.mail.photo.MailPhotoViewActivity;
     37 import com.android.mail.providers.Attachment;
     38 import com.android.mail.providers.UIProvider;
     39 import com.android.mail.providers.UIProvider.AttachmentDestination;
     40 import com.android.mail.providers.UIProvider.AttachmentRendition;
     41 import com.android.mail.ui.AttachmentTile;
     42 import com.android.mail.ui.AttachmentTileGrid;
     43 import com.android.mail.utils.AttachmentUtils;
     44 import com.android.mail.utils.LogTag;
     45 import com.android.mail.utils.LogUtils;
     46 import com.android.mail.utils.Utils;
     47 
     48 import java.util.Comparator;
     49 import java.util.PriorityQueue;
     50 
     51 /**
     52  * View for a single attachment in conversation view. Shows download status and allows launching
     53  * intents to act on an attachment.
     54  *
     55  */
     56 public class MessageAttachmentTile extends AttachmentTile implements OnClickListener,
     57         AttachmentViewInterface {
     58 
     59     private int mPhotoIndex;
     60     private Uri mAttachmentsListUri;
     61     private View mTextContainer;
     62 
     63     private final AttachmentActionHandler mActionHandler;
     64 
     65     private static final String LOG_TAG = LogTag.getLogTag();
     66 
     67     public MessageAttachmentTile(Context context) {
     68         this(context, null);
     69     }
     70 
     71     public MessageAttachmentTile(Context context, AttributeSet attrs) {
     72         super(context, attrs);
     73 
     74         mActionHandler = new AttachmentActionHandler(context, this);
     75     }
     76 
     77     public void initialize(FragmentManager fragmentManager) {
     78         mActionHandler.initialize(fragmentManager);
     79     }
     80 
     81     /**
     82      * Render or update an attachment's view. This happens immediately upon instantiation, and
     83      * repeatedly as status updates stream in, so only properties with new or changed values will
     84      * cause sub-views to update.
     85      */
     86     @Override
     87     public void render(Attachment attachment, Uri attachmentsListUri, int index,
     88             AttachmentPreviewCache attachmentPreviewCache, boolean loaderResult) {
     89         super.render(attachment, attachmentsListUri, index, attachmentPreviewCache, loaderResult);
     90 
     91         mAttachmentsListUri = attachmentsListUri;
     92         mPhotoIndex = index;
     93 
     94         mActionHandler.setAttachment(mAttachment);
     95         mActionHandler.updateStatus(loaderResult);
     96     }
     97 
     98     public static MessageAttachmentTile inflate(LayoutInflater inflater, ViewGroup parent) {
     99         MessageAttachmentTile view = (MessageAttachmentTile) inflater.inflate(
    100                 R.layout.conversation_message_attachment_tile, parent, false);
    101         return view;
    102     }
    103 
    104 
    105     @Override
    106     protected void onFinishInflate() {
    107         super.onFinishInflate();
    108 
    109         mTextContainer = findViewById(R.id.attachment_tile_text_container);
    110 
    111         setOnClickListener(this);
    112     }
    113 
    114     @Override
    115     public void onClick(View v) {
    116         onClick();
    117     }
    118 
    119     private boolean onClick() {
    120         showAndDownloadAttachments();
    121         return true;
    122     }
    123 
    124     private void showAndDownloadAttachments() {
    125         AttachmentTileGrid tileGrid = ((AttachmentTileGrid) getParent());
    126         int childCount = tileGrid.getChildCount();
    127 
    128         PriorityQueue<MessageAttachmentTile> queue = new PriorityQueue<MessageAttachmentTile>(
    129                 childCount, new ViewIndexDistanceComparator(mPhotoIndex));
    130         for (int i = 0; i < childCount; i++) {
    131             MessageAttachmentTile tile = (MessageAttachmentTile) tileGrid.getChildAt(i);
    132             queue.add(tile);
    133         }
    134 
    135         // we want our downloads to have higher priority than the highest background downloads
    136         int maxAdditionalPriority = childCount;
    137         for (int i = 0; i < childCount; i++) {
    138             // higher priority tiles are returned first
    139             MessageAttachmentTile tile = queue.remove();
    140             tile.downloadAttachment(maxAdditionalPriority - i, i != 0);
    141         }
    142 
    143         viewAttachment();
    144     }
    145 
    146     public void downloadAttachment(int additionalPriority, boolean delayDownload) {
    147         if (!mAttachment.isPresentLocally()) {
    148             mActionHandler.startDownloadingAttachment(AttachmentDestination.CACHE,
    149                     UIProvider.AttachmentRendition.BEST, additionalPriority, delayDownload);
    150         }
    151     }
    152 
    153     @Override
    154     public void viewAttachment() {
    155         final String mime = Utils.normalizeMimeType(mAttachment.getContentType());
    156 
    157         Analytics.getInstance()
    158                 .sendEvent("view_attachment", mime, "attachment_tile", mAttachment.size);
    159 
    160         if (ImageUtils.isImageMimeType(mime)) {
    161             MailPhotoViewActivity
    162                     .startMailPhotoViewActivity(getContext(), mAttachmentsListUri, mPhotoIndex);
    163             return;
    164         }
    165 
    166         Intent intent = new Intent(Intent.ACTION_VIEW);
    167         intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
    168                 | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
    169         Utils.setIntentDataAndTypeAndNormalize(
    170                 intent, mAttachment.contentUri, mime);
    171         try {
    172             getContext().startActivity(intent);
    173         } catch (ActivityNotFoundException e) {
    174             // couldn't find activity for View intent
    175             LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e);
    176         }
    177     }
    178 
    179     @Override
    180     public void updateProgress(boolean showDeterminateProgress) {
    181         // do not show progress for image tiles
    182     }
    183 
    184     @Override
    185     public void onUpdateStatus() {
    186     }
    187 
    188     @Override
    189     public void setThumbnailToDefault() {
    190         super.setThumbnailToDefault();
    191         mTextContainer.setVisibility(VISIBLE);
    192     }
    193 
    194     @Override
    195     public void setThumbnail(Bitmap result) {
    196         super.setThumbnail(result);
    197         mTextContainer.setVisibility(GONE);
    198     }
    199 
    200     @Override
    201     public void thumbnailLoadFailed() {
    202         super.thumbnailLoadFailed();
    203 
    204         if (AttachmentUtils.canDownloadAttachment(getContext(), null)) {
    205             // Download if there is network. This check prevents the attachment
    206             // download from failing and making the error toast show
    207             mActionHandler.startDownloadingAttachment(
    208                     AttachmentDestination.CACHE, AttachmentRendition.SIMPLE, 0, false);
    209         }
    210     }
    211 
    212     /**
    213      * Given two child views, figure out whose index is closest to the specified
    214      * index.
    215      */
    216     public static class ViewIndexDistanceComparator implements Comparator<View>{
    217         final private int mIndex;
    218         /**
    219          * @param index Compare based on each view's distance to this index
    220          */
    221         public ViewIndexDistanceComparator(int index) {
    222             mIndex = index;
    223         }
    224 
    225         @Override
    226         public int compare(View lhs, View rhs) {
    227             ViewParent parent = lhs.getParent();
    228             if (parent == rhs.getParent()) {
    229                 if (parent instanceof ViewGroup) {
    230                     ViewGroup p = (ViewGroup) parent;
    231                     int lhsIndex = p.indexOfChild(lhs);
    232                     int rhsIndex = p.indexOfChild(rhs);
    233                     int lhsDistance = Math.abs(mIndex - lhsIndex);
    234                     int rhsDistance = Math.abs(mIndex - rhsIndex);
    235                     // prefer shorter distance since they are the next ones to be swiped to
    236                     int result = lhsDistance - rhsDistance;
    237                     if (result == 0) {
    238                         // prefer higher index since they are to the right in the photoviewer
    239                         return rhsIndex - lhsIndex;
    240                     }
    241                     return result;
    242                 }
    243             }
    244             return 0;
    245         }
    246     }
    247 }
    248