blob: 1cc729bfb38fd2957f9e675ed077ac6fa0c66570 [file] [log] [blame]
Andy Huang7bdc3752012-03-25 17:18:19 -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
18package com.android.mail.browse;
19
Paul Westbrook8081df42012-09-10 15:43:36 -070020import android.app.FragmentManager;
Andy Huang7bdc3752012-03-25 17:18:19 -070021import android.app.LoaderManager;
22import android.content.Context;
Andrew Sapperstein2fd167d2014-01-28 10:07:38 -080023import android.support.v4.text.BidiFormatter;
Andy Huangadbf3e82012-10-13 13:30:19 -070024import android.view.Gravity;
Andy Huang7bdc3752012-03-25 17:18:19 -070025import android.view.LayoutInflater;
26import android.view.View;
27import android.view.ViewGroup;
Andy Huang7bdc3752012-03-25 17:18:19 -070028import android.widget.BaseAdapter;
Andy Huang7bdc3752012-03-25 17:18:19 -070029
Tony Mantler821e5782014-01-06 15:33:43 -080030import com.android.emailcommon.mail.Address;
Andy Huangb8331b42012-07-16 19:08:53 -070031import com.android.mail.ContactInfoSource;
Andy Huang7bdc3752012-03-25 17:18:19 -070032import com.android.mail.FormattedDateBuilder;
33import com.android.mail.R;
34import com.android.mail.browse.ConversationViewHeader.ConversationViewHeaderCallbacks;
Andrew Sapperstein381c3222014-04-20 12:23:57 -070035import com.android.mail.browse.MessageFooterView.MessageFooterCallbacks;
Andy Huang7bdc3752012-03-25 17:18:19 -070036import com.android.mail.browse.MessageHeaderView.MessageHeaderViewCallbacks;
Andy Huang46dfba62012-04-19 01:47:32 -070037import com.android.mail.browse.SuperCollapsedBlock.OnClickListener;
Andy Huang7bdc3752012-03-25 17:18:19 -070038import com.android.mail.providers.Conversation;
Andy Huang7bdc3752012-03-25 17:18:19 -070039import com.android.mail.providers.UIProvider;
Paul Westbrook8081df42012-09-10 15:43:36 -070040import com.android.mail.ui.ControllableActivity;
Vikram Aggarwal69a6cdf2013-01-08 16:05:17 -080041import com.android.mail.utils.VeiledAddressMatcher;
Andy Huang014ea4c2012-09-25 14:50:54 -070042import com.google.common.base.Objects;
Andy Huangc7543572012-04-03 15:34:29 -070043import com.google.common.collect.Lists;
Andy Huang7bdc3752012-03-25 17:18:19 -070044
Andy Huang46dfba62012-04-19 01:47:32 -070045import java.util.Collection;
Andy Huang7bdc3752012-03-25 17:18:19 -070046import java.util.List;
Andy Huang65fe28f2012-04-06 18:08:53 -070047import java.util.Map;
Andy Huang7bdc3752012-03-25 17:18:19 -070048
49/**
50 * A specialized adapter that contains overlay views to draw on top of the underlying conversation
51 * WebView. Each independently drawn overlay view gets its own item in this adapter, and indices
52 * in this adapter do not necessarily line up with cursor indices. For example, an expanded
53 * message may have a header and footer, and since they are not drawn coupled together, they each
54 * get an adapter item.
55 * <p>
Andy Huang46dfba62012-04-19 01:47:32 -070056 * Each item in this adapter is a {@link ConversationOverlayItem} to expose enough information
57 * to {@link ConversationContainer} so that it can position overlays properly.
Andy Huang7bdc3752012-03-25 17:18:19 -070058 *
59 */
60public class ConversationViewAdapter extends BaseAdapter {
61
Martin Hibdonb7eac472013-12-06 17:40:00 -080062 private final Context mContext;
Andy Huang7bdc3752012-03-25 17:18:19 -070063 private final FormattedDateBuilder mDateBuilder;
Andy Huang28b7aee2012-08-20 20:27:32 -070064 private final ConversationAccountController mAccountController;
Andy Huang7bdc3752012-03-25 17:18:19 -070065 private final LoaderManager mLoaderManager;
Paul Westbrook8081df42012-09-10 15:43:36 -070066 private final FragmentManager mFragmentManager;
Andy Huang7bdc3752012-03-25 17:18:19 -070067 private final MessageHeaderViewCallbacks mMessageCallbacks;
Andrew Sapperstein381c3222014-04-20 12:23:57 -070068 private final MessageFooterCallbacks mFooterCallbacks;
Andy Huangb8331b42012-07-16 19:08:53 -070069 private final ContactInfoSource mContactInfoSource;
Martin Hibdonb7eac472013-12-06 17:40:00 -080070 private final ConversationViewHeaderCallbacks mConversationCallbacks;
71 private final OnClickListener mSuperCollapsedListener;
72 private final Map<String, Address> mAddressCache;
Andy Huang7bdc3752012-03-25 17:18:19 -070073 private final LayoutInflater mInflater;
74
Andy Huang46dfba62012-04-19 01:47:32 -070075 private final List<ConversationOverlayItem> mItems;
Vikram Aggarwal69a6cdf2013-01-08 16:05:17 -080076 private final VeiledAddressMatcher mMatcher;
Andy Huang7bdc3752012-03-25 17:18:19 -070077
78 public static final int VIEW_TYPE_CONVERSATION_HEADER = 0;
Andrew Sapperstein98f6e222013-08-28 16:49:44 -070079 public static final int VIEW_TYPE_MESSAGE_HEADER = 1;
80 public static final int VIEW_TYPE_MESSAGE_FOOTER = 2;
81 public static final int VIEW_TYPE_SUPER_COLLAPSED_BLOCK = 3;
82 public static final int VIEW_TYPE_BORDER = 4;
83 public static final int VIEW_TYPE_AD_HEADER = 5;
84 public static final int VIEW_TYPE_AD_SENDER_HEADER = 6;
Andrew Sappersteina467d402013-10-15 18:45:03 -070085 public static final int VIEW_TYPE_COUNT = 7;
Andy Huang7bdc3752012-03-25 17:18:19 -070086
Andrew Sapperstein2fd167d2014-01-28 10:07:38 -080087 private final BidiFormatter mBidiFormatter;
88
Andy Huang46dfba62012-04-19 01:47:32 -070089 public class ConversationHeaderItem extends ConversationOverlayItem {
Andy Huang7bdc3752012-03-25 17:18:19 -070090 public final Conversation mConversation;
91
92 private ConversationHeaderItem(Conversation conv) {
93 mConversation = conv;
94 }
95
96 @Override
97 public int getType() {
98 return VIEW_TYPE_CONVERSATION_HEADER;
99 }
100
101 @Override
102 public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
103 final ConversationViewHeader headerView = (ConversationViewHeader) inflater.inflate(
104 R.layout.conversation_view_header, parent, false);
Andy Huang28b7aee2012-08-20 20:27:32 -0700105 headerView.setCallbacks(mConversationCallbacks, mAccountController);
Mark Weiab2d9982012-09-25 13:06:17 -0700106 headerView.bind(this);
Andrew Sappersteine6bf30d2014-03-13 19:19:26 -0700107 headerView.setSubject(mConversation.subject);
Andy Huang28b7aee2012-08-20 20:27:32 -0700108 if (mAccountController.getAccount().supportsCapability(
Andy Huang7bdc3752012-03-25 17:18:19 -0700109 UIProvider.AccountCapabilities.MULTIPLE_FOLDERS_PER_CONV)) {
Andy Huang7388dba2012-09-25 18:30:28 -0700110 headerView.setFolders(mConversation);
Andy Huang7bdc3752012-03-25 17:18:19 -0700111 }
112
113 return headerView;
114 }
115
116 @Override
Andy Huangb8331b42012-07-16 19:08:53 -0700117 public void bindView(View v, boolean measureOnly) {
Mark Weiab2d9982012-09-25 13:06:17 -0700118 ConversationViewHeader header = (ConversationViewHeader) v;
119 header.bind(this);
Andy Huang7bdc3752012-03-25 17:18:19 -0700120 }
121
122 @Override
Andy Huang7bdc3752012-03-25 17:18:19 -0700123 public boolean isContiguous() {
124 return true;
125 }
126
127 }
128
Andrew Sapperstein4ddda2f2013-06-10 11:15:38 -0700129 public static class MessageHeaderItem extends ConversationOverlayItem {
130
131 private final ConversationViewAdapter mAdapter;
132
Andy Huang014ea4c2012-09-25 14:50:54 -0700133 private ConversationMessage mMessage;
Andy Huang65fe28f2012-04-06 18:08:53 -0700134
135 // view state variables
Andy Huangc7543572012-04-03 15:34:29 -0700136 private boolean mExpanded;
137 public boolean detailsExpanded;
Scott Kennedy20273842012-11-07 11:16:21 -0800138 private boolean mShowImages;
Andy Huang7bdc3752012-03-25 17:18:19 -0700139
Andy Huang65fe28f2012-04-06 18:08:53 -0700140 // cached values to speed up re-rendering during view recycling
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700141 private CharSequence mTimestampShort;
142 private CharSequence mTimestampLong;
Martin Hibdonb7eac472013-12-06 17:40:00 -0800143 private CharSequence mTimestampFull;
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700144 private long mTimestampMs;
Martin Hibdonb7eac472013-12-06 17:40:00 -0800145 private final FormattedDateBuilder mDateBuilder;
Andy Huang65fe28f2012-04-06 18:08:53 -0700146 public CharSequence recipientSummaryText;
147
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700148 MessageHeaderItem(ConversationViewAdapter adapter, FormattedDateBuilder dateBuilder,
149 ConversationMessage message, boolean expanded, boolean showImages) {
Andrew Sapperstein4ddda2f2013-06-10 11:15:38 -0700150 mAdapter = adapter;
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700151 mDateBuilder = dateBuilder;
Andy Huang014ea4c2012-09-25 14:50:54 -0700152 mMessage = message;
Andy Huangc7543572012-04-03 15:34:29 -0700153 mExpanded = expanded;
Scott Kennedy20273842012-11-07 11:16:21 -0800154 mShowImages = showImages;
Andy Huangc7543572012-04-03 15:34:29 -0700155
156 detailsExpanded = false;
Andy Huang7bdc3752012-03-25 17:18:19 -0700157 }
158
Andy Huang014ea4c2012-09-25 14:50:54 -0700159 public ConversationMessage getMessage() {
160 return mMessage;
161 }
162
Andy Huang7bdc3752012-03-25 17:18:19 -0700163 @Override
164 public int getType() {
165 return VIEW_TYPE_MESSAGE_HEADER;
166 }
167
168 @Override
169 public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
170 final MessageHeaderView v = (MessageHeaderView) inflater.inflate(
171 R.layout.conversation_message_header, parent, false);
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700172 v.initialize(mAdapter.mAccountController,
Andrew Sapperstein4ddda2f2013-06-10 11:15:38 -0700173 mAdapter.mAddressCache);
174 v.setCallbacks(mAdapter.mMessageCallbacks);
175 v.setContactInfoSource(mAdapter.mContactInfoSource);
176 v.setVeiledMatcher(mAdapter.mMatcher);
Andy Huang7bdc3752012-03-25 17:18:19 -0700177 return v;
178 }
179
180 @Override
Andy Huangb8331b42012-07-16 19:08:53 -0700181 public void bindView(View v, boolean measureOnly) {
Andy Huang7bdc3752012-03-25 17:18:19 -0700182 final MessageHeaderView header = (MessageHeaderView) v;
Andy Huang28b7aee2012-08-20 20:27:32 -0700183 header.bind(this, measureOnly);
Andy Huang7bdc3752012-03-25 17:18:19 -0700184 }
185
186 @Override
Andy Huang6b3d0d92012-10-30 15:46:48 -0700187 public void onModelUpdated(View v) {
188 final MessageHeaderView header = (MessageHeaderView) v;
189 header.refresh();
190 }
191
192 @Override
Andy Huang7bdc3752012-03-25 17:18:19 -0700193 public boolean isContiguous() {
Andy Huangc7543572012-04-03 15:34:29 -0700194 return !isExpanded();
195 }
196
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700197 @Override
Andy Huangc7543572012-04-03 15:34:29 -0700198 public boolean isExpanded() {
199 return mExpanded;
200 }
201
202 public void setExpanded(boolean expanded) {
203 if (mExpanded != expanded) {
204 mExpanded = expanded;
205 }
Andy Huang7bdc3752012-03-25 17:18:19 -0700206 }
Andy Huang59e0b182012-08-14 14:32:23 -0700207
Scott Kennedy20273842012-11-07 11:16:21 -0800208 public boolean getShowImages() {
209 return mShowImages;
210 }
211
212 public void setShowImages(boolean showImages) {
213 mShowImages = showImages;
214 }
215
Andy Huang59e0b182012-08-14 14:32:23 -0700216 @Override
217 public boolean canBecomeSnapHeader() {
218 return isExpanded();
219 }
220
221 @Override
222 public boolean canPushSnapHeader() {
223 return true;
224 }
225
Andy Huang014ea4c2012-09-25 14:50:54 -0700226 @Override
227 public boolean belongsToMessage(ConversationMessage message) {
228 return Objects.equal(mMessage, message);
229 }
230
231 @Override
232 public void setMessage(ConversationMessage message) {
233 mMessage = message;
234 }
235
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700236 public CharSequence getTimestampShort() {
237 ensureTimestamps();
238 return mTimestampShort;
239 }
240
241 public CharSequence getTimestampLong() {
242 ensureTimestamps();
243 return mTimestampLong;
244 }
245
Martin Hibdonb7eac472013-12-06 17:40:00 -0800246 public CharSequence getTimestampFull() {
247 ensureTimestamps();
248 return mTimestampFull;
249 }
250
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700251 private void ensureTimestamps() {
252 if (mMessage.dateReceivedMs != mTimestampMs) {
253 mTimestampMs = mMessage.dateReceivedMs;
Martin Hibdonb7eac472013-12-06 17:40:00 -0800254 mTimestampShort = mDateBuilder.formatShortDateTime(mTimestampMs);
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700255 mTimestampLong = mDateBuilder.formatLongDateTime(mTimestampMs);
Martin Hibdonb7eac472013-12-06 17:40:00 -0800256 mTimestampFull = mDateBuilder.formatFullDateTime(mTimestampMs);
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700257 }
258 }
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700259
260 public ConversationViewAdapter getAdapter() {
261 return mAdapter;
262 }
Andrew Sapperstein968e0142013-08-21 17:58:01 -0700263
264 @Override
265 public void rebindView(View view) {
266 final MessageHeaderView header = (MessageHeaderView) view;
267 header.rebind(this);
268 }
Andy Huang7bdc3752012-03-25 17:18:19 -0700269 }
270
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700271 public static class MessageFooterItem extends ConversationOverlayItem implements
272 AttachmentActionHandler.AboveAttachmentLayoutDismissedListener {
273 private final ConversationViewAdapter mAdapter;
274
Andy Huang7bdc3752012-03-25 17:18:19 -0700275 /**
276 * A footer can only exist if there is a matching header. Requiring a header allows a
277 * footer to stay in sync with the expanded state of the header.
278 */
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700279 private final MessageHeaderItem mHeaderItem;
Andy Huang7bdc3752012-03-25 17:18:19 -0700280
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700281 private MessageFooterItem(ConversationViewAdapter adapter, MessageHeaderItem item) {
282 mAdapter = adapter;
283 mHeaderItem = item;
Andy Huang7bdc3752012-03-25 17:18:19 -0700284 }
285
286 @Override
287 public int getType() {
288 return VIEW_TYPE_MESSAGE_FOOTER;
289 }
290
291 @Override
292 public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
Andy Huangf0e95c32012-04-02 18:11:17 -0700293 final MessageFooterView v = (MessageFooterView) inflater.inflate(
294 R.layout.conversation_message_footer, parent, false);
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700295 v.initialize(mAdapter.mLoaderManager, mAdapter.mFragmentManager,
296 mAdapter.mAccountController, mAdapter.mFooterCallbacks);
Andy Huangf0e95c32012-04-02 18:11:17 -0700297 return v;
Andy Huang7bdc3752012-03-25 17:18:19 -0700298 }
299
300 @Override
Andy Huangb8331b42012-07-16 19:08:53 -0700301 public void bindView(View v, boolean measureOnly) {
Andy Huangf0e95c32012-04-02 18:11:17 -0700302 final MessageFooterView attachmentsView = (MessageFooterView) v;
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700303 attachmentsView.bind(mHeaderItem, this, measureOnly);
Andy Huang7bdc3752012-03-25 17:18:19 -0700304 }
305
306 @Override
307 public boolean isContiguous() {
308 return true;
309 }
Andy Huangc7543572012-04-03 15:34:29 -0700310
311 @Override
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700312 public boolean isExpanded() {
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700313 return mHeaderItem.isExpanded();
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700314 }
315
316 @Override
Andy Huangadbf3e82012-10-13 13:30:19 -0700317 public int getGravity() {
318 // attachments are top-aligned within their spacer area
319 // Attachments should stay near the body they belong to, even when zoomed far in.
320 return Gravity.TOP;
321 }
322
323 @Override
Andy Huangc7543572012-04-03 15:34:29 -0700324 public int getHeight() {
325 // a footer may change height while its view does not exist because it is offscreen
326 // (but the header is onscreen and thus collapsible)
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700327 if (!mHeaderItem.isExpanded()) {
Andy Huangc7543572012-04-03 15:34:29 -0700328 return 0;
329 }
330 return super.getHeight();
331 }
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700332
333 public MessageHeaderItem getHeaderItem() {
334 return mHeaderItem;
335 }
336
337 @Override
338 public void onOtherLayoutDismissed() {
339 final MessageFooterView view = mAdapter.mFooterCallbacks.getViewForItem(this);
340
341 // the item has a view, use the normal path
342 if (view != null) {
343 view.collapseAboveBarAttachmentsView();
344 return;
345 }
346
347 // the item is offscreen or otherwise doesn't have a view
348 // just update the HTML
349 final int newHeight = mAdapter.mFooterCallbacks.getUpdatedHeight(this);
350 setHeight(newHeight);
351 mAdapter.mFooterCallbacks.setMessageSpacerHeight(this, newHeight);
352 }
Andy Huang7bdc3752012-03-25 17:18:19 -0700353 }
354
Andy Huang46dfba62012-04-19 01:47:32 -0700355 public class SuperCollapsedBlockItem extends ConversationOverlayItem {
356
357 private final int mStart;
358 private int mEnd;
359
360 private SuperCollapsedBlockItem(int start, int end) {
361 mStart = start;
362 mEnd = end;
363 }
364
365 @Override
366 public int getType() {
367 return VIEW_TYPE_SUPER_COLLAPSED_BLOCK;
368 }
369
370 @Override
371 public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
372 final SuperCollapsedBlock scb = (SuperCollapsedBlock) inflater.inflate(
373 R.layout.super_collapsed_block, parent, false);
374 scb.initialize(mSuperCollapsedListener);
375 return scb;
376 }
377
378 @Override
Andy Huangb8331b42012-07-16 19:08:53 -0700379 public void bindView(View v, boolean measureOnly) {
Andy Huang46dfba62012-04-19 01:47:32 -0700380 final SuperCollapsedBlock scb = (SuperCollapsedBlock) v;
381 scb.bind(this);
382 }
383
384 @Override
385 public boolean isContiguous() {
386 return true;
387 }
388
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700389 @Override
390 public boolean isExpanded() {
391 return false;
392 }
393
Andy Huang46dfba62012-04-19 01:47:32 -0700394 public int getStart() {
395 return mStart;
396 }
397
398 public int getEnd() {
399 return mEnd;
400 }
Andy Huang59e0b182012-08-14 14:32:23 -0700401
402 @Override
403 public boolean canPushSnapHeader() {
404 return true;
405 }
Andy Huang46dfba62012-04-19 01:47:32 -0700406 }
407
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700408
409 public class BorderItem extends ConversationOverlayItem {
Andrew Sapperstein12c03aa2013-07-25 17:15:22 -0700410 private final boolean mContiguous;
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700411 private boolean mExpanded;
Andrew Sappersteine5398802013-07-29 20:55:38 -0700412 private final boolean mFirstBorder;
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700413 private boolean mLastBorder;
Andrew Sapperstein12c03aa2013-07-25 17:15:22 -0700414
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700415 public BorderItem(boolean contiguous, boolean isExpanded,
416 boolean firstBorder, boolean lastBorder) {
Andrew Sapperstein12c03aa2013-07-25 17:15:22 -0700417 mContiguous = contiguous;
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700418 mExpanded = isExpanded;
Andrew Sappersteine5398802013-07-29 20:55:38 -0700419 mFirstBorder = firstBorder;
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700420 mLastBorder = lastBorder;
Andrew Sapperstein12c03aa2013-07-25 17:15:22 -0700421 }
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700422
423 @Override
424 public int getType() {
425 return VIEW_TYPE_BORDER;
426 }
427
428 @Override
429 public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
430 return inflater.inflate(R.layout.card_border, parent, false);
431 }
432
433 @Override
434 public void bindView(View v, boolean measureOnly) {
Andrew Sappersteine5398802013-07-29 20:55:38 -0700435 final BorderView border = (BorderView) v;
436 border.bind(this, measureOnly);
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700437 }
438
439 @Override
440 public boolean isContiguous() {
Andrew Sapperstein12c03aa2013-07-25 17:15:22 -0700441 return mContiguous;
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700442 }
443
444 @Override
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700445 public boolean isExpanded() {
446 return mExpanded;
447 }
448
449 public void setExpanded(boolean isExpanded) {
450 mExpanded = isExpanded;
451 }
452
453 @Override
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700454 public boolean canPushSnapHeader() {
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700455 return false;
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700456 }
Andrew Sappersteine5398802013-07-29 20:55:38 -0700457
458 public boolean isFirstBorder() {
459 return mFirstBorder;
460 }
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700461
462 public boolean isLastBorder() {
463 return mLastBorder;
464 }
465
466 public void setIsLastBorder(boolean isLastBorder) {
467 mLastBorder = isLastBorder;
468 }
469
470 public ConversationViewAdapter getAdapter() {
471 return ConversationViewAdapter.this;
472 }
473
474 @Override
475 public void rebindView(View view) {
476 bindView(view, false);
477 }
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700478 }
479
Paul Westbrook8081df42012-09-10 15:43:36 -0700480 public ConversationViewAdapter(ControllableActivity controllableActivity,
Andy Huang28b7aee2012-08-20 20:27:32 -0700481 ConversationAccountController accountController,
482 LoaderManager loaderManager,
Andy Huang7bdc3752012-03-25 17:18:19 -0700483 MessageHeaderViewCallbacks messageCallbacks,
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700484 MessageFooterCallbacks footerCallbacks,
Andy Huangb8331b42012-07-16 19:08:53 -0700485 ContactInfoSource contactInfoSource,
Andy Huang46dfba62012-04-19 01:47:32 -0700486 ConversationViewHeaderCallbacks convCallbacks,
Andy Huang59e0b182012-08-14 14:32:23 -0700487 SuperCollapsedBlock.OnClickListener scbListener, Map<String, Address> addressCache,
Andrew Sapperstein2fd167d2014-01-28 10:07:38 -0800488 FormattedDateBuilder dateBuilder, BidiFormatter bidiFormatter) {
Paul Westbrook8081df42012-09-10 15:43:36 -0700489 mContext = controllableActivity.getActivityContext();
Andy Huang59e0b182012-08-14 14:32:23 -0700490 mDateBuilder = dateBuilder;
Andy Huang28b7aee2012-08-20 20:27:32 -0700491 mAccountController = accountController;
Andy Huang7bdc3752012-03-25 17:18:19 -0700492 mLoaderManager = loaderManager;
Paul Westbrook8081df42012-09-10 15:43:36 -0700493 mFragmentManager = controllableActivity.getFragmentManager();
Andy Huang7bdc3752012-03-25 17:18:19 -0700494 mMessageCallbacks = messageCallbacks;
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700495 mFooterCallbacks = footerCallbacks;
Andy Huangb8331b42012-07-16 19:08:53 -0700496 mContactInfoSource = contactInfoSource;
Andy Huang7bdc3752012-03-25 17:18:19 -0700497 mConversationCallbacks = convCallbacks;
Andy Huang46dfba62012-04-19 01:47:32 -0700498 mSuperCollapsedListener = scbListener;
Andy Huang65fe28f2012-04-06 18:08:53 -0700499 mAddressCache = addressCache;
Paul Westbrook8081df42012-09-10 15:43:36 -0700500 mInflater = LayoutInflater.from(mContext);
Andy Huang7bdc3752012-03-25 17:18:19 -0700501
502 mItems = Lists.newArrayList();
Vikram Aggarwal69a6cdf2013-01-08 16:05:17 -0800503 mMatcher = controllableActivity.getAccountController().getVeiledAddressMatcher();
Andrew Sapperstein2fd167d2014-01-28 10:07:38 -0800504
505 mBidiFormatter = bidiFormatter;
Andy Huang7bdc3752012-03-25 17:18:19 -0700506 }
507
508 @Override
509 public int getCount() {
510 return mItems.size();
511 }
512
513 @Override
514 public int getItemViewType(int position) {
515 return mItems.get(position).getType();
516 }
517
518 @Override
519 public int getViewTypeCount() {
520 return VIEW_TYPE_COUNT;
521 }
522
523 @Override
Andy Huang46dfba62012-04-19 01:47:32 -0700524 public ConversationOverlayItem getItem(int position) {
Andy Huang7bdc3752012-03-25 17:18:19 -0700525 return mItems.get(position);
526 }
527
528 @Override
529 public long getItemId(int position) {
530 return position; // TODO: ensure this works well enough
531 }
532
533 @Override
534 public View getView(int position, View convertView, ViewGroup parent) {
Andy Huangb8331b42012-07-16 19:08:53 -0700535 return getView(getItem(position), convertView, parent, false /* measureOnly */);
Andy Huang46dfba62012-04-19 01:47:32 -0700536 }
537
Andy Huangb8331b42012-07-16 19:08:53 -0700538 public View getView(ConversationOverlayItem item, View convertView, ViewGroup parent,
539 boolean measureOnly) {
Andy Huang7bdc3752012-03-25 17:18:19 -0700540 final View v;
Andy Huang7bdc3752012-03-25 17:18:19 -0700541
542 if (convertView == null) {
543 v = item.createView(mContext, mInflater, parent);
544 } else {
545 v = convertView;
546 }
Andy Huangb8331b42012-07-16 19:08:53 -0700547 item.bindView(v, measureOnly);
Andy Huang7bdc3752012-03-25 17:18:19 -0700548
549 return v;
550 }
551
Andrew Sapperstein888388c2013-08-01 22:51:37 -0700552 public LayoutInflater getLayoutInflater() {
553 return mInflater;
554 }
555
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700556 public FormattedDateBuilder getDateBuilder() {
557 return mDateBuilder;
558 }
559
Andy Huang46dfba62012-04-19 01:47:32 -0700560 public int addItem(ConversationOverlayItem item) {
Andy Huang7bdc3752012-03-25 17:18:19 -0700561 final int pos = mItems.size();
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700562 item.setPosition(pos);
Andy Huang7bdc3752012-03-25 17:18:19 -0700563 mItems.add(item);
Andy Huang7bdc3752012-03-25 17:18:19 -0700564 return pos;
565 }
566
567 public void clear() {
568 mItems.clear();
Andy Huang6cb004b2012-10-26 15:37:32 -0700569 notifyDataSetChanged();
Andy Huang7bdc3752012-03-25 17:18:19 -0700570 }
571
572 public int addConversationHeader(Conversation conv) {
573 return addItem(new ConversationHeaderItem(conv));
574 }
575
Scott Kennedy20273842012-11-07 11:16:21 -0800576 public int addMessageHeader(ConversationMessage msg, boolean expanded, boolean showImages) {
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700577 return addItem(new MessageHeaderItem(this, mDateBuilder, msg, expanded, showImages));
Andy Huang7bdc3752012-03-25 17:18:19 -0700578 }
579
580 public int addMessageFooter(MessageHeaderItem headerItem) {
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700581 return addItem(new MessageFooterItem(this, headerItem));
Andy Huang7bdc3752012-03-25 17:18:19 -0700582 }
583
Andrew Sapperstein4ddda2f2013-06-10 11:15:38 -0700584 public static MessageHeaderItem newMessageHeaderItem(ConversationViewAdapter adapter,
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700585 FormattedDateBuilder dateBuilder, ConversationMessage message,
586 boolean expanded, boolean showImages) {
587 return new MessageHeaderItem(adapter, dateBuilder, message, expanded, showImages);
Andy Huang46dfba62012-04-19 01:47:32 -0700588 }
589
Andrew Sapperstein381c3222014-04-20 12:23:57 -0700590 public static MessageFooterItem newMessageFooterItem(
591 ConversationViewAdapter adapter, MessageHeaderItem headerItem) {
592 return new MessageFooterItem(adapter, headerItem);
Andy Huang46dfba62012-04-19 01:47:32 -0700593 }
594
595 public int addSuperCollapsedBlock(int start, int end) {
596 return addItem(new SuperCollapsedBlockItem(start, end));
597 }
598
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700599 public int addBorder(
600 boolean contiguous, boolean expanded, boolean firstBorder, boolean lastBorder) {
601 return addItem(new BorderItem(contiguous, expanded, firstBorder, lastBorder));
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700602 }
603
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700604 public BorderItem newBorderItem(boolean contiguous, boolean expanded) {
605 return new BorderItem(
606 contiguous, expanded, false /* firstBorder */, false /* lastBorder */);
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700607 }
608
Andy Huang46dfba62012-04-19 01:47:32 -0700609 public void replaceSuperCollapsedBlock(SuperCollapsedBlockItem blockToRemove,
610 Collection<ConversationOverlayItem> replacements) {
611 final int pos = mItems.indexOf(blockToRemove);
612 if (pos == -1) {
613 return;
614 }
615
616 mItems.remove(pos);
617 mItems.addAll(pos, replacements);
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700618
619 // update position for all items
620 for (int i = 0, size = mItems.size(); i < size; i++) {
621 mItems.get(i).setPosition(i);
622 }
Andy Huang46dfba62012-04-19 01:47:32 -0700623 }
624
Andy Huang6b3d0d92012-10-30 15:46:48 -0700625 public void updateItemsForMessage(ConversationMessage message,
626 List<Integer> affectedPositions) {
627 for (int i = 0, len = mItems.size(); i < len; i++) {
628 final ConversationOverlayItem item = mItems.get(i);
Andy Huang014ea4c2012-09-25 14:50:54 -0700629 if (item.belongsToMessage(message)) {
630 item.setMessage(message);
Andy Huang6b3d0d92012-10-30 15:46:48 -0700631 affectedPositions.add(i);
Andy Huang014ea4c2012-09-25 14:50:54 -0700632 }
633 }
Andy Huang014ea4c2012-09-25 14:50:54 -0700634 }
Andrew Sapperstein2fd167d2014-01-28 10:07:38 -0800635
636 public BidiFormatter getBidiFormatter() {
637 return mBidiFormatter;
638 }
Andy Huang7bdc3752012-03-25 17:18:19 -0700639}