mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-30 13:35:18 +00:00
Show per-member delivery/read status on message info in groups
// FREEBIE
This commit is contained in:
parent
2b4064f3b7
commit
285947eb66
@ -6,14 +6,13 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="10dp"
|
android:padding="16dp">
|
||||||
android:paddingRight="10dp">
|
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.AvatarImageView
|
<org.thoughtcrime.securesms.components.AvatarImageView
|
||||||
android:id="@+id/contact_photo_image"
|
android:id="@+id/contact_photo_image"
|
||||||
android:foreground="@drawable/contact_photo_background"
|
android:foreground="@drawable/contact_photo_background"
|
||||||
android:layout_width="50dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="50dp"
|
android:layout_height="40dp"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
@ -28,6 +27,7 @@
|
|||||||
android:layout_marginTop="4dip"
|
android:layout_marginTop="4dip"
|
||||||
android:layout_marginBottom="4dip"
|
android:layout_marginBottom="4dip"
|
||||||
android:layout_toRightOf="@id/contact_photo_image"
|
android:layout_toRightOf="@id/contact_photo_image"
|
||||||
|
android:layout_toEndOf="@id/contact_photo_image"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
@ -77,7 +77,7 @@
|
|||||||
android:drawableLeft="@drawable/ic_error_white_18dp"
|
android:drawableLeft="@drawable/ic_error_white_18dp"
|
||||||
android:text="@string/message_recipients_list_item__view"
|
android:text="@string/message_recipients_list_item__view"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="gone" />
|
||||||
|
|
||||||
<Button android:id="@+id/resend_button"
|
<Button android:id="@+id/resend_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -91,8 +91,13 @@
|
|||||||
android:drawableLeft="@drawable/ic_refresh_white_18dp"
|
android:drawableLeft="@drawable/ic_refresh_white_18dp"
|
||||||
android:text="@string/message_recipients_list_item__resend"
|
android:text="@string/message_recipients_list_item__resend"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="gone" />
|
||||||
|
|
||||||
|
<org.thoughtcrime.securesms.components.DeliveryStatusView
|
||||||
|
android:id="@+id/delivery_status"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/**
|
/*
|
||||||
* Copyright (C) 2015 Open Whisper Systems
|
* Copyright (C) 2015 Open Whisper Systems
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -34,11 +34,14 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.MessageDetailsRecipientAdapter.RecipientDeliveryStatus;
|
||||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
|
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
|
||||||
|
import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
|
||||||
|
import org.thoughtcrime.securesms.database.GroupReceiptDatabase.GroupReceiptInfo;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
@ -153,12 +156,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onModified(final Recipient recipient) {
|
public void onModified(final Recipient recipient) {
|
||||||
Util.runOnMain(new Runnable() {
|
Util.runOnMain(() -> setActionBarColor(recipient.getColor()));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
setActionBarColor(recipient.getColor());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeResources() {
|
private void initializeResources() {
|
||||||
@ -241,7 +239,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRecipients(MessageRecord messageRecord, Recipient recipient, List<Recipient> recipients) {
|
private void updateRecipients(MessageRecord messageRecord, Recipient recipient, List<RecipientDeliveryStatus> recipients) {
|
||||||
final int toFromRes;
|
final int toFromRes;
|
||||||
if (messageRecord.isMms() && !messageRecord.isPush() && !messageRecord.isOutgoing()) {
|
if (messageRecord.isMms() && !messageRecord.isPush() && !messageRecord.isOutgoing()) {
|
||||||
toFromRes = R.string.message_details_header__with;
|
toFromRes = R.string.message_details_header__with;
|
||||||
@ -251,8 +249,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
toFromRes = R.string.message_details_header__from;
|
toFromRes = R.string.message_details_header__from;
|
||||||
}
|
}
|
||||||
toFrom.setText(toFromRes);
|
toFrom.setText(toFromRes);
|
||||||
conversationItem.bind(masterSecret, messageRecord, dynamicLanguage.getCurrentLocale(),
|
conversationItem.bind(masterSecret, messageRecord, dynamicLanguage.getCurrentLocale(), new HashSet<>(), recipient);
|
||||||
new HashSet<MessageRecord>(), recipient);
|
|
||||||
recipientsList.setAdapter(new MessageDetailsRecipientAdapter(this, masterSecret, messageRecord,
|
recipientsList.setAdapter(new MessageDetailsRecipientAdapter(this, masterSecret, messageRecord,
|
||||||
recipients, isPushGroup));
|
recipients, isPushGroup));
|
||||||
}
|
}
|
||||||
@ -319,11 +316,12 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MessageRecipientAsyncTask extends AsyncTask<Void,Void,List<Recipient>> {
|
private class MessageRecipientAsyncTask extends AsyncTask<Void,Void,List<RecipientDeliveryStatus>> {
|
||||||
private WeakReference<Context> weakContext;
|
|
||||||
private MessageRecord messageRecord;
|
|
||||||
|
|
||||||
public MessageRecipientAsyncTask(@NonNull Context context, @NonNull MessageRecord messageRecord) {
|
private final WeakReference<Context> weakContext;
|
||||||
|
private final MessageRecord messageRecord;
|
||||||
|
|
||||||
|
MessageRecipientAsyncTask(@NonNull Context context, @NonNull MessageRecord messageRecord) {
|
||||||
this.weakContext = new WeakReference<>(context);
|
this.weakContext = new WeakReference<>(context);
|
||||||
this.messageRecord = messageRecord;
|
this.messageRecord = messageRecord;
|
||||||
}
|
}
|
||||||
@ -333,27 +331,41 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Recipient> doInBackground(Void... voids) {
|
public List<RecipientDeliveryStatus> doInBackground(Void... voids) {
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
|
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
Log.w(TAG, "associated context is destroyed, finishing early");
|
Log.w(TAG, "associated context is destroyed, finishing early");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Recipient> recipients = new LinkedList<>();
|
List<RecipientDeliveryStatus> recipients = new LinkedList<>();
|
||||||
|
|
||||||
if (!messageRecord.getRecipient().isGroupRecipient()) {
|
if (!messageRecord.getRecipient().isGroupRecipient()) {
|
||||||
Log.w(TAG, "Recipient is not a group, resolving members immediately.");
|
recipients.add(new RecipientDeliveryStatus(messageRecord.getRecipient(), getStatusFor(messageRecord.getDeliveryReceiptCount(), messageRecord.getReadReceiptCount(), messageRecord.isPending()), -1));
|
||||||
recipients.add(messageRecord.getRecipient());
|
|
||||||
} else {
|
} else {
|
||||||
recipients.addAll(DatabaseFactory.getGroupDatabase(context).getGroupMembers(messageRecord.getRecipient().getAddress().toGroupString(), false));
|
List<GroupReceiptInfo> receiptInfoList = DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageRecord.getId());
|
||||||
|
|
||||||
|
if (receiptInfoList.isEmpty()) {
|
||||||
|
List<Recipient> group = DatabaseFactory.getGroupDatabase(context).getGroupMembers(messageRecord.getRecipient().getAddress().toGroupString(), false);
|
||||||
|
|
||||||
|
for (Recipient recipient : group) {
|
||||||
|
recipients.add(new RecipientDeliveryStatus(recipient, RecipientDeliveryStatus.Status.UNKNOWN, -1));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (GroupReceiptInfo info : receiptInfoList) {
|
||||||
|
recipients.add(new RecipientDeliveryStatus(Recipient.from(context, info.getAddress(), true),
|
||||||
|
getStatusFor(info.getStatus(), messageRecord.isPending()),
|
||||||
|
info.getTimestamp()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return recipients;
|
return recipients;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPostExecute(List<Recipient> recipients) {
|
public void onPostExecute(List<RecipientDeliveryStatus> recipients) {
|
||||||
if (getContext() == null) {
|
if (getContext() == null) {
|
||||||
Log.w(TAG, "AsyncTask finished with a destroyed context, leaving early.");
|
Log.w(TAG, "AsyncTask finished with a destroyed context, leaving early.");
|
||||||
return;
|
return;
|
||||||
@ -373,5 +385,22 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
metadataContainer.setVisibility(View.VISIBLE);
|
metadataContainer.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RecipientDeliveryStatus.Status getStatusFor(int deliveryReceiptCount, int readReceiptCount, boolean pending) {
|
||||||
|
if (readReceiptCount > 0) return RecipientDeliveryStatus.Status.READ;
|
||||||
|
else if (deliveryReceiptCount > 0) return RecipientDeliveryStatus.Status.DELIVERED;
|
||||||
|
else if (!pending) return RecipientDeliveryStatus.Status.SENT;
|
||||||
|
else return RecipientDeliveryStatus.Status.PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RecipientDeliveryStatus.Status getStatusFor(int groupStatus, boolean pending) {
|
||||||
|
if (groupStatus == GroupReceiptDatabase.STATUS_READ) return RecipientDeliveryStatus.Status.READ;
|
||||||
|
else if (groupStatus == GroupReceiptDatabase.STATUS_DELIVERED) return RecipientDeliveryStatus.Status.DELIVERED;
|
||||||
|
else if (groupStatus == GroupReceiptDatabase.STATUS_UNDELIVERED && !pending) return RecipientDeliveryStatus.Status.SENT;
|
||||||
|
else if (groupStatus == GroupReceiptDatabase.STATUS_UNDELIVERED) return RecipientDeliveryStatus.Status.PENDING;
|
||||||
|
else if (groupStatus == GroupReceiptDatabase.STATUS_UNKNOWN) return RecipientDeliveryStatus.Status.UNKNOWN;
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,39 +16,38 @@ import java.security.MessageDigest;
|
|||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsListView.RecyclerListener {
|
class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsListView.RecyclerListener {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final MasterSecret masterSecret;
|
private final MasterSecret masterSecret;
|
||||||
private final MessageRecord record;
|
private final MessageRecord record;
|
||||||
private final List<Recipient> recipients;
|
private final List<RecipientDeliveryStatus> members;
|
||||||
private final boolean isPushGroup;
|
private final boolean isPushGroup;
|
||||||
|
|
||||||
public MessageDetailsRecipientAdapter(Context context, MasterSecret masterSecret,
|
MessageDetailsRecipientAdapter(Context context, MasterSecret masterSecret, MessageRecord record,
|
||||||
MessageRecord record, List<Recipient> recipients,
|
List<RecipientDeliveryStatus> members, boolean isPushGroup)
|
||||||
boolean isPushGroup)
|
|
||||||
{
|
{
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.masterSecret = masterSecret;
|
this.masterSecret = masterSecret;
|
||||||
this.record = record;
|
this.record = record;
|
||||||
this.recipients = recipients;
|
|
||||||
this.isPushGroup = isPushGroup;
|
this.isPushGroup = isPushGroup;
|
||||||
|
this.members = members;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return recipients.size();
|
return members.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getItem(int position) {
|
public Object getItem(int position) {
|
||||||
return recipients.get(position);
|
return members.get(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getItemId(int position) {
|
public long getItemId(int position) {
|
||||||
try {
|
try {
|
||||||
return Conversions.byteArrayToLong(MessageDigest.getInstance("SHA1").digest(recipients.get(position).getAddress().serialize().getBytes()));
|
return Conversions.byteArrayToLong(MessageDigest.getInstance("SHA1").digest(members.get(position).recipient.getAddress().serialize().getBytes()));
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
@ -60,8 +59,9 @@ public class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsLi
|
|||||||
convertView = LayoutInflater.from(context).inflate(R.layout.message_recipient_list_item, parent, false);
|
convertView = LayoutInflater.from(context).inflate(R.layout.message_recipient_list_item, parent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Recipient recipient = recipients.get(position);
|
RecipientDeliveryStatus member = members.get(position);
|
||||||
((MessageRecipientListItem)convertView).set(masterSecret, record, recipient, isPushGroup);
|
|
||||||
|
((MessageRecipientListItem)convertView).set(masterSecret, record, member, isPushGroup);
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,4 +70,35 @@ public class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsLi
|
|||||||
((MessageRecipientListItem)view).unbind();
|
((MessageRecipientListItem)view).unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class RecipientDeliveryStatus {
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
UNKNOWN, PENDING, SENT, DELIVERED, READ
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Recipient recipient;
|
||||||
|
private final Status deliveryStatus;
|
||||||
|
private final long timestamp;
|
||||||
|
|
||||||
|
RecipientDeliveryStatus(Recipient recipient, Status deliveryStatus, long timestamp) {
|
||||||
|
this.recipient = recipient;
|
||||||
|
this.deliveryStatus = deliveryStatus;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status getDeliveryStatus() {
|
||||||
|
return deliveryStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Recipient getRecipient() {
|
||||||
|
return recipient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/**
|
/*
|
||||||
* Copyright (C) 2014 Open Whisper Systems
|
* Copyright (C) 2014 Open Whisper Systems
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -25,7 +25,9 @@ import android.widget.Button;
|
|||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.MessageDetailsRecipientAdapter.RecipientDeliveryStatus;
|
||||||
import org.thoughtcrime.securesms.components.AvatarImageView;
|
import org.thoughtcrime.securesms.components.AvatarImageView;
|
||||||
|
import org.thoughtcrime.securesms.components.DeliveryStatusView;
|
||||||
import org.thoughtcrime.securesms.components.FromTextView;
|
import org.thoughtcrime.securesms.components.FromTextView;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
@ -48,13 +50,14 @@ public class MessageRecipientListItem extends RelativeLayout
|
|||||||
{
|
{
|
||||||
private final static String TAG = MessageRecipientListItem.class.getSimpleName();
|
private final static String TAG = MessageRecipientListItem.class.getSimpleName();
|
||||||
|
|
||||||
private Recipient recipient;
|
private RecipientDeliveryStatus member;
|
||||||
private FromTextView fromView;
|
private FromTextView fromView;
|
||||||
private TextView errorDescription;
|
private TextView errorDescription;
|
||||||
private TextView actionDescription;
|
private TextView actionDescription;
|
||||||
private Button conflictButton;
|
private Button conflictButton;
|
||||||
private Button resendButton;
|
private Button resendButton;
|
||||||
private AvatarImageView contactPhotoImage;
|
private AvatarImageView contactPhotoImage;
|
||||||
|
private DeliveryStatusView deliveryStatusView;
|
||||||
|
|
||||||
public MessageRecipientListItem(Context context) {
|
public MessageRecipientListItem(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@ -73,18 +76,19 @@ public class MessageRecipientListItem extends RelativeLayout
|
|||||||
this.contactPhotoImage = (AvatarImageView) findViewById(R.id.contact_photo_image);
|
this.contactPhotoImage = (AvatarImageView) findViewById(R.id.contact_photo_image);
|
||||||
this.conflictButton = (Button) findViewById(R.id.conflict_button);
|
this.conflictButton = (Button) findViewById(R.id.conflict_button);
|
||||||
this.resendButton = (Button) findViewById(R.id.resend_button);
|
this.resendButton = (Button) findViewById(R.id.resend_button);
|
||||||
|
this.deliveryStatusView = (DeliveryStatusView) findViewById(R.id.delivery_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(final MasterSecret masterSecret,
|
public void set(final MasterSecret masterSecret,
|
||||||
final MessageRecord record,
|
final MessageRecord record,
|
||||||
final Recipient recipient,
|
final RecipientDeliveryStatus member,
|
||||||
final boolean isPushGroup)
|
final boolean isPushGroup)
|
||||||
{
|
{
|
||||||
this.recipient = recipient;
|
this.member = member;
|
||||||
|
|
||||||
recipient.addListener(this);
|
member.getRecipient().addListener(this);
|
||||||
fromView.setText(recipient);
|
fromView.setText(member.getRecipient());
|
||||||
contactPhotoImage.setAvatar(recipient, false);
|
contactPhotoImage.setAvatar(member.getRecipient(), false);
|
||||||
setIssueIndicators(masterSecret, record, isPushGroup);
|
setIssueIndicators(masterSecret, record, isPushGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,12 +106,7 @@ public class MessageRecipientListItem extends RelativeLayout
|
|||||||
conflictButton.setVisibility(View.VISIBLE);
|
conflictButton.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
errorText = getContext().getString(R.string.MessageDetailsRecipient_new_safety_number);
|
errorText = getContext().getString(R.string.MessageDetailsRecipient_new_safety_number);
|
||||||
conflictButton.setOnClickListener(new OnClickListener() {
|
conflictButton.setOnClickListener(v -> new ConfirmIdentityDialog(getContext(), masterSecret, record, keyMismatch).show());
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
new ConfirmIdentityDialog(getContext(), masterSecret, record, keyMismatch).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (networkFailure != null || (!isPushGroup && record.isFailed())) {
|
} else if (networkFailure != null || (!isPushGroup && record.isFailed())) {
|
||||||
resendButton.setVisibility(View.VISIBLE);
|
resendButton.setVisibility(View.VISIBLE);
|
||||||
resendButton.setEnabled(true);
|
resendButton.setEnabled(true);
|
||||||
@ -115,17 +114,27 @@ public class MessageRecipientListItem extends RelativeLayout
|
|||||||
conflictButton.setVisibility(View.GONE);
|
conflictButton.setVisibility(View.GONE);
|
||||||
|
|
||||||
errorText = getContext().getString(R.string.MessageDetailsRecipient_failed_to_send);
|
errorText = getContext().getString(R.string.MessageDetailsRecipient_failed_to_send);
|
||||||
resendButton.setOnClickListener(new OnClickListener() {
|
resendButton.setOnClickListener(v -> {
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
resendButton.setVisibility(View.GONE);
|
resendButton.setVisibility(View.GONE);
|
||||||
errorDescription.setVisibility(View.GONE);
|
errorDescription.setVisibility(View.GONE);
|
||||||
actionDescription.setVisibility(View.VISIBLE);
|
actionDescription.setVisibility(View.VISIBLE);
|
||||||
actionDescription.setText(R.string.message_recipients_list_item__resending);
|
actionDescription.setText(R.string.message_recipients_list_item__resending);
|
||||||
new ResendAsyncTask(masterSecret, record, networkFailure).execute();
|
new ResendAsyncTask(masterSecret, record, networkFailure).execute();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.PENDING || member.getDeliveryStatus() == RecipientDeliveryStatus.Status.UNKNOWN) {
|
||||||
|
deliveryStatusView.setVisibility(View.GONE);
|
||||||
|
} else if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.READ) {
|
||||||
|
deliveryStatusView.setRead();
|
||||||
|
deliveryStatusView.setVisibility(View.VISIBLE);
|
||||||
|
} else if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.DELIVERED) {
|
||||||
|
deliveryStatusView.setDelivered();
|
||||||
|
deliveryStatusView.setVisibility(View.VISIBLE);
|
||||||
|
} else if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.SENT) {
|
||||||
|
deliveryStatusView.setSent();
|
||||||
|
deliveryStatusView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
resendButton.setVisibility(View.GONE);
|
resendButton.setVisibility(View.GONE);
|
||||||
conflictButton.setVisibility(View.GONE);
|
conflictButton.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
@ -137,7 +146,7 @@ public class MessageRecipientListItem extends RelativeLayout
|
|||||||
private NetworkFailure getNetworkFailure(final MessageRecord record) {
|
private NetworkFailure getNetworkFailure(final MessageRecord record) {
|
||||||
if (record.hasNetworkFailures()) {
|
if (record.hasNetworkFailures()) {
|
||||||
for (final NetworkFailure failure : record.getNetworkFailures()) {
|
for (final NetworkFailure failure : record.getNetworkFailures()) {
|
||||||
if (failure.getAddress().equals(recipient.getAddress())) {
|
if (failure.getAddress().equals(member.getRecipient().getAddress())) {
|
||||||
return failure;
|
return failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,7 +157,7 @@ public class MessageRecipientListItem extends RelativeLayout
|
|||||||
private IdentityKeyMismatch getKeyMismatch(final MessageRecord record) {
|
private IdentityKeyMismatch getKeyMismatch(final MessageRecord record) {
|
||||||
if (record.isIdentityMismatchFailure()) {
|
if (record.isIdentityMismatchFailure()) {
|
||||||
for (final IdentityKeyMismatch mismatch : record.getIdentityKeyMismatches()) {
|
for (final IdentityKeyMismatch mismatch : record.getIdentityKeyMismatches()) {
|
||||||
if (mismatch.getAddress().equals(recipient.getAddress())) {
|
if (mismatch.getAddress().equals(member.getRecipient().getAddress())) {
|
||||||
return mismatch;
|
return mismatch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +166,7 @@ public class MessageRecipientListItem extends RelativeLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void unbind() {
|
public void unbind() {
|
||||||
if (this.recipient != null) this.recipient.removeListener(this);
|
if (this.member != null && this.member.getRecipient() != null) this.member.getRecipient().removeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -107,7 +107,8 @@ public class DatabaseFactory {
|
|||||||
private static final int PROFILE_SHARING_APPROVAL = 42;
|
private static final int PROFILE_SHARING_APPROVAL = 42;
|
||||||
private static final int UNSEEN_NUMBER_OFFER = 43;
|
private static final int UNSEEN_NUMBER_OFFER = 43;
|
||||||
private static final int READ_RECEIPTS = 44;
|
private static final int READ_RECEIPTS = 44;
|
||||||
private static final int DATABASE_VERSION = 44;
|
private static final int GROUP_RECEIPT_TRACKING = 45;
|
||||||
|
private static final int DATABASE_VERSION = 45;
|
||||||
|
|
||||||
private static final String DATABASE_NAME = "messages.db";
|
private static final String DATABASE_NAME = "messages.db";
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
@ -129,6 +130,7 @@ public class DatabaseFactory {
|
|||||||
private final GroupDatabase groupDatabase;
|
private final GroupDatabase groupDatabase;
|
||||||
private final RecipientDatabase recipientDatabase;
|
private final RecipientDatabase recipientDatabase;
|
||||||
private final ContactsDatabase contactsDatabase;
|
private final ContactsDatabase contactsDatabase;
|
||||||
|
private final GroupReceiptDatabase groupReceiptDatabase;
|
||||||
|
|
||||||
public static DatabaseFactory getInstance(Context context) {
|
public static DatabaseFactory getInstance(Context context) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
@ -191,6 +193,10 @@ public class DatabaseFactory {
|
|||||||
return getInstance(context).contactsDatabase;
|
return getInstance(context).contactsDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static GroupReceiptDatabase getGroupReceiptDatabase(Context context) {
|
||||||
|
return getInstance(context).groupReceiptDatabase;
|
||||||
|
}
|
||||||
|
|
||||||
private DatabaseFactory(Context context) {
|
private DatabaseFactory(Context context) {
|
||||||
this.databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
|
this.databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
this.sms = new SmsDatabase(context, databaseHelper);
|
this.sms = new SmsDatabase(context, databaseHelper);
|
||||||
@ -205,6 +211,7 @@ public class DatabaseFactory {
|
|||||||
this.pushDatabase = new PushDatabase(context, databaseHelper);
|
this.pushDatabase = new PushDatabase(context, databaseHelper);
|
||||||
this.groupDatabase = new GroupDatabase(context, databaseHelper);
|
this.groupDatabase = new GroupDatabase(context, databaseHelper);
|
||||||
this.recipientDatabase = new RecipientDatabase(context, databaseHelper);
|
this.recipientDatabase = new RecipientDatabase(context, databaseHelper);
|
||||||
|
this.groupReceiptDatabase = new GroupReceiptDatabase(context, databaseHelper);
|
||||||
this.contactsDatabase = new ContactsDatabase(context);
|
this.contactsDatabase = new ContactsDatabase(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +230,7 @@ public class DatabaseFactory {
|
|||||||
this.pushDatabase.reset(databaseHelper);
|
this.pushDatabase.reset(databaseHelper);
|
||||||
this.groupDatabase.reset(databaseHelper);
|
this.groupDatabase.reset(databaseHelper);
|
||||||
this.recipientDatabase.reset(databaseHelper);
|
this.recipientDatabase.reset(databaseHelper);
|
||||||
|
this.groupReceiptDatabase.reset(databaseHelper);
|
||||||
old.close();
|
old.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,6 +544,7 @@ public class DatabaseFactory {
|
|||||||
db.execSQL(PushDatabase.CREATE_TABLE);
|
db.execSQL(PushDatabase.CREATE_TABLE);
|
||||||
db.execSQL(GroupDatabase.CREATE_TABLE);
|
db.execSQL(GroupDatabase.CREATE_TABLE);
|
||||||
db.execSQL(RecipientDatabase.CREATE_TABLE);
|
db.execSQL(RecipientDatabase.CREATE_TABLE);
|
||||||
|
db.execSQL(GroupReceiptDatabase.CREATE_TABLE);
|
||||||
|
|
||||||
executeStatements(db, SmsDatabase.CREATE_INDEXS);
|
executeStatements(db, SmsDatabase.CREATE_INDEXS);
|
||||||
executeStatements(db, MmsDatabase.CREATE_INDEXS);
|
executeStatements(db, MmsDatabase.CREATE_INDEXS);
|
||||||
@ -543,6 +552,7 @@ public class DatabaseFactory {
|
|||||||
executeStatements(db, ThreadDatabase.CREATE_INDEXS);
|
executeStatements(db, ThreadDatabase.CREATE_INDEXS);
|
||||||
executeStatements(db, DraftDatabase.CREATE_INDEXS);
|
executeStatements(db, DraftDatabase.CREATE_INDEXS);
|
||||||
executeStatements(db, GroupDatabase.CREATE_INDEXS);
|
executeStatements(db, GroupDatabase.CREATE_INDEXS);
|
||||||
|
executeStatements(db, GroupReceiptDatabase.CREATE_INDEXES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1328,6 +1338,11 @@ public class DatabaseFactory {
|
|||||||
db.execSQL("ALTER TABLE thread ADD COLUMN read_receipt_count INTEGER DEFAULT 0");
|
db.execSQL("ALTER TABLE thread ADD COLUMN read_receipt_count INTEGER DEFAULT 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldVersion < GROUP_RECEIPT_TRACKING) {
|
||||||
|
db.execSQL("CREATE TABLE group_receipts (_id INTEGER PRIMARY KEY, mms_id INTEGER, address TEXT, status INTEGER, timestamp INTEGER)");
|
||||||
|
db.execSQL("CREATE INDEX IF NOT EXISTS group_receipt_mms_id_index ON group_receipts (mms_id)");
|
||||||
|
}
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,112 @@
|
|||||||
|
package org.thoughtcrime.securesms.database;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GroupReceiptDatabase extends Database {
|
||||||
|
|
||||||
|
public static final String TABLE_NAME = "group_receipts";
|
||||||
|
|
||||||
|
private static final String ID = "_id";
|
||||||
|
private static final String MMS_ID = "mms_id";
|
||||||
|
private static final String ADDRESS = "address";
|
||||||
|
private static final String STATUS = "status";
|
||||||
|
private static final String TIMESTAMP = "timestamp";
|
||||||
|
|
||||||
|
public static final int STATUS_UNKNOWN = -1;
|
||||||
|
public static final int STATUS_UNDELIVERED = 0;
|
||||||
|
public static final int STATUS_DELIVERED = 1;
|
||||||
|
public static final int STATUS_READ = 2;
|
||||||
|
|
||||||
|
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
||||||
|
MMS_ID + " INTEGER, " + ADDRESS + " TEXT, " + STATUS + " INTEGER, " + TIMESTAMP + " INTEGER);";
|
||||||
|
|
||||||
|
public static final String[] CREATE_INDEXES = {
|
||||||
|
"CREATE INDEX IF NOT EXISTS group_receipt_mms_id_index ON " + TABLE_NAME + " (" + MMS_ID + ");",
|
||||||
|
};
|
||||||
|
|
||||||
|
public GroupReceiptDatabase(Context context, SQLiteOpenHelper databaseHelper) {
|
||||||
|
super(context, databaseHelper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insert(List<Address> addresses, long mmsId, int status, long timestamp) {
|
||||||
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
|
|
||||||
|
for (Address address : addresses) {
|
||||||
|
ContentValues values = new ContentValues(4);
|
||||||
|
values.put(MMS_ID, mmsId);
|
||||||
|
values.put(ADDRESS, address.serialize());
|
||||||
|
values.put(STATUS, status);
|
||||||
|
values.put(TIMESTAMP, timestamp);
|
||||||
|
|
||||||
|
db.insert(TABLE_NAME, null, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(Address address, long mmsId, int status, long timestamp) {
|
||||||
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
|
ContentValues values = new ContentValues(2);
|
||||||
|
values.put(STATUS, status);
|
||||||
|
values.put(TIMESTAMP, timestamp);
|
||||||
|
|
||||||
|
db.update(TABLE_NAME, values, MMS_ID + " = ? AND " + ADDRESS + " = ? AND " + STATUS + " < ?",
|
||||||
|
new String[] {String.valueOf(mmsId), address.serialize(), String.valueOf(status)});
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NonNull List<GroupReceiptInfo> getGroupReceiptInfo(long mmsId) {
|
||||||
|
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||||
|
List<GroupReceiptInfo> results = new LinkedList<>();
|
||||||
|
|
||||||
|
try (Cursor cursor = db.query(TABLE_NAME, null, MMS_ID + " = ?", new String[] {String.valueOf(mmsId)}, null, null, null)) {
|
||||||
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
|
results.add(new GroupReceiptInfo(Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS))),
|
||||||
|
cursor.getInt(cursor.getColumnIndexOrThrow(STATUS)),
|
||||||
|
cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteRowsForMessage(long mmsId) {
|
||||||
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
|
db.delete(TABLE_NAME, MMS_ID + " = ?", new String[] {String.valueOf(mmsId)});
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteAllRows() {
|
||||||
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
|
db.delete(TABLE_NAME, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GroupReceiptInfo {
|
||||||
|
private final Address address;
|
||||||
|
private final int status;
|
||||||
|
private final long timestamp;
|
||||||
|
|
||||||
|
public GroupReceiptInfo(Address address, int status, long timestamp) {
|
||||||
|
this.address = address;
|
||||||
|
this.status = status;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,7 @@ import android.text.TextUtils;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import com.annimon.stream.Stream;
|
||||||
import com.google.android.mms.pdu_alt.NotificationInd;
|
import com.google.android.mms.pdu_alt.NotificationInd;
|
||||||
import com.google.android.mms.pdu_alt.PduHeaders;
|
import com.google.android.mms.pdu_alt.PduHeaders;
|
||||||
|
|
||||||
@ -125,7 +126,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
CONTENT_LOCATION, EXPIRY, MESSAGE_TYPE,
|
CONTENT_LOCATION, EXPIRY, MESSAGE_TYPE,
|
||||||
MESSAGE_SIZE, STATUS, TRANSACTION_ID,
|
MESSAGE_SIZE, STATUS, TRANSACTION_ID,
|
||||||
BODY, PART_COUNT, ADDRESS, ADDRESS_DEVICE_ID,
|
BODY, PART_COUNT, ADDRESS, ADDRESS_DEVICE_ID,
|
||||||
DELIVERY_RECEIPT_COUNT, MISMATCHED_IDENTITIES, NETWORK_FAILURE, SUBSCRIPTION_ID,
|
DELIVERY_RECEIPT_COUNT, READ_RECEIPT_COUNT, MISMATCHED_IDENTITIES, NETWORK_FAILURE, SUBSCRIPTION_ID,
|
||||||
EXPIRES_IN, EXPIRE_STARTED, NOTIFIED,
|
EXPIRES_IN, EXPIRE_STARTED, NOTIFIED,
|
||||||
AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.ROW_ID + " AS " + AttachmentDatabase.ATTACHMENT_ID_ALIAS,
|
AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.ROW_ID + " AS " + AttachmentDatabase.ATTACHMENT_ID_ALIAS,
|
||||||
AttachmentDatabase.UNIQUE_ID,
|
AttachmentDatabase.UNIQUE_ID,
|
||||||
@ -194,7 +195,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void incrementReceiptCount(SyncMessageId messageId, boolean deliveryReceipt, boolean readReceipt) {
|
public void incrementReceiptCount(SyncMessageId messageId, long timestamp, boolean deliveryReceipt, boolean readReceipt) {
|
||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
@ -211,6 +212,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
if (ourAddress.equals(theirAddress) || theirAddress.isGroup()) {
|
if (ourAddress.equals(theirAddress) || theirAddress.isGroup()) {
|
||||||
long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||||
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
|
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
|
||||||
|
int status = deliveryReceipt ? GroupReceiptDatabase.STATUS_DELIVERED : GroupReceiptDatabase.STATUS_READ;
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
@ -218,6 +220,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
columnName + " = " + columnName + " + 1 WHERE " + ID + " = ?",
|
columnName + " = " + columnName + " + 1 WHERE " + ID + " = ?",
|
||||||
new String[] {String.valueOf(id)});
|
new String[] {String.valueOf(id)});
|
||||||
|
|
||||||
|
DatabaseFactory.getGroupReceiptDatabase(context).update(ourAddress, id, status, timestamp);
|
||||||
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
|
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
|
||||||
notifyConversationListeners(threadId);
|
notifyConversationListeners(threadId);
|
||||||
}
|
}
|
||||||
@ -814,6 +817,14 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
|
|
||||||
long messageId = insertMediaMessage(masterSecret, message.getBody(), message.getAttachments(), contentValues, insertListener);
|
long messageId = insertMediaMessage(masterSecret, message.getBody(), message.getAttachments(), contentValues, insertListener);
|
||||||
|
|
||||||
|
if (message.getRecipient().getAddress().isGroup()) {
|
||||||
|
List<Recipient> members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(message.getRecipient().getAddress().toGroupString(), false);
|
||||||
|
GroupReceiptDatabase receiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);
|
||||||
|
|
||||||
|
receiptDatabase.insert(Stream.of(members).map(Recipient::getAddress).toList(),
|
||||||
|
messageId, GroupReceiptDatabase.STATUS_UNDELIVERED, message.getSentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
||||||
DatabaseFactory.getThreadDatabase(context).setHasSent(threadId, true);
|
DatabaseFactory.getThreadDatabase(context).setHasSent(threadId, true);
|
||||||
jobManager.add(new TrimThreadJob(context, threadId));
|
jobManager.add(new TrimThreadJob(context, threadId));
|
||||||
@ -891,6 +902,9 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
|
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
|
||||||
attachmentDatabase.deleteAttachmentsForMessage(messageId);
|
attachmentDatabase.deleteAttachmentsForMessage(messageId);
|
||||||
|
|
||||||
|
GroupReceiptDatabase groupReceiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);
|
||||||
|
groupReceiptDatabase.deleteRowsForMessage(messageId);
|
||||||
|
|
||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
database.delete(TABLE_NAME, ID_WHERE, new String[] {messageId+""});
|
database.delete(TABLE_NAME, ID_WHERE, new String[] {messageId+""});
|
||||||
boolean threadDeleted = DatabaseFactory.getThreadDatabase(context).update(threadId, false);
|
boolean threadDeleted = DatabaseFactory.getThreadDatabase(context).update(threadId, false);
|
||||||
@ -972,6 +986,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
|
|
||||||
public void deleteAllThreads() {
|
public void deleteAllThreads() {
|
||||||
DatabaseFactory.getAttachmentDatabase(context).deleteAllAttachments();
|
DatabaseFactory.getAttachmentDatabase(context).deleteAllAttachments();
|
||||||
|
DatabaseFactory.getGroupReceiptDatabase(context).deleteAllRows();
|
||||||
|
|
||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
database.delete(TABLE_NAME, null, null);
|
database.delete(TABLE_NAME, null, null);
|
||||||
|
@ -137,14 +137,14 @@ public class MmsSmsDatabase extends Database {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void incrementDeliveryReceiptCount(SyncMessageId syncMessageId) {
|
public void incrementDeliveryReceiptCount(SyncMessageId syncMessageId, long timestamp) {
|
||||||
DatabaseFactory.getSmsDatabase(context).incrementReceiptCount(syncMessageId, true, false);
|
DatabaseFactory.getSmsDatabase(context).incrementReceiptCount(syncMessageId, true, false);
|
||||||
DatabaseFactory.getMmsDatabase(context).incrementReceiptCount(syncMessageId, true, false);
|
DatabaseFactory.getMmsDatabase(context).incrementReceiptCount(syncMessageId, timestamp, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void incrementReadReceiptCount(SyncMessageId syncMessageId) {
|
public void incrementReadReceiptCount(SyncMessageId syncMessageId, long timestamp) {
|
||||||
DatabaseFactory.getSmsDatabase(context).incrementReceiptCount(syncMessageId, false, true);
|
DatabaseFactory.getSmsDatabase(context).incrementReceiptCount(syncMessageId, false, true);
|
||||||
DatabaseFactory.getMmsDatabase(context).incrementReceiptCount(syncMessageId, false, true);
|
DatabaseFactory.getMmsDatabase(context).incrementReceiptCount(syncMessageId, timestamp, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cursor queryTables(String[] projection, String selection, String order, String limit) {
|
private Cursor queryTables(String[] projection, String selection, String order, String limit) {
|
||||||
|
@ -836,7 +836,7 @@ public class PushDecryptJob extends ContextJob {
|
|||||||
for (long timestamp : message.getTimestamps()) {
|
for (long timestamp : message.getTimestamps()) {
|
||||||
Log.w(TAG, String.format("Received encrypted delivery receipt: (XXXXX, %d)", timestamp));
|
Log.w(TAG, String.format("Received encrypted delivery receipt: (XXXXX, %d)", timestamp));
|
||||||
DatabaseFactory.getMmsSmsDatabase(context)
|
DatabaseFactory.getMmsSmsDatabase(context)
|
||||||
.incrementDeliveryReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()), timestamp));
|
.incrementDeliveryReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()), timestamp), System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -848,7 +848,7 @@ public class PushDecryptJob extends ContextJob {
|
|||||||
Log.w(TAG, String.format("Received encrypted read receipt: (XXXXX, %d)", timestamp));
|
Log.w(TAG, String.format("Received encrypted read receipt: (XXXXX, %d)", timestamp));
|
||||||
|
|
||||||
DatabaseFactory.getMmsSmsDatabase(context)
|
DatabaseFactory.getMmsSmsDatabase(context)
|
||||||
.incrementReadReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()), timestamp));
|
.incrementReadReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()), timestamp), envelope.getTimestamp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,15 @@ import android.support.annotation.NonNull;
|
|||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
|
||||||
|
import org.thoughtcrime.securesms.database.GroupReceiptDatabase.GroupReceiptInfo;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||||
@ -137,7 +141,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
|||||||
{
|
{
|
||||||
String groupId = message.getRecipient().getAddress().toGroupString();
|
String groupId = message.getRecipient().getAddress().toGroupString();
|
||||||
Optional<byte[]> profileKey = getProfileKey(message.getRecipient());
|
Optional<byte[]> profileKey = getProfileKey(message.getRecipient());
|
||||||
List<Recipient> recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
|
List<Address> recipients = getGroupMessageRecipients(groupId, messageId);
|
||||||
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
|
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
|
||||||
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
|
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
|
||||||
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
|
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
|
||||||
@ -181,13 +185,15 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
|||||||
return addresses;
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SignalServiceAddress> getPushAddresses(List<Recipient> recipients) {
|
private List<SignalServiceAddress> getPushAddresses(List<Address> addresses) {
|
||||||
List<SignalServiceAddress> addresses = new LinkedList<>();
|
return Stream.of(addresses).map(this::getPushAddress).toList();
|
||||||
|
|
||||||
for (Recipient recipient : recipients) {
|
|
||||||
addresses.add(getPushAddress(recipient.getAddress()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return addresses;
|
private @NonNull List<Address> getGroupMessageRecipients(String groupId, long messageId) {
|
||||||
|
List<GroupReceiptInfo> destinations = DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageId);
|
||||||
|
if (!destinations.isEmpty()) return Stream.of(destinations).map(GroupReceiptInfo::getAddress).toList();
|
||||||
|
|
||||||
|
List<Recipient> members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
|
||||||
|
return Stream.of(members).map(Recipient::getAddress).toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ public abstract class PushReceivedJob extends ContextJob {
|
|||||||
private void handleReceipt(SignalServiceEnvelope envelope) {
|
private void handleReceipt(SignalServiceEnvelope envelope) {
|
||||||
Log.w(TAG, String.format("Received receipt: (XXXXX, %d)", envelope.getTimestamp()));
|
Log.w(TAG, String.format("Received receipt: (XXXXX, %d)", envelope.getTimestamp()));
|
||||||
DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()),
|
DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()),
|
||||||
envelope.getTimestamp()));
|
envelope.getTimestamp()), System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isActiveNumber(@NonNull Recipient recipient) {
|
private boolean isActiveNumber(@NonNull Recipient recipient) {
|
||||||
|
Loading…
Reference in New Issue
Block a user