diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java index bb8d720d51..20d0331ed3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java @@ -1026,24 +1026,34 @@ public class ConversationListFragment extends MainFragment implements ActionMode Snackbar.LENGTH_LONG, false) { + private final ThreadDatabase threadDatabase= DatabaseFactory.getThreadDatabase(getActivity()); + + private List pinnedThreadIds; + @Override protected void executeAction(@Nullable Long parameter) { - DatabaseFactory.getThreadDatabase(getActivity()).archiveConversation(threadId); + Context context = requireActivity(); + + pinnedThreadIds = threadDatabase.getPinnedThreadIds(); + threadDatabase.archiveConversation(threadId); if (unreadCount > 0) { - List messageIds = DatabaseFactory.getThreadDatabase(getActivity()).setRead(threadId, false); - ApplicationDependencies.getMessageNotifier().updateNotification(getActivity()); - MarkReadReceiver.process(getActivity(), messageIds); + List messageIds = threadDatabase.setRead(threadId, false); + ApplicationDependencies.getMessageNotifier().updateNotification(context); + MarkReadReceiver.process(context, messageIds); } } @Override protected void reverseAction(@Nullable Long parameter) { - DatabaseFactory.getThreadDatabase(getActivity()).unarchiveConversation(threadId); + Context context = requireActivity(); + + threadDatabase.unarchiveConversation(threadId); + threadDatabase.restorePins(pinnedThreadIds); if (unreadCount > 0) { - DatabaseFactory.getThreadDatabase(getActivity()).incrementUnread(threadId, unreadCount); - ApplicationDependencies.getMessageNotifier().updateNotification(getActivity()); + threadDatabase.incrementUnread(threadId, unreadCount); + ApplicationDependencies.getMessageNotifier().updateNotification(context); } } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, threadId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java index dd9353079d..0fd803be87 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -70,6 +70,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -797,13 +798,10 @@ public class ThreadDatabase extends Database { * @return Pinned recipients, in order from top to bottom. */ public @NonNull List getPinnedRecipientIds() { - SQLiteDatabase db = databaseHelper.getReadableDatabase(); - String[] projection = new String[]{RECIPIENT_ID}; - String query = PINNED + " > ?"; - String[] args = SqlUtil.buildArgs(0); + String[] projection = new String[]{ID, RECIPIENT_ID}; List pinned = new LinkedList<>(); - try (Cursor cursor = db.query(TABLE_NAME, projection, query, args, null, null, PINNED + " ASC")) { + try (Cursor cursor = getPinned(projection)) { while (cursor.moveToNext()) { pinned.add(RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID))); } @@ -812,14 +810,64 @@ public class ThreadDatabase extends Database { return pinned; } - public void pinConversations(@NonNull Set threadIds) { + /** + * @return Pinned thread ids, in order from top to bottom. + */ + public @NonNull List getPinnedThreadIds() { + String[] projection = new String[]{ID}; + List pinned = new LinkedList<>(); + + try (Cursor cursor = getPinned(projection)) { + while (cursor.moveToNext()) { + pinned.add(CursorUtil.requireLong(cursor, ID)); + } + } + + return pinned; + } + + /** + * @return Pinned recipients, in order from top to bottom. + */ + private @NonNull Cursor getPinned(String[] projection) { + SQLiteDatabase db = databaseHelper.getReadableDatabase(); + String query = PINNED + " > ?"; + String[] args = SqlUtil.buildArgs(0); + + return db.query(TABLE_NAME, projection, query, args, null, null, PINNED + " ASC"); + } + + public void restorePins(@NonNull Collection threadIds) { + Log.d(TAG, "Restoring pinned threads " + StringUtil.join(threadIds, ",")); + pinConversations(threadIds, true); + } + + public void pinConversations(@NonNull Collection threadIds) { + Log.d(TAG, "Pinning threads " + StringUtil.join(threadIds, ",")); + pinConversations(threadIds, false); + } + + private void pinConversations(@NonNull Collection threadIds, boolean clearFirst) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); + threadIds = new LinkedHashSet<>(threadIds); try { db.beginTransaction(); + if (clearFirst) { + ContentValues contentValues = new ContentValues(1); + contentValues.put(PINNED, 0); + String query = PINNED + " > ?"; + String[] args = SqlUtil.buildArgs(0); + db.update(TABLE_NAME, contentValues, query, args); + } + int pinnedCount = getPinnedConversationListCount(); + if (pinnedCount > 0 && clearFirst) { + throw new AssertionError(); + } + for (long threadId : threadIds) { ContentValues contentValues = new ContentValues(1); contentValues.put(PINNED, ++pinnedCount);