Add pre-alpha receive support for remote delete.

This commit is contained in:
Greyson Parrelli
2020-04-15 14:56:58 -04:00
parent 456bcf3d57
commit 6ecd3b59fd
29 changed files with 595 additions and 82 deletions

View File

@@ -110,6 +110,7 @@ import org.thoughtcrime.securesms.stickers.StickerPackPreviewActivity;
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.HtmlUtil;
import org.thoughtcrime.securesms.util.RemoteDeleteUtil;
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -602,6 +603,14 @@ public class ConversationFragment extends Fragment
}
private void handleDeleteMessages(final Set<MessageRecord> messageRecords) {
if (FeatureFlags.remoteDelete()) {
buildRemoteDeleteConfirmationDialog(messageRecords).show();
} else {
buildLegacyDeleteConfirmationDialog(messageRecords).show();
}
}
private AlertDialog.Builder buildLegacyDeleteConfirmationDialog(Set<MessageRecord> messageRecords) {
int messagesCount = messageRecords.size();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
@@ -610,40 +619,87 @@ public class ConversationFragment extends Fragment
builder.setMessage(getActivity().getResources().getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messagesCount, messagesCount));
builder.setCancelable(true);
builder.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new ProgressDialogAsyncTask<MessageRecord, Void, Void>(getActivity(),
R.string.ConversationFragment_deleting,
R.string.ConversationFragment_deleting_messages)
{
@Override
protected Void doInBackground(MessageRecord... messageRecords) {
for (MessageRecord messageRecord : messageRecords) {
boolean threadDeleted;
builder.setPositiveButton(R.string.delete, (dialog, which) -> {
new ProgressDialogAsyncTask<Void, Void, Void>(getActivity(),
R.string.ConversationFragment_deleting,
R.string.ConversationFragment_deleting_messages)
{
@Override
protected Void doInBackground(Void... voids) {
for (MessageRecord messageRecord : messageRecords) {
boolean threadDeleted;
if (messageRecord.isMms()) {
threadDeleted = DatabaseFactory.getMmsDatabase(getActivity()).delete(messageRecord.getId());
} else {
threadDeleted = DatabaseFactory.getSmsDatabase(getActivity()).deleteMessage(messageRecord.getId());
}
if (threadDeleted) {
threadId = -1;
listener.setThreadId(threadId);
}
if (messageRecord.isMms()) {
threadDeleted = DatabaseFactory.getMmsDatabase(getActivity()).delete(messageRecord.getId());
} else {
threadDeleted = DatabaseFactory.getSmsDatabase(getActivity()).deleteMessage(messageRecord.getId());
}
return null;
if (threadDeleted) {
threadId = -1;
listener.setThreadId(threadId);
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, messageRecords.toArray(new MessageRecord[messageRecords.size()]));
}
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.show();
return builder;
}
private AlertDialog.Builder buildRemoteDeleteConfirmationDialog(Set<MessageRecord> messageRecords) {
Context context = requireActivity();
int messagesCount = messageRecords.size();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(getActivity().getResources().getQuantityString(R.plurals.ConversationFragment_delete_selected_messages, messagesCount, messagesCount));
builder.setCancelable(true);
builder.setPositiveButton(R.string.ConversationFragment_delete_for_me, (dialog, which) -> {
new ProgressDialogAsyncTask<Void, Void, Void>(getActivity(),
R.string.ConversationFragment_deleting,
R.string.ConversationFragment_deleting_messages)
{
@Override
protected Void doInBackground(Void... voids) {
for (MessageRecord messageRecord : messageRecords) {
boolean threadDeleted;
if (messageRecord.isMms()) {
threadDeleted = DatabaseFactory.getMmsDatabase(context).delete(messageRecord.getId());
} else {
threadDeleted = DatabaseFactory.getSmsDatabase(context).deleteMessage(messageRecord.getId());
}
if (threadDeleted) {
threadId = -1;
listener.setThreadId(threadId);
}
}
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
});
if (RemoteDeleteUtil.isValidSend(messageRecords, System.currentTimeMillis())) {
builder.setNeutralButton(R.string.ConversationFragment_delete_for_everyone, (dialog, which) -> {
SignalExecutors.BOUNDED.execute(() -> {
for (MessageRecord message : messageRecords) {
MessageSender.sendRemoteDelete(context, message.getId(), message.isMms());
}
});
});
}
builder.setNegativeButton(android.R.string.cancel, null);
return builder;
}
private void handleDisplayDetails(MessageRecord message) {
Intent intent = new Intent(getActivity(), MessageDetailsActivity.class);
intent.putExtra(MessageDetailsActivity.MESSAGE_ID_EXTRA, message.getId());
@@ -1086,6 +1142,7 @@ public class ConversationFragment extends Fragment
if (actionMode != null) return;
if (messageRecord.isSecure() &&
!messageRecord.isRemoteDelete() &&
!messageRecord.isUpdate() &&
!recipient.get().isBlocked() &&
!messageRequestViewModel.shouldShowMessageRequest() &&

View File

@@ -36,6 +36,8 @@ import android.text.style.BackgroundColorSpan;
import android.text.style.CharacterStyle;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.util.AttributeSet;
@@ -519,7 +521,14 @@ public class ConversationItem extends LinearLayout implements BindableConversati
bodyText.setFocusable(false);
bodyText.setTextSize(TypedValue.COMPLEX_UNIT_SP, TextSecurePreferences.getMessageBodyTextSize(context));
if (isCaptionlessMms(messageRecord)) {
if (messageRecord.isRemoteDelete()) {
String deletedMessage = context.getString(R.string.ConversationItem_this_message_was_deleted);
SpannableString italics = new SpannableString(deletedMessage);
italics.setSpan(new RelativeSizeSpan(0.9f), 0, deletedMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
italics.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, deletedMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
bodyText.setText(italics);
} else if (isCaptionlessMms(messageRecord)) {
bodyText.setVisibility(View.GONE);
} else {
Spannable styledText = linkifyMessageBody(messageRecord.getDisplayBody(getContext()), batchSelected.isEmpty());

View File

@@ -432,6 +432,7 @@ public final class ConversationReactionOverlay extends RelativeLayout {
toolbar.getMenu().findItem(R.id.action_copy).setVisible(menuState.shouldShowCopyAction());
toolbar.getMenu().findItem(R.id.action_download).setVisible(menuState.shouldShowSaveAttachmentAction());
toolbar.getMenu().findItem(R.id.action_forward).setVisible(menuState.shouldShowForwardAction());
toolbar.getMenu().findItem(R.id.action_reply).setVisible(menuState.shouldShowReplyAction());
}
private boolean handleToolbarItemClicked(@NonNull MenuItem menuItem) {

View File

@@ -59,6 +59,7 @@ final class MenuState {
boolean hasText = false;
boolean sharedContact = false;
boolean viewOnce = false;
boolean remoteDelete = false;
for (MessageRecord messageRecord : messageRecords) {
if (isActionMessage(messageRecord))
@@ -77,6 +78,10 @@ final class MenuState {
if (messageRecord.isViewOnce()) {
viewOnce = true;
}
if (messageRecord.isRemoteDelete()) {
remoteDelete = true;
}
}
if (messageRecords.size() > 1) {
@@ -89,26 +94,27 @@ final class MenuState {
MessageRecord messageRecord = messageRecords.iterator().next();
builder.shouldShowResendAction(messageRecord.isFailed())
.shouldShowSaveAttachmentAction(!actionMessage &&
!viewOnce &&
messageRecord.isMms() &&
!messageRecord.isMmsNotification() &&
((MediaMmsMessageRecord)messageRecord).containsMediaSlide() &&
((MediaMmsMessageRecord)messageRecord).getSlideDeck().getStickerSlide() == null)
.shouldShowForwardAction(!actionMessage && !sharedContact && !viewOnce)
.shouldShowSaveAttachmentAction(!actionMessage &&
!viewOnce &&
messageRecord.isMms() &&
!messageRecord.isMmsNotification() &&
((MediaMmsMessageRecord)messageRecord).containsMediaSlide() &&
((MediaMmsMessageRecord)messageRecord).getSlideDeck().getStickerSlide() == null)
.shouldShowForwardAction(!actionMessage && !sharedContact && !viewOnce && !remoteDelete)
.shouldShowDetailsAction(!actionMessage)
.shouldShowReplyAction(canReplyToMessage(actionMessage, messageRecord, shouldShowMessageRequest));
}
return builder.shouldShowCopyAction(!actionMessage && hasText)
return builder.shouldShowCopyAction(!actionMessage && !remoteDelete && hasText)
.build();
}
static boolean canReplyToMessage(boolean actionMessage, @NonNull MessageRecord messageRecord, boolean isDisplayingMessageRequest) {
return !actionMessage &&
!messageRecord.isPending() &&
!messageRecord.isFailed() &&
!isDisplayingMessageRequest &&
return !actionMessage &&
!messageRecord.isRemoteDelete() &&
!messageRecord.isPending() &&
!messageRecord.isFailed() &&
!isDisplayingMessageRequest &&
messageRecord.isSecure();
}