From 216070fa5d1369da26c29f773186ecf02fe263e6 Mon Sep 17 00:00:00 2001 From: 0x330a <92654767+0x330a@users.noreply.github.com> Date: Mon, 1 May 2023 14:39:17 +1000 Subject: [PATCH] fix: finally fix the darn unread count issue by --- .../conversation/v2/ConversationActivityV2.kt | 2 +- .../securesms/database/MmsDatabase.kt | 2 +- .../securesms/database/SmsDatabase.java | 2 +- .../securesms/database/Storage.kt | 4 +- .../securesms/database/ThreadDatabase.java | 38 +++++++++++++++---- .../notifications/DefaultMessageNotifier.java | 4 +- .../util/ConfigurationMessageUtilities.kt | 1 - .../messaging/jobs/BatchMessageReceiveJob.kt | 7 +++- 8 files changed, 43 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 8ca153cd64..3448150ba1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -443,7 +443,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe withContext(Dispatchers.IO) { storage.markConversationAsRead(viewModel.threadId, SnodeAPI.nowWithOffset) } - val bufferedFlow = bufferedLastSeenChannel.consumeAsFlow() + val bufferedFlow = bufferedLastSeenChannel.consumeAsFlow().debounce(3.seconds) bufferedFlow.collectLatest { withContext(Dispatchers.IO) { storage.markConversationAsRead(viewModel.threadId, SnodeAPI.nowWithOffset) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt index eb42de5363..6abdd8a165 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt @@ -362,7 +362,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa fun setMessagesRead(threadId: Long, beforeTime: Long): List { return setMessagesRead( - THREAD_ID + " = ? AND (" + READ + " = 0 OR " + REACTIONS_UNREAD + " = 1) AND " + DATE_RECEIVED + " <= ?", + THREAD_ID + " = ? AND (" + READ + " = 0 OR " + REACTIONS_UNREAD + " = 1) AND " + DATE_SENT + " <= ?", arrayOf(threadId.toString(), beforeTime.toString()) ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 542e56b43d..296b9d3d3d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -319,7 +319,7 @@ public class SmsDatabase extends MessagingDatabase { } public List setMessagesRead(long threadId, long beforeTime) { - return setMessagesRead(THREAD_ID + " = ? AND (" + READ + " = 0 OR " + REACTIONS_UNREAD + " = 1) AND " + DATE_RECEIVED + " <= ?", new String[]{threadId+"", beforeTime+""}); + return setMessagesRead(THREAD_ID + " = ? AND (" + READ + " = 0 OR " + REACTIONS_UNREAD + " = 1) AND " + DATE_SENT + " <= ?", new String[]{threadId+"", beforeTime+""}); } public List setMessagesRead(long threadId) { return setMessagesRead(THREAD_ID + " = ? AND (" + READ + " = 0 OR " + REACTIONS_UNREAD + " = 1)", new String[] {String.valueOf(threadId)}); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 6b072d0e31..cb487ef973 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -216,7 +216,8 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co override fun markConversationAsRead(threadId: Long, lastSeenTime: Long) { val threadDb = DatabaseComponent.get(context).threadDatabase() getRecipientForThread(threadId)?.let { recipient -> - threadDb.markAllAsRead(threadId, recipient.isGroupRecipient, lastSeenTime) + // don't set the last read in the volatile if we didn't set it in the DB + if (!threadDb.markAllAsRead(threadId, recipient.isGroupRecipient, lastSeenTime)) return // don't process configs for inbox recipients if (recipient.isOpenGroupInboxRecipient) return @@ -1060,7 +1061,6 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co } override fun addLibSessionContacts(contacts: List) { - Log.d("Loki-DBG", "Adding contacts from execution context:\n${Thread.currentThread().stackTrace.joinToString("\n")}") val mappingDb = DatabaseComponent.get(context).blindedIdMappingDatabase() val moreContacts = contacts.filter { contact -> val id = SessionId(contact.id) 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 4b66b91ffb..4afdff3c7c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -315,6 +315,7 @@ public class ThreadDatabase extends Database { ContentValues contentValues = new ContentValues(1); contentValues.put(READ, 1); + Log.d("Loki-DBG", "setRead "+threadId+" @ "+lastReadTime); contentValues.put(LAST_SEEN, lastReadTime); SQLiteDatabase db = databaseHelper.getWritableDatabase(); @@ -335,6 +336,7 @@ public class ThreadDatabase extends Database { contentValues.put(UNREAD_MENTION_COUNT, 0); if (lastSeen) { + Log.d("Loki-DBG", "setRead "+threadId+" @ current time"); contentValues.put(LAST_SEEN, SnodeAPI.getNowWithOffset()); } @@ -526,9 +528,16 @@ public class ThreadDatabase extends Database { return db.rawQuery(query, null); } - public void setLastSeen(long threadId, long timestamp) { + /** + * @param threadId + * @param timestamp + * @return true if we have set the last seen for the thread, false if there were no messages in the thread + */ + public boolean setLastSeen(long threadId, long timestamp) { // edge case where we set the last seen time for a conversation before it loads messages (joining community for example) - if (getMessageCount(threadId) <= 0) return; + MmsSmsDatabase mmsSmsDatabase = DatabaseComponent.get(context).mmsSmsDatabase(); + if (mmsSmsDatabase.getConversationCount(threadId) <= 0) return false; + Log.d("Loki-DBG", "setLastSeen "+threadId+" @ "+timestamp); SQLiteDatabase db = databaseHelper.getWritableDatabase(); @@ -552,11 +561,17 @@ public class ThreadDatabase extends Database { db.execSQL(reflectUpdates, new Object[]{threadId}); db.setTransactionSuccessful(); db.endTransaction(); + Log.d("Loki-DBG", "Updated last seen to "+timestamp); notifyConversationListListeners(); + return true; } - public void setLastSeen(long threadId) { - setLastSeen(threadId, -1); + /** + * @param threadId + * @return true if we have set the last seen for the thread, false if there were no messages in the thread + */ + public boolean setLastSeen(long threadId) { + return setLastSeen(threadId, -1); } public Pair getLastSeenAndHasSent(long threadId) { @@ -716,7 +731,7 @@ public class ThreadDatabase extends Database { MmsSmsDatabase mmsSmsDatabase = DatabaseComponent.get(context).mmsSmsDatabase(); long count = mmsSmsDatabase.getConversationCount(threadId); - boolean shouldDeleteEmptyThread = !shouldDeleteOnEmpty ? false : deleteThreadOnEmpty(threadId); + boolean shouldDeleteEmptyThread = shouldDeleteOnEmpty && deleteThreadOnEmpty(threadId); if (count == 0 && shouldDeleteEmptyThread) { deleteThread(threadId); @@ -778,7 +793,16 @@ public class ThreadDatabase extends Database { } } - public void markAllAsRead(long threadId, boolean isGroupRecipient, long lastSeenTime) { + /** + * @param threadId + * @param isGroupRecipient + * @param lastSeenTime + * @return true if we have set the last seen for the thread, false if there were no messages in the thread + */ + public boolean markAllAsRead(long threadId, boolean isGroupRecipient, long lastSeenTime) { + MmsSmsDatabase mmsSmsDatabase = DatabaseComponent.get(context).mmsSmsDatabase(); + if (mmsSmsDatabase.getConversationCount(threadId) <= 0) return false; + Log.d("Loki-DBG", "markAllAsRead "+threadId+" @ "+lastSeenTime); List messages = setRead(threadId, lastSeenTime); if (isGroupRecipient) { for (MarkedMessageInfo message: messages) { @@ -788,7 +812,7 @@ public class ThreadDatabase extends Database { MarkReadReceiver.process(context, messages); } ApplicationContext.getInstance(context).messageNotifier.updateNotification(context, threadId); - setLastSeen(threadId, lastSeenTime); + return setLastSeen(threadId, lastSeenTime); } private boolean deleteThreadOnEmpty(long threadId) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java index 327492e95c..dfa953044b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java @@ -240,8 +240,8 @@ public class DefaultMessageNotifier implements MessageNotifier { !(recipient.isApproved() || threads.getLastSeenAndHasSent(threadId).second())) { TextSecurePreferences.removeHasHiddenMessageRequests(context); } - if (isVisible && recipient != null) { - List messageIds = threads.setRead(threadId, false); + if (isVisible && recipient != null && threads.getMessageCount(threadId) > 0) { + List messageIds = threads.setRead(threadId, true); if (SessionMetaProtocol.shouldSendReadReceipt(recipient)) { MarkReadReceiver.process(context, messageIds); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt index d01a07def2..8f4fd61044 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt @@ -85,7 +85,6 @@ object ConfigurationMessageUtilities { if (ConfigBase.isNewConfigEnabled) { // schedule job if none exist // don't schedule job if we already have one - Log.d("Loki-DBG", "Forcing config sync") scheduleConfigSync(userPublicKey) return Promise.ofSuccess(Unit) } diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/BatchMessageReceiveJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/BatchMessageReceiveJob.kt index aeb31ff209..b5e7cf8848 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/BatchMessageReceiveJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/BatchMessageReceiveJob.kt @@ -155,7 +155,8 @@ class BatchMessageReceiveJob( // The LinkedHashMap should preserve insertion order val messageIds = linkedMapOf>() val myLastSeen = storage.getLastSeen(threadId) - var newLastSeen = myLastSeen + var newLastSeen = if (myLastSeen == -1L) 0 else myLastSeen + Log.d("Loki-DBG", "myLastSeen = $newLastSeen") messages.forEach { (parameters, message, proto) -> try { when (message) { @@ -224,10 +225,12 @@ class BatchMessageReceiveJob( // increment unreads, notify, and update thread // last seen will be the current last seen if not changed (re-computes the read counts for thread record) // might have been updated from a different thread at this point - val currentLastSeen = storage.getLastSeen(threadId) + val currentLastSeen = storage.getLastSeen(threadId).let { if (it == -1L) 0 else it } + Log.d("Loki-DBG", "currentLastSeen = $currentLastSeen") if (currentLastSeen > newLastSeen) { newLastSeen = currentLastSeen } + Log.d("Loki-DBG", "newLastSeen = $newLastSeen") storage.markConversationAsRead(threadId, newLastSeen) storage.updateThread(threadId, true) SSKEnvironment.shared.notificationManager.updateNotification(context, threadId)