MessageAttachmentTile.java revision e003b4cc4a23e6d394998bebe26430a361c5ac29
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 18package com.android.mail.browse; 19 20import android.app.FragmentManager; 21import android.content.ActivityNotFoundException; 22import android.content.Context; 23import android.content.Intent; 24import android.graphics.Bitmap; 25import android.net.Uri; 26import android.util.AttributeSet; 27import android.view.LayoutInflater; 28import android.view.View; 29import android.view.View.OnClickListener; 30import android.view.ViewGroup; 31import android.view.ViewParent; 32 33import com.android.ex.photo.util.ImageUtils; 34import com.android.mail.R; 35import com.android.mail.analytics.Analytics; 36import com.android.mail.photo.MailPhotoViewActivity; 37import com.android.mail.providers.Attachment; 38import com.android.mail.providers.UIProvider; 39import com.android.mail.providers.UIProvider.AttachmentDestination; 40import com.android.mail.providers.UIProvider.AttachmentRendition; 41import com.android.mail.ui.AttachmentTile; 42import com.android.mail.ui.AttachmentTileGrid; 43import com.android.mail.utils.AttachmentUtils; 44import com.android.mail.utils.LogTag; 45import com.android.mail.utils.LogUtils; 46import com.android.mail.utils.Utils; 47 48import java.util.Comparator; 49import 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 */ 56public 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