Add delivery status icons to the conversation list

Closes #4710
This commit is contained in:
haffenloher 2015-11-24 16:06:41 +01:00 committed by Moxie Marlinspike
parent df5c497b5b
commit 7c95adc7e6
24 changed files with 447 additions and 318 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 997 B

24
res/layout/alert_view.xml Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<ImageView
android:id="@+id/sms_failed_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_error_red_24dp"
android:visibility="gone"
tools:visibility="visible"
android:contentDescription="@string/conversation_item_sent__send_failed_indicator_description" />
<ImageView
android:id="@+id/pending_approval_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_info_outline_grey600_24dp"
android:visibility="gone"
tools:visibility="visible"
android:layout_gravity="center_vertical"
android:contentDescription="@string/conversation_item_sent__pending_approval_description" />
</merge>

View File

@ -2,9 +2,8 @@
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/pending_indicator"
android:layout_width="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceSmall"
android:fontFamily="sans-serif-light"
android:textColor="?conversation_item_sent_text_secondary_color"

View File

@ -4,9 +4,8 @@
<pl.tajchert.sample.DotsTextView
android:id="@+id/pending_indicator"
android:layout_width="20dp"
android:layout_width="match_parent"
android:layout_height="20dp"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceSmall"
android:fontFamily="sans-serif-light"
android:textColor="?conversation_item_sent_text_secondary_color"

View File

@ -109,16 +109,6 @@
android:orientation="horizontal"
android:gravity="left">
<ImageView android:id="@+id/sent_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
<ImageView android:id="@+id/delivered_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
<ImageView android:id="@+id/secure_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -131,9 +121,11 @@
android:tint="?conversation_item_received_text_secondary_color"
android:tintMode="multiply"/>
<FrameLayout android:id="@+id/pending_indicator_stub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<org.thoughtcrime.securesms.components.DeliveryStatusView
android:id="@+id/delivery_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
<TextView android:id="@+id/conversation_item_date"
android:layout_width="wrap_content"
@ -149,31 +141,13 @@
</LinearLayout>
</LinearLayout>
<LinearLayout android:id="@+id/indicators_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:orientation="vertical"
android:gravity="center_vertical">
<ImageView android:id="@+id/sms_failed_indicator"
<org.thoughtcrime.securesms.components.AlertView
android:id="@+id/indicators_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_warning_red"
android:contentDescription="@string/conversation_item_sent__send_failed_indicator_description"
android:visibility="gone" />
<ImageView
android:id="@+id/pending_approval_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_info_outline_grey600_24dp"
android:visibility="gone"
android:layout_gravity="center_vertical"
android:contentDescription="@string/conversation_item_sent__pending_approval_description"
tools:visibility="gone" />
</LinearLayout>
android:layout_alignParentRight="true"
android:orientation="vertical"
android:gravity="center_vertical"/>
<TextView android:id="@+id/indicator_text"
android:layout_width="wrap_content"

View File

@ -16,35 +16,15 @@
android:layout_marginBottom="6dp"
android:layout_marginRight="0dp">
<LinearLayout android:id="@+id/indicators_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="left|center_vertical"
android:layout_marginLeft="6dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true">
<ImageView
android:id="@+id/sms_failed_indicator"
<org.thoughtcrime.securesms.components.AlertView
android:id="@+id/indicators_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_error_red_24dp"
tools:visibility="visible"
android:visibility="gone"
android:contentDescription="@string/conversation_item_sent__send_failed_indicator_description" />
<ImageView
android:id="@+id/pending_approval_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_info_outline_grey600_24dp"
android:visibility="gone"
android:layout_gravity="center_vertical"
android:contentDescription="@string/conversation_item_sent__pending_approval_description"
tools:visibility="visible" />
</LinearLayout>
android:orientation="vertical"
android:gravity="left|center_vertical"
android:layout_marginLeft="6dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"/>
<LinearLayout android:id="@+id/body_bubble"
android:layout_width="wrap_content"
@ -145,33 +125,11 @@
android:paddingBottom="2dp"
tools:text="30 mins" />
<FrameLayout android:id="@+id/pending_indicator_stub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView android:id="@+id/sent_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/ic_done_white_18dp"
android:paddingLeft="2dp"
android:paddingBottom="2dp"
android:visibility="gone"
android:tint="?conversation_item_sent_text_secondary_color"
android:tintMode="multiply"
android:contentDescription="@string/conversation_item_sent__delivered_description" />
<ImageView android:id="@+id/delivered_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/ic_done_all_white_18dp"
android:paddingLeft="2dp"
android:paddingBottom="2dp"
android:visibility="gone"
android:tint="?conversation_item_sent_text_secondary_color"
android:tintMode="multiply"
android:contentDescription="@string/conversation_item_sent__delivered_description" />
<org.thoughtcrime.securesms.components.DeliveryStatusView
android:id="@+id/delivery_status"
android:layout_width="20dp"
android:layout_height="wrap_content"
app:iconColor="?conversation_item_sent_text_secondary_color"/>
<ImageView android:id="@+id/secure_indicator"
android:layout_width="wrap_content"

View File

@ -44,24 +44,25 @@
android:ellipsize="end"
android:drawablePadding="5dp"/>
<ImageView android:id="@+id/error"
android:layout_height="20dp"
android:layout_width="20dp"
android:layout_alignParentLeft="true"
android:layout_below="@id/from"
android:paddingBottom="3dp"
android:visibility="gone"
tools:visibility="visible"
android:src="@drawable/ic_action_warning_red"
android:contentDescription="@string/conversation_list_item_view__error_alert" />
<org.thoughtcrime.securesms.components.AlertView
android:id="@+id/indicators_parent"
android:layout_width="18dp"
android:layout_height="18dp"
android:paddingTop="2dp"
android:layout_marginRight="2dp"
android:layout_alignParentLeft="true"
android:layout_below="@id/from"
app:useSmallIcon="true"
android:visibility="gone"
tools:visibility="visible"/>
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/subject"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/from"
android:layout_toRightOf="@id/error"
android:layout_toLeftOf="@+id/archived"
android:layout_toRightOf="@id/indicators_parent"
android:layout_toLeftOf="@+id/delivery_status"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?attr/conversation_list_item_subject_color"
android:fontFamily="sans-serif-light"
@ -111,6 +112,14 @@
android:textSize="12sp"
/>
<org.thoughtcrime.securesms.components.DeliveryStatusView
android:id="@+id/delivery_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/date"
android:layout_toLeftOf="@+id/archived"
android:layout_alignWithParentIfMissing="true"
app:iconColor="?attr/conversation_list_item_subject_color"/>
</RelativeLayout>
</org.thoughtcrime.securesms.ConversationListItem>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout android:id="@+id/pending_indicator_stub"
android:layout_width="wrap_content"
android:paddingRight="2dp"
android:layout_height="wrap_content" />
<ImageView android:id="@+id/sent_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/ic_done_white_18dp"
android:paddingLeft="2dp"
android:paddingBottom="2dp"
android:visibility="gone"
android:contentDescription="@string/conversation_item_sent__delivered_description" />
<ImageView android:id="@+id/delivered_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:src="@drawable/ic_done_all_white_18dp"
android:paddingLeft="2dp"
android:paddingBottom="2dp"
android:visibility="gone"
android:contentDescription="@string/conversation_item_sent__delivered_description" />
</merge>

View File

@ -139,6 +139,14 @@
<attr name="backgroundColorHint" format="color" />
</declare-styleable>
<declare-styleable name="DeliveryStatusView">
<attr name="iconColor" format="color" />
</declare-styleable>
<declare-styleable name="AlertView">
<attr name="useSmallIcon" format="boolean" />
</declare-styleable>
<declare-styleable name="AudioView">
<attr name="tintColor" format="color" />
</declare-styleable>

View File

@ -23,7 +23,6 @@ import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
@ -31,7 +30,6 @@ import android.text.TextUtils;
import android.text.util.Linkify;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
@ -42,6 +40,8 @@ import android.widget.Toast;
import org.thoughtcrime.securesms.components.AudioView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.DeliveryStatusView;
import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
@ -90,22 +90,18 @@ public class ConversationItem extends LinearLayout
private boolean groupThread;
private Recipient recipient;
private View bodyBubble;
private TextView bodyText;
private TextView dateText;
private TextView indicatorText;
private TextView groupStatusText;
private ImageView secureImage;
private AvatarImageView contactPhoto;
private ImageView failedIndicator;
private ImageView deliveredIndicator;
private ImageView sentIndicator;
private View pendingIndicator;
private ImageView pendingApprovalIndicator;
private View bodyBubble;
private TextView bodyText;
private TextView dateText;
private TextView indicatorText;
private TextView groupStatusText;
private ImageView secureImage;
private AvatarImageView contactPhoto;
private DeliveryStatusView deliveryStatusIndicator;
private AlertView alertView;
private @NonNull Set<MessageRecord> batchSelected = new HashSet<>();
private @Nullable Recipients conversationRecipients;
private @NonNull StatusManager statusManager;
private @NonNull ThumbnailView mediaThumbnail;
private @NonNull AudioView audioView;
private @NonNull Button mmsDownloadButton;
@ -136,31 +132,20 @@ public class ConversationItem extends LinearLayout
super.onFinishInflate();
initializeAttributes();
ViewGroup pendingIndicatorStub = (ViewGroup) findViewById(R.id.pending_indicator_stub);
if (pendingIndicatorStub != null) {
LayoutInflater inflater = LayoutInflater.from(context);
if (Build.VERSION.SDK_INT >= 11) inflater.inflate(R.layout.conversation_item_pending_v11, pendingIndicatorStub, true);
else inflater.inflate(R.layout.conversation_item_pending, pendingIndicatorStub, true);
}
this.bodyText = (TextView) findViewById(R.id.conversation_item_body);
this.dateText = (TextView) findViewById(R.id.conversation_item_date);
this.indicatorText = (TextView) findViewById(R.id.indicator_text);
this.groupStatusText = (TextView) findViewById(R.id.group_message_status);
this.secureImage = (ImageView) findViewById(R.id.secure_indicator);
this.failedIndicator = (ImageView) findViewById(R.id.sms_failed_indicator);
this.mmsDownloadButton = (Button) findViewById(R.id.mms_download_button);
this.mmsDownloadingLabel = (TextView) findViewById(R.id.mms_label_downloading);
this.contactPhoto = (AvatarImageView) findViewById(R.id.contact_photo);
this.deliveredIndicator = (ImageView) findViewById(R.id.delivered_indicator);
this.sentIndicator = (ImageView) findViewById(R.id.sent_indicator);
this.bodyBubble = findViewById(R.id.body_bubble);
this.pendingApprovalIndicator = (ImageView) findViewById(R.id.pending_approval_indicator);
this.pendingIndicator = findViewById(R.id.pending_indicator);
this.mediaThumbnail = (ThumbnailView) findViewById(R.id.image_view);
this.audioView = (AudioView) findViewById(R.id.audio_view);
this.statusManager = new StatusManager(pendingIndicator, sentIndicator, deliveredIndicator, failedIndicator, pendingApprovalIndicator);
this.bodyText = (TextView) findViewById(R.id.conversation_item_body);
this.dateText = (TextView) findViewById(R.id.conversation_item_date);
this.indicatorText = (TextView) findViewById(R.id.indicator_text);
this.groupStatusText = (TextView) findViewById(R.id.group_message_status);
this.secureImage = (ImageView) findViewById(R.id.secure_indicator);
this.deliveryStatusIndicator = (DeliveryStatusView) findViewById(R.id.delivery_status);
this.alertView = (AlertView) findViewById(R.id.indicators_parent);
this.mmsDownloadButton = (Button) findViewById(R.id.mms_download_button);
this.mmsDownloadingLabel = (TextView) findViewById(R.id.mms_label_downloading);
this.contactPhoto = (AvatarImageView) findViewById(R.id.contact_photo);
this.bodyBubble = findViewById(R.id.body_bubble);
this.mediaThumbnail = (ThumbnailView) findViewById(R.id.image_view);
this.audioView = (AudioView) findViewById(R.id.audio_view);
setOnClickListener(new ClickListener(null));
PassthroughClickListener passthroughClickListener = new PassthroughClickListener();
@ -334,16 +319,25 @@ public class ConversationItem extends LinearLayout
dateText.setText(DateUtils.getExtendedRelativeTimeSpanString(getContext(), locale, timestamp));
if (messageRecord.isFailed()) setFailedStatusIcons();
else if (messageRecord.isPendingInsecureSmsFallback()) setFallbackStatusIcons();
else if (messageRecord.isPending()) statusManager.displayPending();
else if (messageRecord.isDelivered()) statusManager.displayDelivered();
else statusManager.displaySent();
if (messageRecord.isFailed()) {
setFailedStatusIcons();
} else if (messageRecord.isPendingInsecureSmsFallback()) {
setFallbackStatusIcons();
} else {
alertView.setNone();
if (!messageRecord.isOutgoing()) deliveryStatusIndicator.setNone();
else if (messageRecord.isPending()) deliveryStatusIndicator.setPending();
else if (messageRecord.isDelivered()) deliveryStatusIndicator.setDelivered();
else deliveryStatusIndicator.setSent();
}
}
private void setFailedStatusIcons() {
statusManager.displayFailed();
alertView.setFailed();
deliveryStatusIndicator.setNone();
dateText.setText(R.string.ConversationItem_error_not_delivered);
if (messageRecord.isOutgoing()) {
indicatorText.setText(R.string.ConversationItem_click_for_details);
indicatorText.setVisibility(View.VISIBLE);
@ -351,7 +345,8 @@ public class ConversationItem extends LinearLayout
}
private void setFallbackStatusIcons() {
statusManager.displayPendingApproval();
alertView.setPendingApproval();
deliveryStatusIndicator.setNone();
indicatorText.setVisibility(View.VISIBLE);
indicatorText.setText(R.string.ConversationItem_click_to_approve_unencrypted);
}
@ -612,72 +607,4 @@ public class ConversationItem extends LinearLayout
builder.show();
}
private static class StatusManager {
private final View pendingIndicator;
private final View sentIndicator;
private final View deliveredIndicator;
private final View failedIndicator;
private final View approvalIndicator;
public StatusManager(View pendingIndicator, View sentIndicator,
View deliveredIndicator, View failedIndicator,
View approvalIndicator)
{
this.pendingIndicator = pendingIndicator;
this.sentIndicator = sentIndicator;
this.deliveredIndicator = deliveredIndicator;
this.failedIndicator = failedIndicator;
this.approvalIndicator = approvalIndicator;
}
public void displayFailed() {
pendingIndicator.setVisibility(View.GONE);
sentIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.GONE);
approvalIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.VISIBLE);
}
public void displayPendingApproval() {
pendingIndicator.setVisibility(View.GONE);
sentIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.GONE);
approvalIndicator.setVisibility(View.VISIBLE);
}
public void displayPending() {
sentIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.GONE);
approvalIndicator.setVisibility(View.GONE);
pendingIndicator.setVisibility(View.VISIBLE);
}
public void displaySent() {
pendingIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.GONE);
approvalIndicator.setVisibility(View.GONE);
sentIndicator.setVisibility(View.VISIBLE);
}
public void displayDelivered() {
pendingIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.GONE);
approvalIndicator.setVisibility(View.GONE);
sentIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.VISIBLE);
}
}
}

View File

@ -27,12 +27,13 @@ import android.os.Handler;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.DeliveryStatusView;
import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.FromTextView;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
@ -63,13 +64,16 @@ public class ConversationListItem extends RelativeLayout
private final static Typeface BOLD_TYPEFACE = Typeface.create("sans-serif", Typeface.BOLD);
private final static Typeface LIGHT_TYPEFACE = Typeface.create("sans-serif-light", Typeface.NORMAL);
private Set<Long> selectedThreads;
private Recipients recipients;
private long threadId;
private TextView subjectView;
private FromTextView fromView;
private TextView dateView;
private TextView archivedView;
private Set<Long> selectedThreads;
private Recipients recipients;
private long threadId;
private TextView subjectView;
private FromTextView fromView;
private TextView dateView;
private TextView archivedView;
private DeliveryStatusView deliveryStatusIndicator;
private AlertView alertView;
private boolean read;
private AvatarImageView contactPhotoImage;
private ThumbnailView thumbnailView;
@ -93,12 +97,14 @@ public class ConversationListItem extends RelativeLayout
@Override
protected void onFinishInflate() {
super.onFinishInflate();
this.subjectView = (TextView) findViewById(R.id.subject);
this.fromView = (FromTextView) findViewById(R.id.from);
this.dateView = (TextView) findViewById(R.id.date);
this.contactPhotoImage = (AvatarImageView) findViewById(R.id.contact_photo_image);
this.thumbnailView = (ThumbnailView) findViewById(R.id.thumbnail);
this.archivedView = ViewUtil.findById(this, R.id.archived);
this.subjectView = (TextView) findViewById(R.id.subject);
this.fromView = (FromTextView) findViewById(R.id.from);
this.dateView = (TextView) findViewById(R.id.date);
this.deliveryStatusIndicator = (DeliveryStatusView) findViewById(R.id.delivery_status);
this.alertView = (AlertView) findViewById(R.id.indicators_parent);
this.contactPhotoImage = (AvatarImageView) findViewById(R.id.contact_photo_image);
this.thumbnailView = (ThumbnailView) findViewById(R.id.thumbnail);
this.archivedView = ViewUtil.findById(this, R.id.archived);
thumbnailView.setClickable(false);
}
@ -129,6 +135,7 @@ public class ConversationListItem extends RelativeLayout
this.archivedView.setVisibility(View.GONE);
}
setStatusIcons(thread);
setThumbnailSnippet(masterSecret, thread);
setBatchState(batchMode);
setBackground(thread);
@ -165,16 +172,35 @@ public class ConversationListItem extends RelativeLayout
LayoutParams subjectParams = (RelativeLayout.LayoutParams)this.subjectView.getLayoutParams();
subjectParams.addRule(RelativeLayout.LEFT_OF, R.id.thumbnail);
this.subjectView.setLayoutParams(subjectParams);
this.post(new ThumbnailPositioner(thumbnailView, archivedView, dateView));
this.post(new ThumbnailPositioner(thumbnailView, archivedView, deliveryStatusIndicator, dateView));
} else {
this.thumbnailView.setVisibility(View.GONE);
LayoutParams subjectParams = (RelativeLayout.LayoutParams)this.subjectView.getLayoutParams();
subjectParams.addRule(RelativeLayout.LEFT_OF, R.id.archived);
subjectParams.addRule(RelativeLayout.LEFT_OF, R.id.delivery_status);
this.subjectView.setLayoutParams(subjectParams);
}
}
private void setStatusIcons(ThreadRecord thread) {
if (!thread.isOutgoing()) {
deliveryStatusIndicator.setNone();
alertView.setNone();
} else if (thread.isFailed()) {
deliveryStatusIndicator.setNone();
alertView.setFailed();
} else if (thread.isPendingInsecureSmsFallback()) {
deliveryStatusIndicator.setNone();
alertView.setPendingApproval();
} else {
alertView.setNone();
if (thread.isPending()) deliveryStatusIndicator.setPending();
else if (thread.isDelivered()) deliveryStatusIndicator.setDelivered();
else deliveryStatusIndicator.setSent();
}
}
private void setBackground(ThreadRecord thread) {
if (thread.isRead()) setBackgroundResource(readBackground);
else setBackgroundResource(unreadBackround);
@ -204,20 +230,24 @@ public class ConversationListItem extends RelativeLayout
private final View thumbnailView;
private final View archivedView;
private final View deliveryStatusView;
private final View dateView;
public ThumbnailPositioner(View thumbnailView, View archivedView, View dateView) {
this.thumbnailView = thumbnailView;
this.archivedView = archivedView;
this.dateView = dateView;
public ThumbnailPositioner(View thumbnailView, View archivedView, View deliveryStatusView, View dateView) {
this.thumbnailView = thumbnailView;
this.archivedView = archivedView;
this.deliveryStatusView = deliveryStatusView;
this.dateView = dateView;
}
@Override
public void run() {
LayoutParams thumbnailParams = (RelativeLayout.LayoutParams)thumbnailView.getLayoutParams();
if (archivedView.getVisibility() == View.VISIBLE && archivedView.getWidth() > dateView.getWidth()) {
thumbnailParams.addRule(RelativeLayout.LEFT_OF, R.id.archived);
if (archivedView.getVisibility() == View.VISIBLE &&
(archivedView.getWidth() + deliveryStatusView.getWidth()) > dateView.getWidth())
{
thumbnailParams.addRule(RelativeLayout.LEFT_OF, R.id.delivery_status);
} else {
thumbnailParams.addRule(RelativeLayout.LEFT_OF, R.id.date);
}

View File

@ -0,0 +1,69 @@
package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build.VERSION_CODES;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import org.thoughtcrime.securesms.R;
public class AlertView extends LinearLayout {
private static final String TAG = AlertView.class.getSimpleName();
private ImageView approvalIndicator;
private ImageView failedIndicator;
public AlertView(Context context) {
this(context, null);
}
public AlertView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(attrs);
}
@TargetApi(VERSION_CODES.HONEYCOMB)
public AlertView(final Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize(attrs);
}
private void initialize(AttributeSet attrs) {
inflate(getContext(), R.layout.alert_view, this);
approvalIndicator = (ImageView) findViewById(R.id.pending_approval_indicator);
failedIndicator = (ImageView) findViewById(R.id.sms_failed_indicator);
if (attrs != null) {
TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.AlertView, 0, 0);
boolean useSmallIcon = typedArray.getBoolean(R.styleable.AlertView_useSmallIcon, false);
typedArray.recycle();
if (useSmallIcon) {
failedIndicator.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.ic_error_red_18dp));
}
}
}
public void setNone() {
this.setVisibility(View.GONE);
}
public void setPendingApproval() {
this.setVisibility(View.VISIBLE);
approvalIndicator.setVisibility(View.VISIBLE);
failedIndicator.setVisibility(View.GONE);
}
public void setFailed() {
this.setVisibility(View.VISIBLE);
approvalIndicator.setVisibility(View.GONE);
failedIndicator.setVisibility(View.VISIBLE);
}
}

View File

@ -0,0 +1,89 @@
package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import org.thoughtcrime.securesms.R;
import pl.tajchert.sample.DotsTextView;
public class DeliveryStatusView extends FrameLayout {
private static final String TAG = DeliveryStatusView.class.getSimpleName();
private final ViewGroup pendingIndicatorStub;
private final ImageView sentIndicator;
private final ImageView deliveredIndicator;
public DeliveryStatusView(Context context) {
this(context, null);
}
public DeliveryStatusView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DeliveryStatusView(final Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
inflate(context, R.layout.delivery_status_view, this);
this.deliveredIndicator = (ImageView) findViewById(R.id.delivered_indicator);
this.sentIndicator = (ImageView) findViewById(R.id.sent_indicator);
this.pendingIndicatorStub = (ViewGroup) findViewById(R.id.pending_indicator_stub);
int iconColor = Color.GRAY;
if (attrs != null) {
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DeliveryStatusView, 0, 0);
iconColor = typedArray.getColor(R.styleable.DeliveryStatusView_iconColor, iconColor);
typedArray.recycle();
}
deliveredIndicator.setColorFilter(iconColor, android.graphics.PorterDuff.Mode.MULTIPLY);
sentIndicator.setColorFilter(iconColor, android.graphics.PorterDuff.Mode.MULTIPLY);
if (Build.VERSION.SDK_INT >= 11) {
inflate(context, R.layout.conversation_item_pending_v11, pendingIndicatorStub);
DotsTextView pendingIndicator = (DotsTextView) findViewById(R.id.pending_indicator);
pendingIndicator.setDotsColor(iconColor);
} else {
inflate(context, R.layout.conversation_item_pending, pendingIndicatorStub);
TextView pendingIndicator = (TextView) findViewById(R.id.pending_indicator);
pendingIndicator.setTextColor(iconColor);
}
}
public void setNone() {
this.setVisibility(View.GONE);
}
public void setPending() {
this.setVisibility(View.VISIBLE);
pendingIndicatorStub.setVisibility(View.VISIBLE);
sentIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.GONE);
}
public void setSent() {
this.setVisibility(View.VISIBLE);
pendingIndicatorStub.setVisibility(View.GONE);
sentIndicator.setVisibility(View.VISIBLE);
deliveredIndicator.setVisibility(View.GONE);
}
public void setDelivered() {
this.setVisibility(View.VISIBLE);
pendingIndicatorStub.setVisibility(View.GONE);
sentIndicator.setVisibility(View.GONE);
deliveredIndicator.setVisibility(View.VISIBLE);
}
}

View File

@ -69,7 +69,8 @@ public class DatabaseFactory {
private static final int INTRODUCED_INVITE_REMINDERS_VERSION = 22;
private static final int INTRODUCED_CONVERSATION_LIST_THUMBNAILS_VERSION = 23;
private static final int INTRODUCED_ARCHIVE_VERSION = 24;
private static final int DATABASE_VERSION = 24;
private static final int INTRODUCED_CONVERSATION_LIST_STATUS_VERSION = 25;
private static final int DATABASE_VERSION = 25;
private static final String DATABASE_NAME = "messages.db";
private static final Object lock = new Object();
@ -784,6 +785,11 @@ public class DatabaseFactory {
db.execSQL("CREATE INDEX IF NOT EXISTS archived_index ON thread (archived)");
}
if (oldVersion < INTRODUCED_CONVERSATION_LIST_STATUS_VERSION) {
db.execSQL("ALTER TABLE thread ADD COLUMN status INTEGER DEFAULT -1");
db.execSQL("ALTER TABLE thread ADD COLUMN delivery_receipt_count INTEGER DEFAULT 0");
}
db.setTransactionSuccessful();
db.endTransaction();
}

View File

@ -214,6 +214,7 @@ public class MmsDatabase extends MessagingDatabase {
RECEIPT_COUNT + " = " + RECEIPT_COUNT + " + 1 WHERE " + ID + " = ?",
new String[] {String.valueOf(id)});
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
notifyConversationListeners(threadId);
}
} catch (InvalidNumberException e) {
@ -337,6 +338,8 @@ public class MmsDatabase extends MessagingDatabase {
db.execSQL("UPDATE " + TABLE_NAME +
" SET " + MESSAGE_BOX + " = (" + MESSAGE_BOX + " & " + (Types.TOTAL_MASK - maskOff) + " | " + maskOn + " )" +
" WHERE " + ID + " = ?", new String[] {id + ""});
DatabaseFactory.getThreadDatabase(context).update(getThreadIdForMessage(id), false);
}
public void markAsOutbox(long messageId) {

View File

@ -120,7 +120,6 @@ public class SmsDatabase extends MessagingDatabase {
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
notifyConversationListeners(threadId);
notifyConversationListListeners();
}
public long getThreadIdForMessage(long id) {
@ -265,12 +264,15 @@ public class SmsDatabase extends MessagingDatabase {
String ourAddress = canonicalizeNumber(context, cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
if (ourAddress.equals(theirAddress)) {
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
database.execSQL("UPDATE " + TABLE_NAME +
" SET " + RECEIPT_COUNT + " = " + RECEIPT_COUNT + " + 1 WHERE " +
ID + " = ?",
new String[] {String.valueOf(cursor.getLong(cursor.getColumnIndexOrThrow(ID)))});
notifyConversationListeners(cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID)));
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
notifyConversationListeners(threadId);
}
} catch (InvalidNumberException e) {
Log.w("SmsDatabase", e);

View File

@ -64,12 +64,17 @@ public class ThreadDatabase extends Database {
public static final String SNIPPET_TYPE = "snippet_type";
public static final String SNIPPET_URI = "snippet_uri";
public static final String ARCHIVED = "archived";
public static final String STATUS = "status";
public static final String RECEIPT_COUNT = "delivery_receipt_count";
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
DATE + " INTEGER DEFAULT 0, " + MESSAGE_COUNT + " INTEGER DEFAULT 0, " +
RECIPIENT_IDS + " TEXT, " + SNIPPET + " TEXT, " + SNIPPET_CHARSET + " INTEGER DEFAULT 0, " +
READ + " INTEGER DEFAULT 1, " + TYPE + " INTEGER DEFAULT 0, " + ERROR + " INTEGER DEFAULT 0, " +
SNIPPET_TYPE + " INTEGER DEFAULT 0, " + SNIPPET_URI + " TEXT DEFAULT NULL, " + ARCHIVED + " INTEGER DEFAULT 0);";
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" +
ID + " INTEGER PRIMARY KEY, " + DATE + " INTEGER DEFAULT 0, " +
MESSAGE_COUNT + " INTEGER DEFAULT 0, " + RECIPIENT_IDS + " TEXT, " + SNIPPET + " TEXT, " +
SNIPPET_CHARSET + " INTEGER DEFAULT 0, " + READ + " INTEGER DEFAULT 1, " +
TYPE + " INTEGER DEFAULT 0, " + ERROR + " INTEGER DEFAULT 0, " +
SNIPPET_TYPE + " INTEGER DEFAULT 0, " + SNIPPET_URI + " TEXT DEFAULT NULL, " +
ARCHIVED + " INTEGER DEFAULT 0, " + STATUS + " INTEGER DEFAULT 0, " +
RECEIPT_COUNT + " INTEGER DEFAULT 0);";
public static final String[] CREATE_INDEXS = {
"CREATE INDEX IF NOT EXISTS thread_recipient_ids_index ON " + TABLE_NAME + " (" + RECIPIENT_IDS + ");",
@ -126,14 +131,17 @@ public class ThreadDatabase extends Database {
return db.insert(TABLE_NAME, null, contentValues);
}
private void updateThread(long threadId, long count, String body, @Nullable Uri attachment, long date, long type, boolean unarchive)
private void updateThread(long threadId, long count, String body, @Nullable Uri attachment,
long date, int status, int receiptCount, long type, boolean unarchive)
{
ContentValues contentValues = new ContentValues(5);
ContentValues contentValues = new ContentValues(7);
contentValues.put(DATE, date - date % 1000);
contentValues.put(MESSAGE_COUNT, count);
contentValues.put(SNIPPET, body);
contentValues.put(SNIPPET_URI, attachment == null ? null : attachment.toString());
contentValues.put(SNIPPET_TYPE, type);
contentValues.put(STATUS, status);
contentValues.put(RECEIPT_COUNT, receiptCount);
if (unarchive) {
contentValues.put(ARCHIVED, 0);
@ -145,7 +153,7 @@ public class ThreadDatabase extends Database {
}
public void updateSnippet(long threadId, String snippet, @Nullable Uri attachment, long date, long type, boolean unarchive) {
ContentValues contentValues = new ContentValues(3);
ContentValues contentValues = new ContentValues(4);
contentValues.put(DATE, date - date % 1000);
contentValues.put(SNIPPET, snippet);
@ -479,10 +487,9 @@ public class ThreadDatabase extends Database {
if (record.isPush()) timestamp = record.getDateSent();
else timestamp = record.getDateReceived();
updateThread(threadId, count, record.getBody().getBody(),
getAttachmentUriFor(record), timestamp,
updateThread(threadId, count, record.getBody().getBody(), getAttachmentUriFor(record),
timestamp, record.getDeliveryStatus(), record.getReceiptCount(),
record.getType(), unarchive);
notifyConversationListListeners();
return false;
} else {
@ -549,10 +556,12 @@ public class ThreadDatabase extends Database {
long type = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_TYPE));
int distributionType = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.TYPE));
boolean archived = cursor.getInt(cursor.getColumnIndex(ThreadDatabase.ARCHIVED)) != 0;
int status = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.STATUS));
int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.RECEIPT_COUNT));
Uri snippetUri = getSnippetUri(cursor);
return new ThreadRecord(context, body, snippetUri, recipients, date, count,
read == 1, threadId, type, distributionType, archived);
return new ThreadRecord(context, body, snippetUri, recipients, date, count, read == 1,
threadId, receiptCount, status, type, distributionType, archived);
}
private DisplayRecord.Body getPlaintextBody(Cursor cursor) {

View File

@ -43,10 +43,11 @@ public class ConversationListLoader extends AbstractCursorLoader {
ThreadDatabase.ID, ThreadDatabase.DATE, ThreadDatabase.MESSAGE_COUNT,
ThreadDatabase.RECIPIENT_IDS, ThreadDatabase.SNIPPET, ThreadDatabase.READ,
ThreadDatabase.TYPE, ThreadDatabase.SNIPPET_TYPE, ThreadDatabase.SNIPPET_URI,
ThreadDatabase.ARCHIVED}, 1);
ThreadDatabase.ARCHIVED, ThreadDatabase.STATUS, ThreadDatabase.RECEIPT_COUNT}, 1);
switchToArchiveCursor.addRow(new Object[] {-1L, System.currentTimeMillis(), archivedCount,
"-1", null, 1, ThreadDatabase.DistributionTypes.ARCHIVE, 0, null, 0});
"-1", null, 1, ThreadDatabase.DistributionTypes.ARCHIVE,
0, null, 0, -1, 0});
cursorList.add(switchToArchiveCursor);
}

View File

@ -19,6 +19,7 @@ package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import android.text.SpannableString;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.recipients.Recipients;
@ -40,9 +41,11 @@ public abstract class DisplayRecord {
private final long dateReceived;
private final long threadId;
private final Body body;
private final int deliveryStatus;
private final int receiptCount;
public DisplayRecord(Context context, Body body, Recipients recipients, long dateSent,
long dateReceived, long threadId, long type)
long dateReceived, long threadId, int deliveryStatus, int receiptCount, long type)
{
this.context = context.getApplicationContext();
this.threadId = threadId;
@ -51,12 +54,29 @@ public abstract class DisplayRecord {
this.dateReceived = dateReceived;
this.type = type;
this.body = body;
this.receiptCount = receiptCount;
this.deliveryStatus = deliveryStatus;
}
public Body getBody() {
return body;
}
public boolean isFailed() {
return
MmsSmsColumns.Types.isFailedMessageType(type) ||
MmsSmsColumns.Types.isPendingSecureSmsFallbackType(type) ||
deliveryStatus >= SmsDatabase.Status.STATUS_FAILED;
}
public boolean isPending() {
return MmsSmsColumns.Types.isPendingMessageType(type);
}
public boolean isOutgoing() {
return MmsSmsColumns.Types.isOutgoingMessageType(type);
}
public abstract SpannableString getDisplayBody();
public Recipients getRecipients() {
@ -115,6 +135,23 @@ public abstract class DisplayRecord {
return SmsDatabase.Types.isMissedCall(type);
}
public int getDeliveryStatus() {
return deliveryStatus;
}
public int getReceiptCount() {
return receiptCount;
}
public boolean isDelivered() {
return (deliveryStatus >= SmsDatabase.Status.STATUS_COMPLETE &&
deliveryStatus < SmsDatabase.Status.STATUS_PENDING) || receiptCount > 0;
}
public boolean isPendingInsecureSmsFallback() {
return SmsDatabase.Types.isPendingInsecureSmsFallbackType(type);
}
public static class Body {
private final String body;
private final boolean plaintext;

View File

@ -21,6 +21,7 @@ import android.support.annotation.NonNull;
import android.text.SpannableString;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
@ -47,16 +48,15 @@ public class MediaMmsMessageRecord extends MessageRecord {
public MediaMmsMessageRecord(Context context, long id, Recipients recipients,
Recipient individualRecipient, int recipientDeviceId,
long dateSent, long dateReceived, int deliveredCount,
long dateSent, long dateReceived, int receiptCount,
long threadId, Body body,
@NonNull SlideDeck slideDeck,
int partCount, long mailbox,
List<IdentityKeyMismatch> mismatches,
List<NetworkFailure> failures)
{
super(context, id, body, recipients, individualRecipient, recipientDeviceId,
dateSent, dateReceived, threadId, DELIVERY_STATUS_NONE, deliveredCount, mailbox,
mismatches, failures);
super(context, id, body, recipients, individualRecipient, recipientDeviceId, dateSent,
dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox, mismatches, failures);
this.context = context.getApplicationContext();
this.partCount = partCount;

View File

@ -43,18 +43,11 @@ import java.util.List;
*/
public abstract class MessageRecord extends DisplayRecord {
public static final int DELIVERY_STATUS_NONE = 0;
public static final int DELIVERY_STATUS_RECEIVED = 1;
public static final int DELIVERY_STATUS_PENDING = 2;
public static final int DELIVERY_STATUS_FAILED = 3;
private static final int MAX_DISPLAY_LENGTH = 2000;
private final Recipient individualRecipient;
private final int recipientDeviceId;
private final long id;
private final int deliveryStatus;
private final int receiptCount;
private final List<IdentityKeyMismatch> mismatches;
private final List<NetworkFailure> networkFailures;
@ -65,12 +58,11 @@ public abstract class MessageRecord extends DisplayRecord {
List<IdentityKeyMismatch> mismatches,
List<NetworkFailure> networkFailures)
{
super(context, body, recipients, dateSent, dateReceived, threadId, type);
super(context, body, recipients, dateSent, dateReceived, threadId, deliveryStatus, receiptCount,
type);
this.id = id;
this.individualRecipient = individualRecipient;
this.recipientDeviceId = recipientDeviceId;
this.deliveryStatus = deliveryStatus;
this.receiptCount = receiptCount;
this.mismatches = mismatches;
this.networkFailures = networkFailures;
}
@ -78,21 +70,6 @@ public abstract class MessageRecord extends DisplayRecord {
public abstract boolean isMms();
public abstract boolean isMmsNotification();
public boolean isFailed() {
return
MmsSmsColumns.Types.isFailedMessageType(type) ||
MmsSmsColumns.Types.isPendingSecureSmsFallbackType(type) ||
getDeliveryStatus() == DELIVERY_STATUS_FAILED;
}
public boolean isOutgoing() {
return MmsSmsColumns.Types.isOutgoingMessageType(type);
}
public boolean isPending() {
return MmsSmsColumns.Types.isPendingMessageType(type);
}
public boolean isSecure() {
return MmsSmsColumns.Types.isSecureType(type);
}
@ -134,14 +111,6 @@ public abstract class MessageRecord extends DisplayRecord {
return id;
}
public int getDeliveryStatus() {
return deliveryStatus;
}
public boolean isDelivered() {
return getDeliveryStatus() == DELIVERY_STATUS_RECEIVED || receiptCount > 0;
}
public boolean isPush() {
return SmsDatabase.Types.isPushType(type) && !SmsDatabase.Types.isForcedSms(type);
}
@ -158,10 +127,6 @@ public abstract class MessageRecord extends DisplayRecord {
return SmsDatabase.Types.isProcessedKeyExchange(type);
}
public boolean isPendingInsecureSmsFallback() {
return SmsDatabase.Types.isPendingInsecureSmsFallbackType(type);
}
public boolean isIdentityMismatchFailure() {
return mismatches != null && !mismatches.isEmpty();
}

View File

@ -20,6 +20,7 @@ import android.content.Context;
import android.text.SpannableString;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
@ -51,7 +52,7 @@ public class NotificationMmsMessageRecord extends MessageRecord {
long expiry, int status, byte[] transactionId, long mailbox)
{
super(context, id, new Body("", true), recipients, individualRecipient, recipientDeviceId,
dateSent, dateReceived, threadId, DELIVERY_STATUS_NONE, receiptCount, mailbox,
dateSent, dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox,
new LinkedList<IdentityKeyMismatch>(), new LinkedList<NetworkFailure>());
this.contentLocation = contentLocation;

View File

@ -50,7 +50,7 @@ public class SmsMessageRecord extends MessageRecord {
int status, List<IdentityKeyMismatch> mismatches)
{
super(context, id, body, recipients, individualRecipient, recipientDeviceId,
dateSent, dateReceived, threadId, getGenericDeliveryStatus(status), receiptCount, type,
dateSent, dateReceived, threadId, status, receiptCount, type,
mismatches, new LinkedList<NetworkFailure>());
}
@ -104,16 +104,4 @@ public class SmsMessageRecord extends MessageRecord {
public boolean isMmsNotification() {
return false;
}
private static int getGenericDeliveryStatus(int status) {
if (status == SmsDatabase.Status.STATUS_NONE) {
return MessageRecord.DELIVERY_STATUS_NONE;
} else if (status >= SmsDatabase.Status.STATUS_FAILED) {
return MessageRecord.DELIVERY_STATUS_FAILED;
} else if (status >= SmsDatabase.Status.STATUS_PENDING) {
return MessageRecord.DELIVERY_STATUS_PENDING;
} else {
return MessageRecord.DELIVERY_STATUS_RECEIVED;
}
}
}

View File

@ -28,6 +28,7 @@ import android.text.style.StyleSpan;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.GroupUtil;
@ -48,9 +49,10 @@ public class ThreadRecord extends DisplayRecord {
public ThreadRecord(@NonNull Context context, @NonNull Body body, @Nullable Uri snippetUri,
@NonNull Recipients recipients, long date, long count, boolean read,
long threadId, long snippetType, int distributionType, boolean archived)
long threadId, int receiptCount, int status, long snippetType,
int distributionType, boolean archived)
{
super(context, body, recipients, date, date, threadId, snippetType);
super(context, body, recipients, date, date, threadId, status, receiptCount, snippetType);
this.context = context.getApplicationContext();
this.snippetUri = snippetUri;
this.count = count;