1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.messaging.datamodel.data; 18 19 import android.database.Cursor; 20 import android.net.Uri; 21 import android.provider.BaseColumns; 22 import android.text.TextUtils; 23 24 import com.android.messaging.datamodel.DatabaseHelper; 25 import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns; 26 import com.android.messaging.datamodel.DatabaseHelper.MessageColumns; 27 import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns; 28 import com.android.messaging.datamodel.DatabaseWrapper; 29 import com.android.messaging.datamodel.action.DeleteConversationAction; 30 import com.android.messaging.util.Assert; 31 import com.android.messaging.util.ContactUtil; 32 import com.android.messaging.util.Dates; 33 import com.google.common.base.Joiner; 34 35 import java.util.ArrayList; 36 import java.util.List; 37 38 /** 39 * Class wrapping the conversation list view used to display each item in conversation list 40 */ 41 public class ConversationListItemData { 42 private String mConversationId; 43 private String mName; 44 private String mIcon; 45 private boolean mIsRead; 46 private long mTimestamp; 47 private String mSnippetText; 48 private Uri mPreviewUri; 49 private String mPreviewContentType; 50 private long mParticipantContactId; 51 private String mParticipantLookupKey; 52 private String mOtherParticipantNormalizedDestination; 53 private String mSelfId; 54 private int mParticipantCount; 55 private boolean mNotificationEnabled; 56 private String mNotificationSoundUri; 57 private boolean mNotificationVibrate; 58 private boolean mIncludeEmailAddress; 59 private int mMessageStatus; 60 private int mMessageRawTelephonyStatus; 61 private boolean mShowDraft; 62 private Uri mDraftPreviewUri; 63 private String mDraftPreviewContentType; 64 private String mDraftSnippetText; 65 private boolean mIsArchived; 66 private String mSubject; 67 private String mDraftSubject; 68 private String mSnippetSenderFirstName; 69 private String mSnippetSenderDisplayDestination; 70 private boolean mIsEnterprise; 71 ConversationListItemData()72 public ConversationListItemData() { 73 } 74 bind(final Cursor cursor)75 public void bind(final Cursor cursor) { 76 bind(cursor, false); 77 } 78 bind(final Cursor cursor, final boolean ignoreDraft)79 public void bind(final Cursor cursor, final boolean ignoreDraft) { 80 mConversationId = cursor.getString(INDEX_ID); 81 mName = cursor.getString(INDEX_CONVERSATION_NAME); 82 mIcon = cursor.getString(INDEX_CONVERSATION_ICON); 83 mSnippetText = cursor.getString(INDEX_SNIPPET_TEXT); 84 mTimestamp = cursor.getLong(INDEX_SORT_TIMESTAMP); 85 mIsRead = cursor.getInt(INDEX_READ) == 1; 86 final String previewUriString = cursor.getString(INDEX_PREVIEW_URI); 87 mPreviewUri = TextUtils.isEmpty(previewUriString) ? null : Uri.parse(previewUriString); 88 mPreviewContentType = cursor.getString(INDEX_PREVIEW_CONTENT_TYPE); 89 mParticipantContactId = cursor.getLong(INDEX_PARTICIPANT_CONTACT_ID); 90 mParticipantLookupKey = cursor.getString(INDEX_PARTICIPANT_LOOKUP_KEY); 91 mOtherParticipantNormalizedDestination = cursor.getString( 92 INDEX_OTHER_PARTICIPANT_NORMALIZED_DESTINATION); 93 mSelfId = cursor.getString(INDEX_SELF_ID); 94 mParticipantCount = cursor.getInt(INDEX_PARTICIPANT_COUNT); 95 mNotificationEnabled = cursor.getInt(INDEX_NOTIFICATION_ENABLED) == 1; 96 mNotificationSoundUri = cursor.getString(INDEX_NOTIFICATION_SOUND_URI); 97 mNotificationVibrate = cursor.getInt(INDEX_NOTIFICATION_VIBRATION) == 1; 98 mIncludeEmailAddress = cursor.getInt(INDEX_INCLUDE_EMAIL_ADDRESS) == 1; 99 mMessageStatus = cursor.getInt(INDEX_MESSAGE_STATUS); 100 mMessageRawTelephonyStatus = cursor.getInt(INDEX_MESSAGE_RAW_TELEPHONY_STATUS); 101 if (!ignoreDraft) { 102 mShowDraft = cursor.getInt(INDEX_SHOW_DRAFT) == 1; 103 final String draftPreviewUriString = cursor.getString(INDEX_DRAFT_PREVIEW_URI); 104 mDraftPreviewUri = TextUtils.isEmpty(draftPreviewUriString) ? 105 null : Uri.parse(draftPreviewUriString); 106 mDraftPreviewContentType = cursor.getString(INDEX_DRAFT_PREVIEW_CONTENT_TYPE); 107 mDraftSnippetText = cursor.getString(INDEX_DRAFT_SNIPPET_TEXT); 108 mDraftSubject = cursor.getString(INDEX_DRAFT_SUBJECT_TEXT); 109 } else { 110 mShowDraft = false; 111 mDraftPreviewUri = null; 112 mDraftPreviewContentType = null; 113 mDraftSnippetText = null; 114 mDraftSubject = null; 115 } 116 117 mIsArchived = cursor.getInt(INDEX_ARCHIVE_STATUS) == 1; 118 mSubject = cursor.getString(INDEX_SUBJECT_TEXT); 119 mSnippetSenderFirstName = cursor.getString(INDEX_SNIPPET_SENDER_FIRST_NAME); 120 mSnippetSenderDisplayDestination = 121 cursor.getString(INDEX_SNIPPET_SENDER_DISPLAY_DESTINATION); 122 mIsEnterprise = cursor.getInt(INDEX_IS_ENTERPRISE) == 1; 123 } 124 getConversationId()125 public String getConversationId() { 126 return mConversationId; 127 } 128 getName()129 public String getName() { 130 return mName; 131 } 132 getIcon()133 public String getIcon() { 134 return mIcon; 135 } 136 getIsRead()137 public boolean getIsRead() { 138 return mIsRead; 139 } 140 getFormattedTimestamp()141 public String getFormattedTimestamp() { 142 return Dates.getConversationTimeString(mTimestamp).toString(); 143 } 144 getTimestamp()145 public long getTimestamp() { 146 return mTimestamp; 147 } 148 getSnippetText()149 public String getSnippetText() { 150 return mSnippetText; 151 } 152 getPreviewUri()153 public Uri getPreviewUri() { 154 return mPreviewUri; 155 } 156 getPreviewContentType()157 public String getPreviewContentType() { 158 return mPreviewContentType; 159 } 160 161 /** 162 * @see ConversationColumns#PARTICIPANT_CONTACT_ID 163 * @return the contact id of the participant if it is a 1:1 conversation, -1 for group. 164 */ getParticipantContactId()165 public long getParticipantContactId() { 166 return mParticipantContactId; 167 } 168 169 /** 170 * @see ConversationColumns#IS_ENTERPRISE 171 * @return whether the conversation is enterprise. 172 */ isEnterprise()173 public boolean isEnterprise() { 174 return mIsEnterprise; 175 } 176 getParticipantLookupKey()177 public String getParticipantLookupKey() { 178 return mParticipantLookupKey; 179 } 180 getOtherParticipantNormalizedDestination()181 public String getOtherParticipantNormalizedDestination() { 182 return mOtherParticipantNormalizedDestination; 183 } 184 getSelfId()185 public String getSelfId() { 186 return mSelfId; 187 } 188 getParticipantCount()189 public int getParticipantCount() { 190 return mParticipantCount; 191 } 192 getIsGroup()193 public boolean getIsGroup() { 194 // Participant count excludes self 195 return (mParticipantCount > 1); 196 } 197 getIncludeEmailAddress()198 public boolean getIncludeEmailAddress() { 199 return mIncludeEmailAddress; 200 } 201 getNotificationEnabled()202 public boolean getNotificationEnabled() { 203 return mNotificationEnabled; 204 } 205 getNotificationSoundUri()206 public String getNotificationSoundUri() { 207 return mNotificationSoundUri; 208 } 209 getNotifiationVibrate()210 public boolean getNotifiationVibrate() { 211 return mNotificationVibrate; 212 } 213 getIsFailedStatus()214 public final boolean getIsFailedStatus() { 215 return (mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_FAILED || 216 mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER || 217 mMessageStatus == MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED || 218 mMessageStatus == MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE); 219 } 220 getIsSendRequested()221 public final boolean getIsSendRequested() { 222 return (mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND || 223 mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY || 224 mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_SENDING || 225 mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_RESENDING); 226 } 227 getIsMessageTypeOutgoing()228 public boolean getIsMessageTypeOutgoing() { 229 return !MessageData.getIsIncoming(mMessageStatus); 230 } 231 getMessageRawTelephonyStatus()232 public int getMessageRawTelephonyStatus() { 233 return mMessageRawTelephonyStatus; 234 } 235 getMessageStatus()236 public int getMessageStatus() { 237 return mMessageStatus; 238 } 239 getShowDraft()240 public boolean getShowDraft() { 241 return mShowDraft; 242 } 243 getDraftSnippetText()244 public String getDraftSnippetText() { 245 return mDraftSnippetText; 246 } 247 getDraftPreviewUri()248 public Uri getDraftPreviewUri() { 249 return mDraftPreviewUri; 250 } 251 getDraftPreviewContentType()252 public String getDraftPreviewContentType() { 253 return mDraftPreviewContentType; 254 } 255 getIsArchived()256 public boolean getIsArchived() { 257 return mIsArchived; 258 } 259 getSubject()260 public String getSubject() { 261 return mSubject; 262 } 263 getDraftSubject()264 public String getDraftSubject() { 265 return mDraftSubject; 266 } 267 getSnippetSenderName()268 public String getSnippetSenderName() { 269 if (!TextUtils.isEmpty(mSnippetSenderFirstName)) { 270 return mSnippetSenderFirstName; 271 } 272 return mSnippetSenderDisplayDestination; 273 } 274 deleteConversation()275 public void deleteConversation() { 276 DeleteConversationAction.deleteConversation(mConversationId, mTimestamp); 277 } 278 279 /** 280 * Get the name of the view for this data item 281 */ getConversationListView()282 public static final String getConversationListView() { 283 return CONVERSATION_LIST_VIEW; 284 } 285 getConversationListViewSql()286 public static final String getConversationListViewSql() { 287 return CONVERSATION_LIST_VIEW_SQL; 288 } 289 290 private static final String CONVERSATION_LIST_VIEW = "conversation_list_view"; 291 292 private static final String CONVERSATION_LIST_VIEW_PROJECTION = 293 DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns._ID 294 + " as " + ConversationListViewColumns._ID + ", " 295 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NAME 296 + " as " + ConversationListViewColumns.NAME + ", " 297 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.CURRENT_SELF_ID 298 + " as " + ConversationListViewColumns.CURRENT_SELF_ID + ", " 299 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.ARCHIVE_STATUS 300 + " as " + ConversationListViewColumns.ARCHIVE_STATUS + ", " 301 + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.READ 302 + " as " + ConversationListViewColumns.READ + ", " 303 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.ICON 304 + " as " + ConversationListViewColumns.ICON + ", " 305 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PARTICIPANT_CONTACT_ID 306 + " as " + ConversationListViewColumns.PARTICIPANT_CONTACT_ID + ", " 307 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PARTICIPANT_LOOKUP_KEY 308 + " as " + ConversationListViewColumns.PARTICIPANT_LOOKUP_KEY + ", " 309 + DatabaseHelper.CONVERSATIONS_TABLE + '.' 310 + ConversationColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION 311 + " as " + ConversationListViewColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION + ", " 312 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SORT_TIMESTAMP 313 + " as " + ConversationListViewColumns.SORT_TIMESTAMP + ", " 314 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SHOW_DRAFT 315 + " as " + ConversationListViewColumns.SHOW_DRAFT + ", " 316 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.DRAFT_SNIPPET_TEXT 317 + " as " + ConversationListViewColumns.DRAFT_SNIPPET_TEXT + ", " 318 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.DRAFT_PREVIEW_URI 319 + " as " + ConversationListViewColumns.DRAFT_PREVIEW_URI + ", " 320 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.DRAFT_SUBJECT_TEXT 321 + " as " + ConversationListViewColumns.DRAFT_SUBJECT_TEXT + ", " 322 + DatabaseHelper.CONVERSATIONS_TABLE + '.' 323 + ConversationColumns.DRAFT_PREVIEW_CONTENT_TYPE 324 + " as " + ConversationListViewColumns.DRAFT_PREVIEW_CONTENT_TYPE + ", " 325 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PREVIEW_URI 326 + " as " + ConversationListViewColumns.PREVIEW_URI + ", " 327 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PREVIEW_CONTENT_TYPE 328 + " as " + ConversationListViewColumns.PREVIEW_CONTENT_TYPE + ", " 329 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PARTICIPANT_COUNT 330 + " as " + ConversationListViewColumns.PARTICIPANT_COUNT + ", " 331 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NOTIFICATION_ENABLED 332 + " as " + ConversationListViewColumns.NOTIFICATION_ENABLED + ", " 333 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NOTIFICATION_SOUND_URI 334 + " as " + ConversationListViewColumns.NOTIFICATION_SOUND_URI + ", " 335 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NOTIFICATION_VIBRATION 336 + " as " + ConversationListViewColumns.NOTIFICATION_VIBRATION + ", " 337 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + 338 ConversationColumns.INCLUDE_EMAIL_ADDRESS 339 + " as " + ConversationListViewColumns.INCLUDE_EMAIL_ADDRESS + ", " 340 + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.STATUS 341 + " as " + ConversationListViewColumns.MESSAGE_STATUS + ", " 342 + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RAW_TELEPHONY_STATUS 343 + " as " + ConversationListViewColumns.MESSAGE_RAW_TELEPHONY_STATUS + ", " 344 + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns._ID 345 + " as " + ConversationListViewColumns.MESSAGE_ID + ", " 346 + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.FIRST_NAME 347 + " as " + ConversationListViewColumns.SNIPPET_SENDER_FIRST_NAME + ", " 348 + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.DISPLAY_DESTINATION 349 + " as " + ConversationListViewColumns.SNIPPET_SENDER_DISPLAY_DESTINATION + ", " 350 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.IS_ENTERPRISE 351 + " as " + ConversationListViewColumns.IS_ENTERPRISE; 352 353 private static final String JOIN_PARTICIPANTS = 354 " LEFT JOIN " + DatabaseHelper.PARTICIPANTS_TABLE + " ON (" 355 + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SENDER_PARTICIPANT_ID 356 + '=' + DatabaseHelper.PARTICIPANTS_TABLE + '.' + DatabaseHelper.ParticipantColumns._ID 357 + ") "; 358 359 // View that makes latest message read flag available with rest of conversation data. 360 private static final String CONVERSATION_LIST_VIEW_SQL = "CREATE VIEW " + 361 CONVERSATION_LIST_VIEW + " AS SELECT " 362 + CONVERSATION_LIST_VIEW_PROJECTION + ", " 363 // Snippet not part of the base projection shared with search view 364 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SNIPPET_TEXT 365 + " as " + ConversationListViewColumns.SNIPPET_TEXT + ", " 366 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SUBJECT_TEXT 367 + " as " + ConversationListViewColumns.SUBJECT_TEXT + " " 368 + " FROM " + DatabaseHelper.CONVERSATIONS_TABLE 369 + " LEFT JOIN " + DatabaseHelper.MESSAGES_TABLE + " ON (" 370 + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.LATEST_MESSAGE_ID 371 + '=' + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns._ID + ") " 372 + JOIN_PARTICIPANTS 373 + "ORDER BY " + DatabaseHelper.CONVERSATIONS_TABLE + '.' 374 + ConversationColumns.SORT_TIMESTAMP + " DESC"; 375 376 public static class ConversationListViewColumns implements BaseColumns { 377 public static final String _ID = ConversationColumns._ID; 378 static final String NAME = ConversationColumns.NAME; 379 static final String ARCHIVE_STATUS = ConversationColumns.ARCHIVE_STATUS; 380 static final String READ = MessageColumns.READ; 381 static final String SORT_TIMESTAMP = ConversationColumns.SORT_TIMESTAMP; 382 static final String PREVIEW_URI = ConversationColumns.PREVIEW_URI; 383 static final String PREVIEW_CONTENT_TYPE = ConversationColumns.PREVIEW_CONTENT_TYPE; 384 static final String SNIPPET_TEXT = ConversationColumns.SNIPPET_TEXT; 385 static final String SUBJECT_TEXT = ConversationColumns.SUBJECT_TEXT; 386 static final String ICON = ConversationColumns.ICON; 387 static final String SHOW_DRAFT = ConversationColumns.SHOW_DRAFT; 388 static final String DRAFT_SUBJECT_TEXT = ConversationColumns.DRAFT_SUBJECT_TEXT; 389 static final String DRAFT_PREVIEW_URI = ConversationColumns.DRAFT_PREVIEW_URI; 390 static final String DRAFT_PREVIEW_CONTENT_TYPE = 391 ConversationColumns.DRAFT_PREVIEW_CONTENT_TYPE; 392 static final String DRAFT_SNIPPET_TEXT = ConversationColumns.DRAFT_SNIPPET_TEXT; 393 static final String PARTICIPANT_CONTACT_ID = ConversationColumns.PARTICIPANT_CONTACT_ID; 394 static final String PARTICIPANT_LOOKUP_KEY = ConversationColumns.PARTICIPANT_LOOKUP_KEY; 395 static final String OTHER_PARTICIPANT_NORMALIZED_DESTINATION = 396 ConversationColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION; 397 static final String CURRENT_SELF_ID = ConversationColumns.CURRENT_SELF_ID; 398 static final String PARTICIPANT_COUNT = ConversationColumns.PARTICIPANT_COUNT; 399 static final String NOTIFICATION_ENABLED = ConversationColumns.NOTIFICATION_ENABLED; 400 static final String NOTIFICATION_SOUND_URI = ConversationColumns.NOTIFICATION_SOUND_URI; 401 static final String NOTIFICATION_VIBRATION = ConversationColumns.NOTIFICATION_VIBRATION; 402 static final String INCLUDE_EMAIL_ADDRESS = 403 ConversationColumns.INCLUDE_EMAIL_ADDRESS; 404 static final String MESSAGE_STATUS = MessageColumns.STATUS; 405 static final String MESSAGE_RAW_TELEPHONY_STATUS = MessageColumns.RAW_TELEPHONY_STATUS; 406 static final String MESSAGE_ID = "message_id"; 407 static final String SNIPPET_SENDER_FIRST_NAME = "snippet_sender_first_name"; 408 static final String SNIPPET_SENDER_DISPLAY_DESTINATION = 409 "snippet_sender_display_destination"; 410 static final String IS_ENTERPRISE = ConversationColumns.IS_ENTERPRISE; 411 } 412 413 public static final String[] PROJECTION = { 414 ConversationListViewColumns._ID, 415 ConversationListViewColumns.NAME, 416 ConversationListViewColumns.ICON, 417 ConversationListViewColumns.SNIPPET_TEXT, 418 ConversationListViewColumns.SORT_TIMESTAMP, 419 ConversationListViewColumns.READ, 420 ConversationListViewColumns.PREVIEW_URI, 421 ConversationListViewColumns.PREVIEW_CONTENT_TYPE, 422 ConversationListViewColumns.PARTICIPANT_CONTACT_ID, 423 ConversationListViewColumns.PARTICIPANT_LOOKUP_KEY, 424 ConversationListViewColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION, 425 ConversationListViewColumns.PARTICIPANT_COUNT, 426 ConversationListViewColumns.CURRENT_SELF_ID, 427 ConversationListViewColumns.NOTIFICATION_ENABLED, 428 ConversationListViewColumns.NOTIFICATION_SOUND_URI, 429 ConversationListViewColumns.NOTIFICATION_VIBRATION, 430 ConversationListViewColumns.INCLUDE_EMAIL_ADDRESS, 431 ConversationListViewColumns.MESSAGE_STATUS, 432 ConversationListViewColumns.SHOW_DRAFT, 433 ConversationListViewColumns.DRAFT_PREVIEW_URI, 434 ConversationListViewColumns.DRAFT_PREVIEW_CONTENT_TYPE, 435 ConversationListViewColumns.DRAFT_SNIPPET_TEXT, 436 ConversationListViewColumns.ARCHIVE_STATUS, 437 ConversationListViewColumns.MESSAGE_ID, 438 ConversationListViewColumns.SUBJECT_TEXT, 439 ConversationListViewColumns.DRAFT_SUBJECT_TEXT, 440 ConversationListViewColumns.MESSAGE_RAW_TELEPHONY_STATUS, 441 ConversationListViewColumns.SNIPPET_SENDER_FIRST_NAME, 442 ConversationListViewColumns.SNIPPET_SENDER_DISPLAY_DESTINATION, 443 ConversationListViewColumns.IS_ENTERPRISE, 444 }; 445 446 private static final int INDEX_ID = 0; 447 private static final int INDEX_CONVERSATION_NAME = 1; 448 private static final int INDEX_CONVERSATION_ICON = 2; 449 private static final int INDEX_SNIPPET_TEXT = 3; 450 private static final int INDEX_SORT_TIMESTAMP = 4; 451 private static final int INDEX_READ = 5; 452 private static final int INDEX_PREVIEW_URI = 6; 453 private static final int INDEX_PREVIEW_CONTENT_TYPE = 7; 454 private static final int INDEX_PARTICIPANT_CONTACT_ID = 8; 455 private static final int INDEX_PARTICIPANT_LOOKUP_KEY = 9; 456 private static final int INDEX_OTHER_PARTICIPANT_NORMALIZED_DESTINATION = 10; 457 private static final int INDEX_PARTICIPANT_COUNT = 11; 458 private static final int INDEX_SELF_ID = 12; 459 private static final int INDEX_NOTIFICATION_ENABLED = 13; 460 private static final int INDEX_NOTIFICATION_SOUND_URI = 14; 461 private static final int INDEX_NOTIFICATION_VIBRATION = 15; 462 private static final int INDEX_INCLUDE_EMAIL_ADDRESS = 16; 463 private static final int INDEX_MESSAGE_STATUS = 17; 464 private static final int INDEX_SHOW_DRAFT = 18; 465 private static final int INDEX_DRAFT_PREVIEW_URI = 19; 466 private static final int INDEX_DRAFT_PREVIEW_CONTENT_TYPE = 20; 467 private static final int INDEX_DRAFT_SNIPPET_TEXT = 21; 468 private static final int INDEX_ARCHIVE_STATUS = 22; 469 private static final int INDEX_MESSAGE_ID = 23; 470 private static final int INDEX_SUBJECT_TEXT = 24; 471 private static final int INDEX_DRAFT_SUBJECT_TEXT = 25; 472 private static final int INDEX_MESSAGE_RAW_TELEPHONY_STATUS = 26; 473 private static final int INDEX_SNIPPET_SENDER_FIRST_NAME = 27; 474 private static final int INDEX_SNIPPET_SENDER_DISPLAY_DESTINATION = 28; 475 private static final int INDEX_IS_ENTERPRISE = 29; 476 477 private static final String DIVIDER_TEXT = ", "; 478 hasAnyEnterpriseContact( final List<ParticipantData> participants)479 public static boolean hasAnyEnterpriseContact( 480 final List<ParticipantData> participants) { 481 for (final ParticipantData participant : participants) { 482 if (ContactUtil.isEnterpriseContactId(participant.getContactId())) { 483 return true; 484 } 485 } 486 return false; 487 } 488 489 /** 490 * Get a conversation from the local DB based on the conversation id. 491 * 492 * @param dbWrapper The database 493 * @param conversationId The conversation Id to read 494 * @return The existing conversation or null 495 */ getExistingConversation(final DatabaseWrapper dbWrapper, final String conversationId)496 public static ConversationListItemData getExistingConversation(final DatabaseWrapper dbWrapper, 497 final String conversationId) { 498 ConversationListItemData conversation = null; 499 500 // Look for an existing conversation in the db with this conversation id 501 Cursor cursor = null; 502 try { 503 // TODO: Should we be able to read a row from just the conversation table? 504 cursor = dbWrapper.query(getConversationListView(), 505 PROJECTION, 506 ConversationColumns._ID + "=?", 507 new String[] { conversationId }, 508 null, null, null); 509 Assert.inRange(cursor.getCount(), 0, 1); 510 if (cursor.moveToFirst()) { 511 conversation = new ConversationListItemData(); 512 conversation.bind(cursor); 513 } 514 } finally { 515 if (cursor != null) { 516 cursor.close(); 517 } 518 } 519 520 return conversation; 521 } 522 generateConversationName(final List<ParticipantData> participants)523 public static String generateConversationName(final List<ParticipantData> 524 participants) { 525 if (participants.size() == 1) { 526 // Prefer full name over first name for 1:1 conversation 527 return participants.get(0).getDisplayName(true); 528 } 529 530 final ArrayList<String> participantNames = new ArrayList<String>(); 531 for (final ParticipantData participant : participants) { 532 // Prefer first name over full name for group conversation 533 participantNames.add(participant.getDisplayName(false)); 534 } 535 536 final Joiner joiner = Joiner.on(DIVIDER_TEXT).skipNulls(); 537 return joiner.join(participantNames); 538 } 539 540 } 541