Option to lock a specific thread

Stephen Paul Weber created

Change summary

src/cheogram/res/values/strings.xml                               |  1 
src/cheogram/res/values/themes.xml                                |  2 
src/main/java/eu/siacs/conversations/entities/Conversation.java   | 13 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 19 
src/main/res/layout/fragment_conversation.xml                     | 36 
src/main/res/menu/message_context.xml                             |  5 
src/main/res/values/attrs.xml                                     |  1 
7 files changed, 65 insertions(+), 12 deletions(-)

Detailed changes

src/cheogram/res/values/strings.xml 🔗

@@ -25,6 +25,7 @@
     <string name="action_execute">Go</string>
     <string name="pref_theme_oledblack">OLED Black</string>
     <string name="invite_to_app">Invite to Chat</string>
+    <string name="only_this_thread">Show only this thread</string>
     <string name="pref_dialler_integration_incoming">Use Phone Accounts for Incoming Calls</string>
     <string name="pref_dialler_integration_incoming_summary">Incoming calls from phone numbers may ring with your system dialler instead of this app\'s notification settings</string>
 </resources>

src/cheogram/res/values/themes.xml 🔗

@@ -121,6 +121,7 @@
         <item name="icon_help" type="reference">@drawable/ic_help_white_24dp</item>
         <item name="icon_goto_chat" type="reference">@drawable/ic_question_answer_white_24dp</item>
         <item name="icon_secure" type="reference">@drawable/ic_lock_open_white_24dp</item>
+        <item name="icon_small_lock" type="reference">@drawable/ic_lock_black_18dp</item>
         <item name="icon_settings" type="reference">@drawable/ic_settings_black_24dp</item>
         <item name="icon_share" type="reference">@drawable/ic_share_white_24dp</item>
         <item name="ic_cloud_download" type="reference">@drawable/ic_cloud_download_white_24dp
@@ -275,6 +276,7 @@
         <item name="icon_help" type="reference">@drawable/ic_help_white_24dp</item>
         <item name="icon_goto_chat" type="reference">@drawable/ic_question_answer_white_24dp</item>
         <item name="icon_secure" type="reference">@drawable/ic_lock_open_white_24dp</item>
+        <item name="icon_small_lock" type="reference">@drawable/ic_lock_white_18dp</item>
         <item name="icon_settings" type="reference">@drawable/ic_settings_white_24dp</item>
         <item name="icon_share" type="reference">@drawable/ic_share_white_24dp</item>
         <item name="ic_cloud_download" type="reference">@drawable/ic_cloud_download_white_24dp

src/main/java/eu/siacs/conversations/entities/Conversation.java 🔗

@@ -149,6 +149,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
     protected int mCurrentTab = -1;
     protected ConversationPagerAdapter pagerAdapter = new ConversationPagerAdapter();
     protected Element thread = null;
+    protected boolean lockThread = false;
     protected boolean userSelectedThread = false;
 
     public Conversation(final String name, final Account account, final Jid contactJid,
@@ -531,7 +532,8 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
             messages.addAll(this.messages);
         }
         for (Iterator<Message> iterator = messages.iterator(); iterator.hasNext(); ) {
-            if (iterator.next().wasMergedIntoPrevious()) {
+            Message m = iterator.next();
+            if (m.wasMergedIntoPrevious() || (getLockThread() && (m.getThread() == null || !m.getThread().getContent().equals(getThread().getContent())))) {
                 iterator.remove();
             }
         }
@@ -638,6 +640,15 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
         this.thread = thread;
     }
 
+    public void setLockThread(boolean flag) {
+        this.lockThread = flag;
+        if (flag) setUserSelectedThread(true);
+    }
+
+    public boolean getLockThread() {
+        return this.lockThread;
+    }
+
     public void setUserSelectedThread(boolean flag) {
         this.userSelectedThread = flag;
     }

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -1257,14 +1257,20 @@ public class ConversationFragment extends XmppFragment
             conversation.setUserSelectedThread(true);
         });
 
-        binding.threadIdenticon.setOnClickListener(v -> {
+        binding.threadIdenticonLayout.setOnClickListener(v -> {
+            boolean wasLocked = conversation.getLockThread();
+            conversation.setLockThread(false);
             newThread();
             conversation.setUserSelectedThread(true);
+            if (wasLocked) refresh();
         });
 
-        binding.threadIdenticon.setOnLongClickListener(v -> {
+        binding.threadIdenticonLayout.setOnLongClickListener(v -> {
+            boolean wasLocked = conversation.getLockThread();
+            conversation.setLockThread(false);
             setThread(null);
             conversation.setUserSelectedThread(true);
+            if (wasLocked) refresh();
             return true;
         });
 
@@ -1303,6 +1309,7 @@ public class ConversationFragment extends XmppFragment
     private void setThread(Element thread) {
         this.conversation.setThread(thread);
         binding.threadIdenticon.setAlpha(0f);
+        binding.threadIdenticonLock.setVisibility(this.conversation.getLockThread() ? View.VISIBLE : View.GONE);
         if (thread != null) {
             final String threadId = thread.getContent();
             if (threadId != null) {
@@ -1362,6 +1369,7 @@ public class ConversationFragment extends XmppFragment
             MenuItem retryDecryption = menu.findItem(R.id.retry_decryption);
             MenuItem correctMessage = menu.findItem(R.id.correct_message);
             MenuItem retractMessage = menu.findItem(R.id.retract_message);
+            MenuItem onlyThisThread = menu.findItem(R.id.only_this_thread);
             MenuItem shareWith = menu.findItem(R.id.share_with);
             MenuItem sendAgain = menu.findItem(R.id.send_again);
             MenuItem copyUrl = menu.findItem(R.id.copy_url);
@@ -1369,6 +1377,7 @@ public class ConversationFragment extends XmppFragment
             MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission);
             MenuItem deleteFile = menu.findItem(R.id.delete_file);
             MenuItem showErrorMessage = menu.findItem(R.id.show_error_message);
+            onlyThisThread.setVisible(!conversation.getLockThread() && m.getThread() != null);
             final boolean unInitiatedButKnownSize = MessageUtils.unInitiatedButKnownSize(m);
             final boolean showError =
                     m.getStatus() == Message.STATUS_SEND_FAILED
@@ -1505,6 +1514,12 @@ public class ConversationFragment extends XmppFragment
             case R.id.open_with:
                 openWith(selectedMessage);
                 return true;
+            case R.id.only_this_thread:
+                conversation.setLockThread(true);
+                setThread(selectedMessage.getThread());
+                refresh();
+                setThread(selectedMessage.getThread());
+                return true;
             default:
                 return super.onContextItemSelected(item);
         }

src/main/res/layout/fragment_conversation.xml 🔗

@@ -62,8 +62,8 @@
                         android:layout_height="wrap_content"
                         android:layout_toStartOf="@+id/textSendButton"
                         android:layout_toLeftOf="@+id/textSendButton"
-                        android:layout_toEndOf="@+id/thread_identicon"
-                        android:layout_toRightOf="@+id/thread_identicon"
+                        android:layout_toEndOf="@+id/thread_identicon_layout"
+                        android:layout_toRightOf="@+id/thread_identicon_layout"
                         android:orientation="vertical">
     
                         <TextView
@@ -109,16 +109,34 @@
 
                     </LinearLayout>
 
-                    <com.lelloman.identicon.view.GithubIdenticonView
-                        android:id="@+id/thread_identicon"
-                        android:alpha="0"
-                        android:layout_width="24dp"
-                        android:layout_height="24dp"
-                        android:layout_marginLeft="8dp"
+                    <RelativeLayout
+                        android:id="@+id/thread_identicon_layout"
+                        android:layout_width="30dp"
+                        android:layout_height="30dp"
                         android:layout_alignParentStart="true"
                         android:layout_alignParentLeft="true"
                         android:layout_centerVertical="true"
-                        android:contentDescription="Thread Marker" />
+                        android:layout_marginLeft="8dp">
+
+                        <com.lelloman.identicon.view.GithubIdenticonView
+                            android:id="@+id/thread_identicon"
+                            android:alpha="0"
+                            android:layout_width="24dp"
+                            android:layout_height="24dp"
+                            android:layout_centerVertical="true"
+                            android:contentDescription="Thread Marker" />
+                        <ImageView
+                            android:id="@+id/thread_identicon_lock"
+                            android:layout_width="12dp"
+                            android:layout_height="12dp"
+                            android:layout_alignParentTop="true"
+                            android:layout_alignParentEnd="true"
+                            android:layout_alignParentRight="true"
+                            android:visibility="gone"
+                            android:src="?attr/icon_small_lock"
+                            android:contentDescription="Thread Locked" />
+
+                    </RelativeLayout>
 
                     <ImageButton
                         android:id="@+id/textSendButton"

src/main/res/menu/message_context.xml 🔗

@@ -21,6 +21,11 @@
         android:title="@string/quote"
         android:visible="false" />
 
+    <item
+        android:id="@+id/only_this_thread"
+        android:title="@string/only_this_thread"
+        android:visible="false" />
+
     <item
         android:id="@+id/retry_decryption"
         android:title="@string/retry_decryption"

src/main/res/values/attrs.xml 🔗

@@ -106,6 +106,7 @@
     <attr name="icon_help" format="reference" />
     <attr name="icon_goto_chat" format="reference" />
     <attr name="icon_secure" format="reference" />
+    <attr name="icon_small_lock" format="reference" />
     <attr name="icon_settings" format="reference" />
     <attr name="icon_share" format="reference" />
     <attr name="icon_import_export" format="reference" />