kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add additional fallback logic for change dialog.
rodzic
14565b0864
commit
55c69cd50a
|
@ -70,6 +70,7 @@ public interface BindableConversationItem extends Unbindable, GiphyMp4Playable,
|
||||||
void onGroupMemberClicked(@NonNull RecipientId recipientId, @NonNull GroupId groupId);
|
void onGroupMemberClicked(@NonNull RecipientId recipientId, @NonNull GroupId groupId);
|
||||||
void onMessageWithErrorClicked(@NonNull MessageRecord messageRecord);
|
void onMessageWithErrorClicked(@NonNull MessageRecord messageRecord);
|
||||||
void onMessageWithRecaptchaNeededClicked(@NonNull MessageRecord messageRecord);
|
void onMessageWithRecaptchaNeededClicked(@NonNull MessageRecord messageRecord);
|
||||||
|
void onIncomingIdentityMismatchClicked(@NonNull RecipientId recipientId);
|
||||||
void onRegisterVoiceNoteCallbacks(@NonNull Observer<VoiceNotePlaybackState> onPlaybackStartObserver);
|
void onRegisterVoiceNoteCallbacks(@NonNull Observer<VoiceNotePlaybackState> onPlaybackStartObserver);
|
||||||
void onUnregisterVoiceNoteCallbacks(@NonNull Observer<VoiceNotePlaybackState> onPlaybackStartObserver);
|
void onUnregisterVoiceNoteCallbacks(@NonNull Observer<VoiceNotePlaybackState> onPlaybackStartObserver);
|
||||||
void onVoiceNotePause(@NonNull Uri uri);
|
void onVoiceNotePause(@NonNull Uri uri);
|
||||||
|
|
|
@ -1,176 +0,0 @@
|
||||||
package org.thoughtcrime.securesms;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.text.SpannableString;
|
|
||||||
import android.text.Spanned;
|
|
||||||
import android.text.method.LinkMovementMethod;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
|
|
||||||
import org.signal.core.util.logging.Log;
|
|
||||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
|
||||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
|
||||||
import org.thoughtcrime.securesms.database.MessageDatabase;
|
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
|
||||||
import org.thoughtcrime.securesms.jobs.PushDecryptMessageJob;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
|
||||||
import org.thoughtcrime.securesms.util.Base64;
|
|
||||||
import org.thoughtcrime.securesms.util.VerifySpan;
|
|
||||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
|
||||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class ConfirmIdentityDialog extends AlertDialog {
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private static final String TAG = Log.tag(ConfirmIdentityDialog.class);
|
|
||||||
|
|
||||||
private OnClickListener callback;
|
|
||||||
|
|
||||||
public ConfirmIdentityDialog(Context context,
|
|
||||||
MessageRecord messageRecord,
|
|
||||||
IdentityKeyMismatch mismatch)
|
|
||||||
{
|
|
||||||
super(context);
|
|
||||||
|
|
||||||
Recipient recipient = Recipient.resolved(mismatch.getRecipientId(context));
|
|
||||||
String name = recipient.getDisplayName(context);
|
|
||||||
String introduction = context.getString(R.string.ConfirmIdentityDialog_your_safety_number_with_s_has_changed, name, name);
|
|
||||||
SpannableString spannableString = new SpannableString(introduction + " " +
|
|
||||||
context.getString(R.string.ConfirmIdentityDialog_you_may_wish_to_verify_your_safety_number_with_this_contact));
|
|
||||||
|
|
||||||
spannableString.setSpan(new VerifySpan(context, mismatch),
|
|
||||||
introduction.length()+1, spannableString.length(),
|
|
||||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
||||||
|
|
||||||
setTitle(name);
|
|
||||||
setMessage(spannableString);
|
|
||||||
|
|
||||||
setButton(AlertDialog.BUTTON_POSITIVE, context.getString(R.string.ConfirmIdentityDialog_accept), new AcceptListener(messageRecord, mismatch, recipient.getId()));
|
|
||||||
setButton(AlertDialog.BUTTON_NEGATIVE, context.getString(android.R.string.cancel), new CancelListener());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void show() {
|
|
||||||
super.show();
|
|
||||||
((TextView)this.findViewById(android.R.id.message))
|
|
||||||
.setMovementMethod(LinkMovementMethod.getInstance());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCallback(OnClickListener callback) {
|
|
||||||
this.callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AcceptListener implements OnClickListener {
|
|
||||||
|
|
||||||
private final MessageRecord messageRecord;
|
|
||||||
private final IdentityKeyMismatch mismatch;
|
|
||||||
private final RecipientId recipientId;
|
|
||||||
|
|
||||||
private AcceptListener(MessageRecord messageRecord, IdentityKeyMismatch mismatch, RecipientId recipientId) {
|
|
||||||
this.messageRecord = messageRecord;
|
|
||||||
this.mismatch = mismatch;
|
|
||||||
this.recipientId = recipientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
new AsyncTask<Void, Void, Void>()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... params) {
|
|
||||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
|
||||||
SignalProtocolAddress mismatchAddress = new SignalProtocolAddress(Recipient.resolved(recipientId).requireServiceId(), 1);
|
|
||||||
TextSecureIdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(getContext());
|
|
||||||
|
|
||||||
identityKeyStore.saveIdentity(mismatchAddress, mismatch.getIdentityKey(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
processMessageRecord(messageRecord);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processMessageRecord(MessageRecord messageRecord) {
|
|
||||||
if (messageRecord.isOutgoing()) processOutgoingMessageRecord(messageRecord);
|
|
||||||
else processIncomingMessageRecord(messageRecord);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processOutgoingMessageRecord(MessageRecord messageRecord) {
|
|
||||||
MessageDatabase smsDatabase = DatabaseFactory.getSmsDatabase(getContext());
|
|
||||||
MessageDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(getContext());
|
|
||||||
|
|
||||||
if (messageRecord.isMms()) {
|
|
||||||
mmsDatabase.removeMismatchedIdentity(messageRecord.getId(),
|
|
||||||
mismatch.getRecipientId(getContext()),
|
|
||||||
mismatch.getIdentityKey());
|
|
||||||
|
|
||||||
if (messageRecord.getRecipient().isPushGroup()) {
|
|
||||||
MessageSender.resendGroupMessage(getContext(), messageRecord, Recipient.resolved(mismatch.getRecipientId(getContext())).getId());
|
|
||||||
} else {
|
|
||||||
MessageSender.resend(getContext(), messageRecord);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
smsDatabase.removeMismatchedIdentity(messageRecord.getId(),
|
|
||||||
mismatch.getRecipientId(getContext()),
|
|
||||||
mismatch.getIdentityKey());
|
|
||||||
|
|
||||||
MessageSender.resend(getContext(), messageRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processIncomingMessageRecord(MessageRecord messageRecord) {
|
|
||||||
try {
|
|
||||||
MessageDatabase smsDatabase = DatabaseFactory.getSmsDatabase(getContext());
|
|
||||||
|
|
||||||
smsDatabase.removeMismatchedIdentity(messageRecord.getId(),
|
|
||||||
mismatch.getRecipientId(getContext()),
|
|
||||||
mismatch.getIdentityKey());
|
|
||||||
|
|
||||||
boolean legacy = !messageRecord.isContentBundleKeyExchange();
|
|
||||||
|
|
||||||
SignalServiceEnvelope envelope = new SignalServiceEnvelope(SignalServiceProtos.Envelope.Type.PREKEY_BUNDLE_VALUE,
|
|
||||||
Optional.of(RecipientUtil.toSignalServiceAddress(getContext(), messageRecord.getIndividualRecipient())),
|
|
||||||
messageRecord.getRecipientDeviceId(),
|
|
||||||
messageRecord.getDateSent(),
|
|
||||||
legacy ? Base64.decode(messageRecord.getBody()) : null,
|
|
||||||
!legacy ? Base64.decode(messageRecord.getBody()) : null,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
null);
|
|
||||||
|
|
||||||
ApplicationDependencies.getJobManager().add(new PushDecryptMessageJob(getContext(), envelope, messageRecord.getId()));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
|
|
||||||
if (callback != null) callback.onClick(null, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CancelListener implements OnClickListener {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
if (callback != null) callback.onClick(null, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -92,6 +92,7 @@ import org.thoughtcrime.securesms.conversation.ConversationMessage.ConversationM
|
||||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
||||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerView;
|
import org.thoughtcrime.securesms.conversation.colors.ColorizerView;
|
||||||
import org.thoughtcrime.securesms.conversation.ui.error.EnableCallNotificationSettingsDialog;
|
import org.thoughtcrime.securesms.conversation.ui.error.EnableCallNotificationSettingsDialog;
|
||||||
|
import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MessageDatabase;
|
import org.thoughtcrime.securesms.database.MessageDatabase;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
|
@ -1585,6 +1586,11 @@ public class ConversationFragment extends LoggingFragment {
|
||||||
RecaptchaProofBottomSheetFragment.show(getChildFragmentManager());
|
RecaptchaProofBottomSheetFragment.show(getChildFragmentManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onIncomingIdentityMismatchClicked(@NonNull RecipientId recipientId) {
|
||||||
|
SafetyNumberChangeDialog.show(getParentFragmentManager(), recipientId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVoiceNotePause(@NonNull Uri uri) {
|
public void onVoiceNotePause(@NonNull Uri uri) {
|
||||||
listener.onVoiceNotePause(uri);
|
listener.onVoiceNotePause(uri);
|
||||||
|
|
|
@ -65,7 +65,6 @@ import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.BindableConversationItem;
|
import org.thoughtcrime.securesms.BindableConversationItem;
|
||||||
import org.thoughtcrime.securesms.ConfirmIdentityDialog;
|
|
||||||
import org.thoughtcrime.securesms.MediaPreviewActivity;
|
import org.thoughtcrime.securesms.MediaPreviewActivity;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
||||||
|
@ -121,7 +120,6 @@ import org.thoughtcrime.securesms.revealable.ViewOnceMessageView;
|
||||||
import org.thoughtcrime.securesms.revealable.ViewOnceUtil;
|
import org.thoughtcrime.securesms.revealable.ViewOnceUtil;
|
||||||
import org.thoughtcrime.securesms.stickers.StickerUrl;
|
import org.thoughtcrime.securesms.stickers.StickerUrl;
|
||||||
import org.thoughtcrime.securesms.util.DateUtils;
|
import org.thoughtcrime.securesms.util.DateUtils;
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
|
||||||
import org.thoughtcrime.securesms.util.InterceptableLongClickCopyLinkSpan;
|
import org.thoughtcrime.securesms.util.InterceptableLongClickCopyLinkSpan;
|
||||||
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
|
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
|
||||||
import org.thoughtcrime.securesms.util.Projection;
|
import org.thoughtcrime.securesms.util.Projection;
|
||||||
|
@ -1450,16 +1448,6 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||||
|
|
||||||
/// Event handlers
|
/// Event handlers
|
||||||
|
|
||||||
private void handleApproveIdentity() {
|
|
||||||
List<IdentityKeyMismatch> mismatches = messageRecord.getIdentityKeyMismatches();
|
|
||||||
|
|
||||||
if (mismatches.size() != 1) {
|
|
||||||
throw new AssertionError("Identity mismatch count: " + mismatches.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
new ConfirmIdentityDialog(context, messageRecord, mismatches.get(0)).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Spannable getLongMessageSpan(@NonNull MessageRecord messageRecord) {
|
private Spannable getLongMessageSpan(@NonNull MessageRecord messageRecord) {
|
||||||
String message;
|
String message;
|
||||||
Runnable action;
|
Runnable action;
|
||||||
|
@ -1810,7 +1798,9 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
||||||
eventListener.onMessageWithRecaptchaNeededClicked(messageRecord);
|
eventListener.onMessageWithRecaptchaNeededClicked(messageRecord);
|
||||||
}
|
}
|
||||||
} else if (!messageRecord.isOutgoing() && messageRecord.isIdentityMismatchFailure()) {
|
} else if (!messageRecord.isOutgoing() && messageRecord.isIdentityMismatchFailure()) {
|
||||||
handleApproveIdentity();
|
if (eventListener != null) {
|
||||||
|
eventListener.onIncomingIdentityMismatchClicked(messageRecord.getIndividualRecipient().getId());
|
||||||
|
}
|
||||||
} else if (messageRecord.isPendingInsecureSmsFallback()) {
|
} else if (messageRecord.isPendingInsecureSmsFallback()) {
|
||||||
handleMessageApproval();
|
handleMessageApproval();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,11 +46,22 @@ public final class SafetyNumberChangeDialog extends DialogFragment implements Sa
|
||||||
private static final String MESSAGE_TYPE_EXTRA = "message_type";
|
private static final String MESSAGE_TYPE_EXTRA = "message_type";
|
||||||
private static final String CONTINUE_TEXT_RESOURCE_EXTRA = "continue_text_resource";
|
private static final String CONTINUE_TEXT_RESOURCE_EXTRA = "continue_text_resource";
|
||||||
private static final String CANCEL_TEXT_RESOURCE_EXTRA = "cancel_text_resource";
|
private static final String CANCEL_TEXT_RESOURCE_EXTRA = "cancel_text_resource";
|
||||||
|
private static final String SKIP_CALLBACKS_EXTRA = "skip_callbacks_extra";
|
||||||
|
|
||||||
private SafetyNumberChangeViewModel viewModel;
|
private SafetyNumberChangeViewModel viewModel;
|
||||||
private SafetyNumberChangeAdapter adapter;
|
private SafetyNumberChangeAdapter adapter;
|
||||||
private View dialogView;
|
private View dialogView;
|
||||||
|
|
||||||
|
public static void show(@NonNull FragmentManager fragmentManager, @NonNull RecipientId recipientId) {
|
||||||
|
Bundle arguments = new Bundle();
|
||||||
|
arguments.putStringArray(RECIPIENT_IDS_EXTRA, new String[] { recipientId.serialize() });
|
||||||
|
arguments.putInt(CONTINUE_TEXT_RESOURCE_EXTRA, R.string.safety_number_change_dialog__accept);
|
||||||
|
arguments.putBoolean(SKIP_CALLBACKS_EXTRA, true);
|
||||||
|
SafetyNumberChangeDialog fragment = new SafetyNumberChangeDialog();
|
||||||
|
fragment.setArguments(arguments);
|
||||||
|
fragment.show(fragmentManager, SAFETY_NUMBER_DIALOG);
|
||||||
|
}
|
||||||
|
|
||||||
public static void show(@NonNull FragmentManager fragmentManager, @NonNull List<IdentityDatabase.IdentityRecord> identityRecords) {
|
public static void show(@NonNull FragmentManager fragmentManager, @NonNull List<IdentityDatabase.IdentityRecord> identityRecords) {
|
||||||
List<String> ids = Stream.of(identityRecords)
|
List<String> ids = Stream.of(identityRecords)
|
||||||
.filterNot(IdentityDatabase.IdentityRecord::isFirstUse)
|
.filterNot(IdentityDatabase.IdentityRecord::isFirstUse)
|
||||||
|
@ -196,9 +207,11 @@ public final class SafetyNumberChangeDialog extends DialogFragment implements Sa
|
||||||
private void handleSendAnyway(DialogInterface dialogInterface, int which) {
|
private void handleSendAnyway(DialogInterface dialogInterface, int which) {
|
||||||
Log.d(TAG, "handleSendAnyway");
|
Log.d(TAG, "handleSendAnyway");
|
||||||
|
|
||||||
|
boolean skipCallbacks = requireArguments().getBoolean(SKIP_CALLBACKS_EXTRA, false);
|
||||||
|
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
Callback callback;
|
Callback callback;
|
||||||
if (activity instanceof Callback) {
|
if (activity instanceof Callback && !skipCallbacks) {
|
||||||
callback = (Callback) activity;
|
callback = (Callback) activity;
|
||||||
} else {
|
} else {
|
||||||
callback = null;
|
callback = null;
|
||||||
|
@ -241,7 +254,9 @@ public final class SafetyNumberChangeDialog extends DialogFragment implements Sa
|
||||||
|
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
void onSendAnywayAfterSafetyNumberChange(@NonNull List<RecipientId> changedRecipients);
|
void onSendAnywayAfterSafetyNumberChange(@NonNull List<RecipientId> changedRecipients);
|
||||||
|
|
||||||
void onMessageResentAfterSafetyNumberChange();
|
void onMessageResentAfterSafetyNumberChange();
|
||||||
|
|
||||||
void onCanceled();
|
void onCanceled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.libsignal.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||||
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -124,13 +125,14 @@ final class SafetyNumberChangeRepository {
|
||||||
|
|
||||||
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||||
for (ChangedRecipient changedRecipient : changedRecipients) {
|
for (ChangedRecipient changedRecipient : changedRecipients) {
|
||||||
SignalProtocolAddress mismatchAddress = new SignalProtocolAddress(changedRecipient.getRecipient().requireServiceId(), 1);
|
SignalProtocolAddress mismatchAddress = new SignalProtocolAddress(changedRecipient.getRecipient().requireServiceId(), SignalServiceAddress.DEFAULT_DEVICE_ID);
|
||||||
TextSecureIdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(context);
|
TextSecureIdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(context);
|
||||||
Log.d(TAG, "Saving identity for: " + changedRecipient.getRecipient().getId() + " " + changedRecipient.getIdentityRecord().getIdentityKey().hashCode());
|
Log.d(TAG, "Saving identity for: " + changedRecipient.getRecipient().getId() + " " + changedRecipient.getIdentityRecord().getIdentityKey().hashCode());
|
||||||
TextSecureIdentityKeyStore.SaveResult result = identityKeyStore.saveIdentity(mismatchAddress, changedRecipient.getIdentityRecord().getIdentityKey(), true);
|
TextSecureIdentityKeyStore.SaveResult result = identityKeyStore.saveIdentity(mismatchAddress, changedRecipient.getIdentityRecord().getIdentityKey(), true);
|
||||||
Log.d(TAG, "Saving identity result: " + result);
|
Log.d(TAG, "Saving identity result: " + result);
|
||||||
if (result == TextSecureIdentityKeyStore.SaveResult.NO_CHANGE) {
|
if (result == TextSecureIdentityKeyStore.SaveResult.NO_CHANGE) {
|
||||||
Log.i(TAG, "Archiving sessions explicitly as they appear to be out of sync.");
|
Log.i(TAG, "Archiving sessions explicitly as they appear to be out of sync.");
|
||||||
|
SessionUtil.archiveSession(context, changedRecipient.getRecipient().getId(), SignalServiceAddress.DEFAULT_DEVICE_ID);
|
||||||
SessionUtil.archiveSiblingSessions(context, mismatchAddress);
|
SessionUtil.archiveSiblingSessions(context, mismatchAddress);
|
||||||
DatabaseFactory.getSenderKeySharedDatabase(context).deleteAllFor(changedRecipient.getRecipient().getId());
|
DatabaseFactory.getSenderKeySharedDatabase(context).deleteAllFor(changedRecipient.getRecipient().getId());
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.messagedetails;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
@ -13,9 +12,9 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
|
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
|
||||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
||||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerView;
|
import org.thoughtcrime.securesms.conversation.colors.ColorizerView;
|
||||||
|
import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog;
|
||||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4PlaybackController;
|
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4PlaybackController;
|
||||||
|
@ -26,9 +25,7 @@ import org.thoughtcrime.securesms.messagedetails.MessageDetailsViewModel.Factory
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.util.DynamicDarkActionBarTheme;
|
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
import org.thoughtcrime.securesms.util.WindowUtil;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -102,7 +99,7 @@ public final class MessageDetailsActivity extends PassphraseRequiredActivity {
|
||||||
ColorizerView colorizerView = findViewById(R.id.message_details_colorizer);
|
ColorizerView colorizerView = findViewById(R.id.message_details_colorizer);
|
||||||
|
|
||||||
colorizer = new Colorizer(colorizerView);
|
colorizer = new Colorizer(colorizerView);
|
||||||
adapter = new MessageDetailsAdapter(this, glideRequests, colorizer);
|
adapter = new MessageDetailsAdapter(this, glideRequests, colorizer, this::onErrorClicked);
|
||||||
|
|
||||||
list.setAdapter(adapter);
|
list.setAdapter(adapter);
|
||||||
list.setItemAnimator(null);
|
list.setItemAnimator(null);
|
||||||
|
@ -170,4 +167,8 @@ public final class MessageDetailsActivity extends PassphraseRequiredActivity {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onErrorClicked(@NonNull MessageRecord messageRecord) {
|
||||||
|
SafetyNumberChangeDialog.show(this, messageRecord);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationMessage;
|
import org.thoughtcrime.securesms.conversation.ConversationMessage;
|
||||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
||||||
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -24,13 +25,15 @@ final class MessageDetailsAdapter extends ListAdapter<MessageDetailsAdapter.Mess
|
||||||
private final LifecycleOwner lifecycleOwner;
|
private final LifecycleOwner lifecycleOwner;
|
||||||
private final GlideRequests glideRequests;
|
private final GlideRequests glideRequests;
|
||||||
private final Colorizer colorizer;
|
private final Colorizer colorizer;
|
||||||
|
private Callbacks callbacks;
|
||||||
private boolean running;
|
private boolean running;
|
||||||
|
|
||||||
MessageDetailsAdapter(@NonNull LifecycleOwner lifecycleOwner, @NonNull GlideRequests glideRequests, @NonNull Colorizer colorizer) {
|
MessageDetailsAdapter(@NonNull LifecycleOwner lifecycleOwner, @NonNull GlideRequests glideRequests, @NonNull Colorizer colorizer, @NonNull Callbacks callbacks) {
|
||||||
super(new MessageDetailsDiffer());
|
super(new MessageDetailsDiffer());
|
||||||
this.lifecycleOwner = lifecycleOwner;
|
this.lifecycleOwner = lifecycleOwner;
|
||||||
this.glideRequests = glideRequests;
|
this.glideRequests = glideRequests;
|
||||||
this.colorizer = colorizer;
|
this.colorizer = colorizer;
|
||||||
|
this.callbacks = callbacks;
|
||||||
this.running = true;
|
this.running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +45,7 @@ final class MessageDetailsAdapter extends ListAdapter<MessageDetailsAdapter.Mess
|
||||||
case MessageDetailsViewState.RECIPIENT_HEADER:
|
case MessageDetailsViewState.RECIPIENT_HEADER:
|
||||||
return new RecipientHeaderViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.message_details_recipient_header, parent, false));
|
return new RecipientHeaderViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.message_details_recipient_header, parent, false));
|
||||||
case MessageDetailsViewState.RECIPIENT:
|
case MessageDetailsViewState.RECIPIENT:
|
||||||
return new RecipientViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.message_details_recipient, parent, false));
|
return new RecipientViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.message_details_recipient, parent, false), callbacks);
|
||||||
default:
|
default:
|
||||||
throw new AssertionError("unknown view type");
|
throw new AssertionError("unknown view type");
|
||||||
}
|
}
|
||||||
|
@ -143,4 +146,8 @@ final class MessageDetailsAdapter extends ListAdapter<MessageDetailsAdapter.Mess
|
||||||
this.itemType = itemType;
|
this.itemType = itemType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Callbacks {
|
||||||
|
void onErrorClicked(@NonNull MessageRecord messageRecord);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@ package org.thoughtcrime.securesms.messagedetails;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.ConfirmIdentityDialog;
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.components.AvatarImageView;
|
import org.thoughtcrime.securesms.components.AvatarImageView;
|
||||||
import org.thoughtcrime.securesms.components.FromTextView;
|
import org.thoughtcrime.securesms.components.FromTextView;
|
||||||
|
@ -21,10 +21,13 @@ final class RecipientViewHolder extends RecyclerView.ViewHolder {
|
||||||
private final TextView error;
|
private final TextView error;
|
||||||
private final View conflictButton;
|
private final View conflictButton;
|
||||||
private final View unidentifiedDeliveryIcon;
|
private final View unidentifiedDeliveryIcon;
|
||||||
|
private MessageDetailsAdapter.Callbacks callbacks;
|
||||||
|
|
||||||
RecipientViewHolder(View itemView) {
|
RecipientViewHolder(@NonNull View itemView, @NonNull MessageDetailsAdapter.Callbacks callbacks) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
|
|
||||||
|
this.callbacks = callbacks;
|
||||||
|
|
||||||
fromView = itemView.findViewById(R.id.message_details_recipient_name);
|
fromView = itemView.findViewById(R.id.message_details_recipient_name);
|
||||||
avatar = itemView.findViewById(R.id.message_details_recipient_avatar);
|
avatar = itemView.findViewById(R.id.message_details_recipient_avatar);
|
||||||
timestamp = itemView.findViewById(R.id.message_details_recipient_timestamp);
|
timestamp = itemView.findViewById(R.id.message_details_recipient_timestamp);
|
||||||
|
@ -43,7 +46,7 @@ final class RecipientViewHolder extends RecyclerView.ViewHolder {
|
||||||
error.setVisibility(View.VISIBLE);
|
error.setVisibility(View.VISIBLE);
|
||||||
conflictButton.setVisibility(View.VISIBLE);
|
conflictButton.setVisibility(View.VISIBLE);
|
||||||
error.setText(itemView.getContext().getString(R.string.message_details_recipient__new_safety_number));
|
error.setText(itemView.getContext().getString(R.string.message_details_recipient__new_safety_number));
|
||||||
conflictButton.setOnClickListener(unused -> new ConfirmIdentityDialog(itemView.getContext(), data.getMessageRecord(), data.getKeyMismatchFailure()).show());
|
conflictButton.setOnClickListener(unused -> callbacks.onErrorClicked(data.getMessageRecord()));
|
||||||
} else if ((data.getNetworkFailure() != null && !data.getMessageRecord().isPending()) || (!data.getMessageRecord().getRecipient().isPushGroup() && data.getMessageRecord().isFailed())) {
|
} else if ((data.getNetworkFailure() != null && !data.getMessageRecord().isPending()) || (!data.getMessageRecord().getRecipient().isPushGroup() && data.getMessageRecord().isFailed())) {
|
||||||
timestamp.setVisibility(View.GONE);
|
timestamp.setVisibility(View.GONE);
|
||||||
error.setVisibility(View.VISIBLE);
|
error.setVisibility(View.VISIBLE);
|
||||||
|
|
|
@ -1924,6 +1924,7 @@
|
||||||
|
|
||||||
<!-- safety_number_change_dialog -->
|
<!-- safety_number_change_dialog -->
|
||||||
<string name="safety_number_change_dialog__safety_number_changes">Safety Number Changes</string>
|
<string name="safety_number_change_dialog__safety_number_changes">Safety Number Changes</string>
|
||||||
|
<string name="safety_number_change_dialog__accept">Accept</string>
|
||||||
<string name="safety_number_change_dialog__send_anyway">Send anyway</string>
|
<string name="safety_number_change_dialog__send_anyway">Send anyway</string>
|
||||||
<string name="safety_number_change_dialog__call_anyway">Call anyway</string>
|
<string name="safety_number_change_dialog__call_anyway">Call anyway</string>
|
||||||
<string name="safety_number_change_dialog__join_call">Join call</string>
|
<string name="safety_number_change_dialog__join_call">Join call</string>
|
||||||
|
|
Ładowanie…
Reference in New Issue