diff --git a/res/layout/conversation_item_update.xml b/res/layout/conversation_item_update.xml
index 9a2368a43a..3fdf0a1e18 100644
--- a/res/layout/conversation_item_update.xml
+++ b/res/layout/conversation_item_update.xml
@@ -53,7 +53,7 @@
style="@style/Signal.Text.Preview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:autoLink="all"
+ android:autoLink="none"
android:gravity="center"
android:linksClickable="true"
android:textColor="?attr/conversation_item_update_text_color"
@@ -74,6 +74,15 @@
android:textColor="?conversation_item_update_text_color"
tools:text="30 min ago" />
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d850790d91..e5eac4ea11 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -735,6 +735,9 @@
Bad encrypted message
Message encrypted for non-existing session
+ Could not decrypt an incoming message. Would you like to start a new session with %s?
+ You have sent a session restore request to %s
+ Restore session
Bad encrypted MMS message
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
index 84f3c11da5..46bb52d7b2 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
@@ -154,6 +154,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel;
import org.thoughtcrime.securesms.logging.Log;
+import org.thoughtcrime.securesms.loki.ConversationUpdateItemViewDelegate;
import org.thoughtcrime.securesms.loki.FriendRequestViewDelegate;
import org.thoughtcrime.securesms.loki.LokiAPIUtilities;
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
@@ -272,7 +273,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
ConversationSearchBottomBar.EventListener,
StickerKeyboardProvider.StickerEventListener,
LokiThreadDatabaseDelegate,
- FriendRequestViewDelegate
+ FriendRequestViewDelegate,
+ ConversationUpdateItemViewDelegate
{
private static final String TAG = ConversationActivity.class.getSimpleName();
@@ -376,6 +378,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
fragment = initFragment(R.id.fragment_content, new ConversationFragment(), dynamicLanguage.getCurrentLocale());
fragment.friendRequestViewDelegate = this;
+ fragment.conversationUpdateItemViewDelegate = this;
initializeReceivers();
initializeActionBar();
@@ -3079,4 +3082,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
return TextSecurePreferences.getLocalNumber(this).equals(recipient.getAddress().serialize());
}
// endregion
+
+ @Override
+ public void updateItemButtonPressed(@NonNull MessageRecord messageRecord) {
+ // Loki - User clicked restore session
+ if (messageRecord.isNoRemoteSession() && !messageRecord.isLokiSessionRestoreSent()) {
+ // TODO: Send a message with `SESSION_RESTORE` flag
+ DatabaseFactory.getSmsDatabase(this).markAsLokiSessionRestoreSent(messageRecord.id);
+ TextSecurePreferences.setShowingSessionRestorePrompt(this, messageRecord.getIndividualRecipient().getAddress().serialize(), false);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationAdapter.java b/src/org/thoughtcrime/securesms/conversation/ConversationAdapter.java
index 2adeae528b..d2f2124a4d 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationAdapter.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationAdapter.java
@@ -41,6 +41,7 @@ import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.logging.Log;
+import org.thoughtcrime.securesms.loki.ConversationUpdateItemViewDelegate;
import org.thoughtcrime.securesms.loki.FriendRequestViewDelegate;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.SlideDeck;
@@ -108,6 +109,7 @@ public class ConversationAdapter
private String searchQuery;
public FriendRequestViewDelegate friendRequestViewDelegate; // Loki
+ public ConversationUpdateItemViewDelegate conversationUpdateItemViewDelegate;
protected static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(final @NonNull V itemView) {
@@ -204,6 +206,8 @@ public class ConversationAdapter
BindableConversationItem conversationItem = viewHolder.getView();
if (conversationItem instanceof ConversationItem) {
((ConversationItem)conversationItem).friendRequestViewDelegate = this.friendRequestViewDelegate;
+ } else if (conversationItem instanceof ConversationUpdateItem) {
+ ((ConversationUpdateItem)conversationItem).delegate = this.conversationUpdateItemViewDelegate;
}
conversationItem.bind(messageRecord,
Optional.fromNullable(previousRecord),
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java
index 46338150f5..463a8b41a5 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java
@@ -79,6 +79,7 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.logging.Log;
+import org.thoughtcrime.securesms.loki.ConversationUpdateItemViewDelegate;
import org.thoughtcrime.securesms.loki.FriendRequestViewDelegate;
import org.thoughtcrime.securesms.longmessage.LongMessageActivity;
import org.thoughtcrime.securesms.mediasend.Media;
@@ -152,6 +153,7 @@ public class ConversationFragment extends Fragment
private View scrollToBottomButton;
private TextView scrollDateHeader;
public FriendRequestViewDelegate friendRequestViewDelegate; // Loki
+ public ConversationUpdateItemViewDelegate conversationUpdateItemViewDelegate;
@Override
public void onCreate(Bundle icicle) {
@@ -360,7 +362,8 @@ public class ConversationFragment extends Fragment
if (messageRecord.isGroupAction() || messageRecord.isCallLog() ||
messageRecord.isJoined() || messageRecord.isExpirationTimerUpdate() ||
messageRecord.isEndSession() || messageRecord.isIdentityUpdate() ||
- messageRecord.isIdentityVerified() || messageRecord.isIdentityDefault())
+ messageRecord.isIdentityVerified() || messageRecord.isIdentityDefault() ||
+ messageRecord.isNoRemoteSession() || messageRecord.isLokiSessionRestoreSent())
{
actionMessage = true;
}
@@ -705,6 +708,7 @@ public class ConversationFragment extends Fragment
return;
}
adapter.friendRequestViewDelegate = this.friendRequestViewDelegate;
+ adapter.conversationUpdateItemViewDelegate = this.conversationUpdateItemViewDelegate;
if (cursor.getCount() >= PARTIAL_CONVERSATION_LIMIT && loader.hasLimit()) {
adapter.setFooterView(topLoadMoreView);
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationItem.java b/src/org/thoughtcrime/securesms/conversation/ConversationItem.java
index 7e66fbbcd3..d6ce179425 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationItem.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationItem.java
@@ -87,6 +87,7 @@ import org.thoughtcrime.securesms.jobs.SmsSendJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
import org.thoughtcrime.securesms.logging.Log;
+import org.thoughtcrime.securesms.loki.ConversationUpdateItemViewDelegate;
import org.thoughtcrime.securesms.loki.FriendRequestView;
import org.thoughtcrime.securesms.loki.FriendRequestViewDelegate;
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java b/src/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java
index 89219d3321..f94b268f87 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java
@@ -9,6 +9,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
+import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -21,6 +22,7 @@ import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.logging.Log;
+import org.thoughtcrime.securesms.loki.ConversationUpdateItemViewDelegate;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
@@ -47,10 +49,13 @@ public class ConversationUpdateItem extends LinearLayout
private TextView title;
private TextView body;
private TextView date;
+ private Button button;
private Recipient sender;
private MessageRecord messageRecord;
private Locale locale;
+ public ConversationUpdateItemViewDelegate delegate;
+
public ConversationUpdateItem(Context context) {
super(context);
}
@@ -67,6 +72,12 @@ public class ConversationUpdateItem extends LinearLayout
this.title = findViewById(R.id.conversation_update_title);
this.body = findViewById(R.id.conversation_update_body);
this.date = findViewById(R.id.conversation_update_date);
+ this.button = findViewById(R.id.conversation_update_button);
+ this.button.setOnClickListener(view -> {
+ if (delegate != null && messageRecord != null) {
+ delegate.updateItemButtonPressed(messageRecord);
+ }
+ });
this.setOnClickListener(new InternalClickListener(null));
}
@@ -112,6 +123,8 @@ public class ConversationUpdateItem extends LinearLayout
else if (messageRecord.isIdentityUpdate()) setIdentityRecord(messageRecord);
else if (messageRecord.isIdentityVerified() ||
messageRecord.isIdentityDefault()) setIdentityVerifyUpdate(messageRecord);
+ else if (messageRecord.isNoRemoteSession() ||
+ messageRecord.isLokiSessionRestoreSent()) setTextMessageRecord(messageRecord);
else throw new AssertionError("Neither group nor log nor joined.");
if (batchSelected.contains(messageRecord)) setSelected(true);
@@ -201,6 +214,21 @@ public class ConversationUpdateItem extends LinearLayout
body.setVisibility(VISIBLE);
date.setVisibility(GONE);
}
+
+ private void setTextMessageRecord(MessageRecord messageRecord) {
+ body.setText(messageRecord.getDisplayBody(getContext()));
+ if (messageRecord.isNoRemoteSession() && !messageRecord.isLokiSessionRestoreSent()) {
+ button.setVisibility(VISIBLE);
+ button.setText(R.string.MessageRecord_session_restore_button_title);
+ } else {
+ button.setVisibility(GONE);
+ }
+
+ icon.setVisibility(GONE);
+ title.setVisibility(GONE);
+ body.setVisibility(VISIBLE);
+ date.setVisibility(GONE);
+ }
@Override
public void onModified(Recipient recipient) {
diff --git a/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
index d053ccc74e..2c4bedb676 100644
--- a/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
+++ b/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java
@@ -83,7 +83,7 @@ public interface MmsSmsColumns {
protected static final long ENCRYPTION_REMOTE_LEGACY_BIT = 0x02000000;
// Loki
- protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT = 0x09000000; // Type that determines if we've sent a session reset after receiving `ENCRYPTION_REMOTE_NO_SESSION_BIT`
+ protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT = 0x01000000; // Type that determines if we've sent a session reset after receiving `ENCRYPTION_REMOTE_NO_SESSION_BIT`
public static boolean isDraftMessageType(long type) {
return (type & BASE_TYPE_MASK) == BASE_DRAFT_TYPE;
diff --git a/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java b/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java
index b0a22c36c0..1807ddcce6 100644
--- a/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/DisplayRecord.java
@@ -107,6 +107,10 @@ public abstract class DisplayRecord {
return SmsDatabase.Types.isEndSessionType(type);
}
+ public boolean isNoRemoteSession() { return SmsDatabase.Types.isNoRemoteSessionType(type); }
+
+ public boolean isLokiSessionRestoreSent() { return SmsDatabase.Types.isLokiSessionRestoreSentType(type); }
+
public boolean isGroupUpdate() {
return SmsDatabase.Types.isGroupUpdate(type);
}
diff --git a/src/org/thoughtcrime/securesms/database/model/MessageRecord.java b/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
index 596c2f4853..4664ab5d42 100644
--- a/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/MessageRecord.java
@@ -180,7 +180,7 @@ public abstract class MessageRecord extends DisplayRecord {
public boolean isUpdate() {
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
- isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault();
+ isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() || isNoRemoteSession() || isLokiSessionRestoreSent();
}
public boolean isMediaPending() {
diff --git a/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java b/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java
index 237d038148..d3920b2eaf 100644
--- a/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/SmsMessageRecord.java
@@ -82,6 +82,7 @@ public class SmsMessageRecord extends MessageRecord {
@Override
public SpannableString getDisplayBody(@NonNull Context context) {
+ Recipient recipient = getRecipient();
if (SmsDatabase.Types.isFailedDecryptType(type)) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_bad_encrypted_message));
} else if (isCorruptedKeyExchange()) {
@@ -98,8 +99,14 @@ public class SmsMessageRecord extends MessageRecord {
return emphasisAdded(context.getString(R.string.ConversationItem_received_key_exchange_message_tap_to_process));
} else if (SmsDatabase.Types.isDuplicateMessageType(type)) {
return emphasisAdded(context.getString(R.string.SmsMessageRecord_duplicate_message));
- } else if (SmsDatabase.Types.isNoRemoteSessionType(type)) {
- return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
+ } else if (isLokiSessionRestoreSent()) {
+ return emphasisAdded(context.getString(R.string.MessageRecord_session_restore_sent, recipient.toShortString()));
+ } else if (isNoRemoteSession()) {
+ if (recipient.isGroupRecipient()) {
+ return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
+ } else {
+ return emphasisAdded(context.getString(R.string.MessageRecord_session_restore_required, recipient.toShortString()));
+ }
} else if (isEndSession() && isOutgoing()) {
return emphasisAdded(context.getString(R.string.SmsMessageRecord_secure_session_reset));
} else if (isEndSession()) {
diff --git a/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java b/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java
index 7fae1482c3..ec734b87db 100644
--- a/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java
+++ b/src/org/thoughtcrime/securesms/database/model/ThreadRecord.java
@@ -71,6 +71,7 @@ public class ThreadRecord extends DisplayRecord {
@Override
public SpannableString getDisplayBody(@NonNull Context context) {
+ Recipient recipient = getRecipient();
if (isGroupUpdate()) {
return emphasisAdded(context.getString(R.string.ThreadRecord_group_updated));
} else if (isGroupQuit()) {
@@ -79,8 +80,14 @@ public class ThreadRecord extends DisplayRecord {
return emphasisAdded(context.getString(R.string.ConversationListItem_key_exchange_message));
} else if (SmsDatabase.Types.isFailedDecryptType(type)) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_bad_encrypted_message));
- } else if (SmsDatabase.Types.isNoRemoteSessionType(type)) {
- return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
+ } else if (isLokiSessionRestoreSent()) {
+ return emphasisAdded(context.getString(R.string.MessageRecord_session_restore_sent, recipient.toShortString()));
+ } else if (isNoRemoteSession()) {
+ if (recipient.isGroupRecipient()) {
+ return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
+ } else {
+ return emphasisAdded(context.getString(R.string.MessageRecord_session_restore_required, recipient.toShortString()));
+ }
} else if (SmsDatabase.Types.isEndSessionType(type)) {
return emphasisAdded(context.getString(R.string.ThreadRecord_secure_session_reset));
} else if (MmsSmsColumns.Types.isLegacyType(type)) {
diff --git a/src/org/thoughtcrime/securesms/loki/ConversationUpdateItemViewDelegate.kt b/src/org/thoughtcrime/securesms/loki/ConversationUpdateItemViewDelegate.kt
new file mode 100644
index 0000000000..461f0c1612
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/loki/ConversationUpdateItemViewDelegate.kt
@@ -0,0 +1,7 @@
+package org.thoughtcrime.securesms.loki
+
+import org.thoughtcrime.securesms.database.model.MessageRecord
+
+interface ConversationUpdateItemViewDelegate {
+ fun updateItemButtonPressed(message: MessageRecord)
+}
\ No newline at end of file