Refactor ThreadRecord.

This commit is contained in:
Greyson Parrelli 2020-05-13 17:30:53 -04:00
parent 1cd6b58ece
commit 1b01196ec6
4 changed files with 361 additions and 148 deletions

View File

@ -22,7 +22,9 @@ import android.graphics.Typeface;
import android.graphics.drawable.RippleDrawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.view.View;
@ -41,6 +43,9 @@ import org.thoughtcrime.securesms.components.DeliveryStatusView;
import org.thoughtcrime.securesms.components.FromTextView;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.components.TypingIndicatorView;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
@ -48,6 +53,8 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
import org.thoughtcrime.securesms.conversationlist.model.MessageResult;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.SearchUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
@ -94,7 +101,7 @@ public class ConversationListItem extends RelativeLayout
private final RecipientForeverObserver groupAddedByObserver = adder -> {
if (isAttachedToWindow() && subjectView != null && thread != null) {
subjectView.setText(thread.getDisplayBody(getContext()));
subjectView.setText(getThreadDisplayBody(getContext(), thread));
}
};
@ -176,7 +183,7 @@ public class ConversationListItem extends RelativeLayout
this.typingView.stopAnimation();
this.subjectView.setVisibility(VISIBLE);
this.subjectView.setText(getTrimmedSnippet(thread.getDisplayBody(getContext())));
this.subjectView.setText(getTrimmedSnippet(getThreadDisplayBody(getContext(), thread)));
if (thread.getGroupAddedBy() != null) {
groupAddedBy = Recipient.live(thread.getGroupAddedBy());
@ -377,6 +384,99 @@ public class ConversationListItem extends RelativeLayout
setRippleColor(recipient);
}
private static SpannableString getThreadDisplayBody(@NonNull Context context, @NonNull ThreadRecord thread) {
if (thread.getGroupAddedBy() != null) {
return emphasisAdded(context.getString(thread.isGv2Invite() ? R.string.ThreadRecord_s_invited_you_to_the_group
: R.string.ThreadRecord_s_added_you_to_the_group,
Recipient.live(thread.getGroupAddedBy()).get().getDisplayName(context)));
} else if (!thread.isMessageRequestAccepted()) {
return emphasisAdded(context.getString(R.string.ThreadRecord_message_request));
} else if (SmsDatabase.Types.isGroupUpdate(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_group_updated));
} else if (SmsDatabase.Types.isGroupQuit(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_left_the_group));
} else if (SmsDatabase.Types.isKeyExchangeType(thread.getType())) {
return emphasisAdded(context.getString(R.string.ConversationListItem_key_exchange_message));
} else if (SmsDatabase.Types.isFailedDecryptType(thread.getType())) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_bad_encrypted_message));
} else if (SmsDatabase.Types.isNoRemoteSessionType(thread.getType())) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
} else if (SmsDatabase.Types.isEndSessionType(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_secure_session_reset));
} else if (MmsSmsColumns.Types.isLegacyType(thread.getType())) {
return emphasisAdded(context.getString(R.string.MessageRecord_message_encrypted_with_a_legacy_protocol_version_that_is_no_longer_supported));
} else if (MmsSmsColumns.Types.isDraftMessageType(thread.getType())) {
String draftText = context.getString(R.string.ThreadRecord_draft);
return emphasisAdded(draftText + " " + thread.getBody(), 0, draftText.length());
} else if (SmsDatabase.Types.isOutgoingCall(thread.getType())) {
return emphasisAdded(context.getString(org.thoughtcrime.securesms.R.string.ThreadRecord_called));
} else if (SmsDatabase.Types.isIncomingCall(thread.getType())) {
return emphasisAdded(context.getString(org.thoughtcrime.securesms.R.string.ThreadRecord_called_you));
} else if (SmsDatabase.Types.isMissedCall(thread.getType())) {
return emphasisAdded(context.getString(org.thoughtcrime.securesms.R.string.ThreadRecord_missed_call));
} else if (SmsDatabase.Types.isJoinedType(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_s_is_on_signal, thread.getRecipient().toShortString(context)));
} else if (SmsDatabase.Types.isExpirationTimerUpdate(thread.getType())) {
int seconds = (int)(thread.getExpiresIn() / 1000);
if (seconds <= 0) {
return emphasisAdded(context.getString(R.string.ThreadRecord_disappearing_messages_disabled));
}
String time = ExpirationUtil.getExpirationDisplayValue(context, seconds);
return emphasisAdded(context.getString(R.string.ThreadRecord_disappearing_message_time_updated_to_s, time));
} else if (SmsDatabase.Types.isIdentityUpdate(thread.getType())) {
if (thread.getRecipient().isGroup()) {
return emphasisAdded(context.getString(R.string.ThreadRecord_safety_number_changed));
} else {
return emphasisAdded(context.getString(R.string.ThreadRecord_your_safety_number_with_s_has_changed, thread.getRecipient().toShortString(context)));
}
} else if (SmsDatabase.Types.isIdentityVerified(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_you_marked_verified));
} else if (SmsDatabase.Types.isIdentityDefault(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_you_marked_unverified));
} else if (SmsDatabase.Types.isUnsupportedMessageType(thread.getType())) {
return emphasisAdded(context.getString(R.string.ThreadRecord_message_could_not_be_processed));
} else {
if (TextUtils.isEmpty(thread.getBody())) {
ThreadDatabase.Extra extra = thread.getExtra();
if (extra != null && extra.isSticker()) {
return new SpannableString(emphasisAdded(context.getString(R.string.ThreadRecord_sticker)));
} else if (extra != null && extra.isViewOnce()) {
return new SpannableString(emphasisAdded(getViewOnceDescription(context, thread.getContentType())));
} else if (extra != null && extra.isRemoteDelete()) {
return new SpannableString(emphasisAdded(context.getString(R.string.ThreadRecord_this_message_was_deleted)));
} else {
return new SpannableString(emphasisAdded(context.getString(R.string.ThreadRecord_media_message)));
}
} else {
return new SpannableString(thread.getBody());
}
}
}
private static @NonNull SpannableString emphasisAdded(String sequence) {
return emphasisAdded(sequence, 0, sequence.length());
}
private static @NonNull SpannableString emphasisAdded(String sequence, int start, int end) {
SpannableString spannable = new SpannableString(sequence);
spannable.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC),
start,
end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable;
}
private static String getViewOnceDescription(@NonNull Context context, @Nullable String contentType) {
if (MediaUtil.isViewOnceType(contentType)) {
return context.getString(R.string.ThreadRecord_view_once_media);
} else if (MediaUtil.isVideoType(contentType)) {
return context.getString(R.string.ThreadRecord_view_once_video);
} else {
return context.getString(R.string.ThreadRecord_view_once_photo);
}
}
private static class ThumbnailPositioner implements Runnable {
private final View thumbnailView;

View File

@ -848,30 +848,14 @@ public class ThreadDatabase extends Database {
}
public ThreadRecord getCurrent() {
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID));
int distributionType = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.TYPE));
RecipientId recipientId = RecipientId.from(cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.RECIPIENT_ID)));
Recipient recipient = Recipient.live(recipientId).get();
String body = cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET));
long date = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE));
long count = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT));
int unreadCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.UNREAD_COUNT));
long type = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_TYPE));
boolean archived = cursor.getInt(cursor.getColumnIndex(ThreadDatabase.ARCHIVED)) != 0;
int status = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.STATUS));
int deliveryReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.DELIVERY_RECEIPT_COUNT));
int readReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.READ_RECEIPT_COUNT));
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.EXPIRES_IN));
long lastSeen = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.LAST_SEEN));
Uri snippetUri = getSnippetUri(cursor);
String contentType = cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_CONTENT_TYPE));
int readReceiptCount = TextSecurePreferences.isReadReceiptsEnabled(context) ? cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.READ_RECEIPT_COUNT))
: 0;
String extraString = cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_EXTRAS));
if (!TextSecurePreferences.isReadReceiptsEnabled(context)) {
readReceiptCount = 0;
}
Extra extra = null;
if (extraString != null) {
@ -882,9 +866,24 @@ public class ThreadDatabase extends Database {
}
}
return new ThreadRecord(body, snippetUri, contentType, extra, recipient, date, count,
unreadCount, threadId, deliveryReceiptCount, status, type,
distributionType, archived, expiresIn, lastSeen, readReceiptCount);
return new ThreadRecord.Builder(cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID)))
.setRecipient(recipient)
.setType(cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_TYPE)))
.setDistributionType(cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.TYPE)))
.setBody(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET)))
.setDate(cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE)))
.setArchived(cursor.getInt(cursor.getColumnIndex(ThreadDatabase.ARCHIVED)) != 0)
.setDeliveryStatus(cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.STATUS)))
.setDeliveryReceiptCount(cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.DELIVERY_RECEIPT_COUNT)))
.setReadReceiptCount(readReceiptCount)
.setExpiresIn(cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.EXPIRES_IN)))
.setLastSeen(cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.LAST_SEEN)))
.setSnippetUri(getSnippetUri(cursor))
.setContentType(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_CONTENT_TYPE)))
.setCount(cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT)))
.setUnreadCount(cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.UNREAD_COUNT)))
.setExtra(extra)
.build();
}
private @Nullable Uri getSnippetUri(Cursor cursor) {

View File

@ -0,0 +1,29 @@
package org.thoughtcrime.securesms.database.model;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.SmsDatabase;
final class StatusUtil {
private StatusUtil() {}
static boolean isDelivered(long deliveryStatus, int deliveryReceiptCount) {
return (deliveryStatus >= SmsDatabase.Status.STATUS_COMPLETE &&
deliveryStatus < SmsDatabase.Status.STATUS_PENDING) || deliveryReceiptCount > 0;
}
static boolean isPending(long type) {
return MmsSmsColumns.Types.isPendingMessageType(type) &&
!MmsSmsColumns.Types.isIdentityVerified(type) &&
!MmsSmsColumns.Types.isIdentityDefault(type);
}
static boolean isFailed(long type, long deliveryStatus) {
return MmsSmsColumns.Types.isFailedMessageType(type) ||
MmsSmsColumns.Types.isPendingSecureSmsFallbackType(type) ||
deliveryStatus >= SmsDatabase.Status.STATUS_FAILED;
}
static boolean isVerificationStatusChange(long type) {
return SmsDatabase.Types.isIdentityDefault(type) || SmsDatabase.Types.isIdentityVerified(type);
}
}

View File

@ -17,36 +17,34 @@
*/
package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import android.net.Uri;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.StyleSpan;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase.Extra;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.whispersystems.libsignal.util.guava.Preconditions;
/**
* The message record model which represents thread heading messages.
*
* @author Moxie Marlinspike
*
* Represents an entry in the {@link org.thoughtcrime.securesms.database.ThreadDatabase}.
*/
public class ThreadRecord extends DisplayRecord {
public final class ThreadRecord {
private @Nullable final Uri snippetUri;
private @Nullable final String contentType;
private @Nullable final Extra extra;
private final long threadId;
private final String body;
private final Recipient recipient;
private final long type;
private final long date;
private final long deliveryStatus;
private final int deliveryReceiptCount;
private final int readReceiptCount;
private final Uri snippetUri;
private final String contentType;
private final Extra extra;
private final long count;
private final int unreadCount;
private final int distributionType;
@ -54,114 +52,48 @@ public class ThreadRecord extends DisplayRecord {
private final long expiresIn;
private final long lastSeen;
public ThreadRecord(@NonNull String body, @Nullable Uri snippetUri,
@Nullable String contentType, @Nullable Extra extra,
@NonNull Recipient recipient, long date, long count, int unreadCount,
long threadId, int deliveryReceiptCount, int status, long snippetType,
int distributionType, boolean archived, long expiresIn, long lastSeen,
int readReceiptCount)
{
super(body, recipient, date, date, threadId, status, deliveryReceiptCount, snippetType, readReceiptCount);
this.snippetUri = snippetUri;
this.contentType = contentType;
this.extra = extra;
this.count = count;
this.unreadCount = unreadCount;
this.distributionType = distributionType;
this.archived = archived;
this.expiresIn = expiresIn;
this.lastSeen = lastSeen;
private ThreadRecord(@NonNull Builder builder) {
this.threadId = builder.threadId;
this.body = builder.body;
this.recipient = builder.recipient;
this.date = builder.date;
this.type = builder.type;
this.deliveryStatus = builder.deliveryStatus;
this.deliveryReceiptCount = builder.deliveryReceiptCount;
this.readReceiptCount = builder.readReceiptCount;
this.snippetUri = builder.snippetUri;
this.contentType = builder.contentType;
this.extra = builder.extra;
this.count = builder.count;
this.unreadCount = builder.unreadCount;
this.distributionType = builder.distributionType;
this.archived = builder.archived;
this.expiresIn = builder.expiresIn;
this.lastSeen = builder.lastSeen;
}
public long getThreadId() {
return threadId;
}
public @NonNull Recipient getRecipient() {
return recipient;
}
public @Nullable Uri getSnippetUri() {
return snippetUri;
}
@Override
public SpannableString getDisplayBody(@NonNull Context context) {
if (getGroupAddedBy() != null) {
return emphasisAdded(context.getString(isGv2Invite() ? R.string.ThreadRecord_s_invited_you_to_the_group
: R.string.ThreadRecord_s_added_you_to_the_group,
Recipient.live(getGroupAddedBy()).get().getDisplayName(context)));
} else if (!isMessageRequestAccepted()) {
return emphasisAdded(context.getString(R.string.ThreadRecord_message_request));
} else if (isGroupUpdate()) {
return emphasisAdded(context.getString(R.string.ThreadRecord_group_updated));
} else if (isGroupQuit()) {
return emphasisAdded(context.getString(R.string.ThreadRecord_left_the_group));
} else if (isKeyExchange()) {
return emphasisAdded(context.getString(R.string.ConversationListItem_key_exchange_message));
} else if (SmsDatabase.Types.isFailedDecryptType(type)) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_bad_encrypted_message));
} else if (SmsDatabase.Types.isNoRemoteSessionType(type)) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
} else if (SmsDatabase.Types.isEndSessionType(type)) {
return emphasisAdded(context.getString(R.string.ThreadRecord_secure_session_reset));
} else if (MmsSmsColumns.Types.isLegacyType(type)) {
return emphasisAdded(context.getString(R.string.MessageRecord_message_encrypted_with_a_legacy_protocol_version_that_is_no_longer_supported));
} else if (MmsSmsColumns.Types.isDraftMessageType(type)) {
String draftText = context.getString(R.string.ThreadRecord_draft);
return emphasisAdded(draftText + " " + getBody(), 0, draftText.length());
} else if (SmsDatabase.Types.isOutgoingCall(type)) {
return emphasisAdded(context.getString(org.thoughtcrime.securesms.R.string.ThreadRecord_called));
} else if (SmsDatabase.Types.isIncomingCall(type)) {
return emphasisAdded(context.getString(org.thoughtcrime.securesms.R.string.ThreadRecord_called_you));
} else if (SmsDatabase.Types.isMissedCall(type)) {
return emphasisAdded(context.getString(org.thoughtcrime.securesms.R.string.ThreadRecord_missed_call));
} else if (SmsDatabase.Types.isJoinedType(type)) {
return emphasisAdded(context.getString(R.string.ThreadRecord_s_is_on_signal, getRecipient().toShortString(context)));
} else if (SmsDatabase.Types.isExpirationTimerUpdate(type)) {
int seconds = (int)(getExpiresIn() / 1000);
if (seconds <= 0) {
return emphasisAdded(context.getString(R.string.ThreadRecord_disappearing_messages_disabled));
}
String time = ExpirationUtil.getExpirationDisplayValue(context, seconds);
return emphasisAdded(context.getString(R.string.ThreadRecord_disappearing_message_time_updated_to_s, time));
} else if (SmsDatabase.Types.isIdentityUpdate(type)) {
if (getRecipient().isGroup()) return emphasisAdded(context.getString(R.string.ThreadRecord_safety_number_changed));
else return emphasisAdded(context.getString(R.string.ThreadRecord_your_safety_number_with_s_has_changed, getRecipient().toShortString(context)));
} else if (SmsDatabase.Types.isIdentityVerified(type)) {
return emphasisAdded(context.getString(R.string.ThreadRecord_you_marked_verified));
} else if (SmsDatabase.Types.isIdentityDefault(type)) {
return emphasisAdded(context.getString(R.string.ThreadRecord_you_marked_unverified));
} else if (SmsDatabase.Types.isUnsupportedMessageType(type)) {
return emphasisAdded(context.getString(R.string.ThreadRecord_message_could_not_be_processed));
} else {
if (TextUtils.isEmpty(getBody())) {
if (extra != null && extra.isSticker()) {
return new SpannableString(emphasisAdded(context.getString(R.string.ThreadRecord_sticker)));
} else if (extra != null && extra.isViewOnce()) {
return new SpannableString(emphasisAdded(getViewOnceDescription(context, contentType)));
} else if (extra != null && extra.isRemoteDelete()) {
return new SpannableString(emphasisAdded(context.getString(R.string.ThreadRecord_this_message_was_deleted)));
} else {
return new SpannableString(emphasisAdded(context.getString(R.string.ThreadRecord_media_message)));
}
} else {
return new SpannableString(getBody());
}
}
public @NonNull String getBody() {
return body;
}
private SpannableString emphasisAdded(String sequence) {
return emphasisAdded(sequence, 0, sequence.length());
public @Nullable Extra getExtra() {
return extra;
}
private SpannableString emphasisAdded(String sequence, int start, int end) {
SpannableString spannable = new SpannableString(sequence);
spannable.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC),
start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable;
}
private String getViewOnceDescription(@NonNull Context context, @Nullable String contentType) {
if (MediaUtil.isViewOnceType(contentType)) {
return context.getString(R.string.ThreadRecord_view_once_media);
} else if (MediaUtil.isVideoType(contentType)) {
return context.getString(R.string.ThreadRecord_view_once_video);
} else {
return context.getString(R.string.ThreadRecord_view_once_photo);
}
public @Nullable String getContentType() {
return contentType;
}
public long getCount() {
@ -173,13 +105,17 @@ public class ThreadRecord extends DisplayRecord {
}
public long getDate() {
return getDateReceived();
return date;
}
public boolean isArchived() {
return archived;
}
public long getType() {
return type;
}
public int getDistributionType() {
return distributionType;
}
@ -192,6 +128,38 @@ public class ThreadRecord extends DisplayRecord {
return lastSeen;
}
public boolean isOutgoing() {
return MmsSmsColumns.Types.isOutgoingMessageType(type);
}
public boolean isOutgoingCall() {
return SmsDatabase.Types.isOutgoingCall(type);
}
public boolean isVerificationStatusChange() {
return StatusUtil.isVerificationStatusChange(type);
}
public boolean isPending() {
return StatusUtil.isPending(type);
}
public boolean isFailed() {
return StatusUtil.isFailed(type, deliveryStatus);
}
public boolean isRemoteRead() {
return readReceiptCount > 0;
}
public boolean isPendingInsecureSmsFallback() {
return SmsDatabase.Types.isPendingInsecureSmsFallbackType(type);
}
public boolean isDelivered() {
return StatusUtil.isDelivered(deliveryStatus, deliveryReceiptCount);
}
public @Nullable RecipientId getGroupAddedBy() {
if (extra != null && extra.getGroupAddedBy() != null) return RecipientId.from(extra.getGroupAddedBy());
else return null;
@ -205,4 +173,121 @@ public class ThreadRecord extends DisplayRecord {
if (extra != null) return extra.isMessageRequestAccepted();
else return true;
}
public static class Builder {
private long threadId;
private String body;
private Recipient recipient;
private long type;
private long date;
private long deliveryStatus;
private int deliveryReceiptCount;
private int readReceiptCount;
private Uri snippetUri;
private String contentType;
private Extra extra;
private long count;
private int unreadCount;
private int distributionType;
private boolean archived;
private long expiresIn;
private long lastSeen;
public Builder(long threadId) {
this.threadId = threadId;
}
public Builder setBody(@NonNull String body) {
this.body = body;
return this;
}
public Builder setRecipient(@NonNull Recipient recipient) {
this.recipient = recipient;
return this;
}
public Builder setType(long type) {
this.type = type;
return this;
}
public Builder setThreadId(long threadId) {
this.threadId = threadId;
return this;
}
public Builder setDate(long date) {
this.date = date;
return this;
}
public Builder setDeliveryStatus(long deliveryStatus) {
this.deliveryStatus = deliveryStatus;
return this;
}
public Builder setDeliveryReceiptCount(int deliveryReceiptCount) {
this.deliveryReceiptCount = deliveryReceiptCount;
return this;
}
public Builder setReadReceiptCount(int readReceiptCount) {
this.readReceiptCount = readReceiptCount;
return this;
}
public Builder setSnippetUri(@Nullable Uri snippetUri) {
this.snippetUri = snippetUri;
return this;
}
public Builder setContentType(@Nullable String contentType) {
this.contentType = contentType;
return this;
}
public Builder setExtra(@Nullable Extra extra) {
this.extra = extra;
return this;
}
public Builder setCount(long count) {
this.count = count;
return this;
}
public Builder setUnreadCount(int unreadCount) {
this.unreadCount = unreadCount;
return this;
}
public Builder setDistributionType(int distributionType) {
this.distributionType = distributionType;
return this;
}
public Builder setArchived(boolean archived) {
this.archived = archived;
return this;
}
public Builder setExpiresIn(long expiresIn) {
this.expiresIn = expiresIn;
return this;
}
public Builder setLastSeen(long lastSeen) {
this.lastSeen = lastSeen;
return this;
}
public ThreadRecord build() {
Preconditions.checkArgument(threadId > 0);
Preconditions.checkArgument(date > 0);
Preconditions.checkNotNull(body);
Preconditions.checkNotNull(recipient);
return new ThreadRecord(this);
}
}
}