diff --git a/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java b/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java index bd9cee321..45c2ecb56 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/client/MessageTracker.java @@ -47,8 +47,8 @@ public interface MessageTracker { throws DbException; /** - * Loads the stored message id for the respective group id or returns null - * if none is available. + * Loads the stored message id for the respective group id or returns null + * if none is available. */ @Nullable MessageId loadStoredMessageId(GroupId g) throws DbException; @@ -64,6 +64,16 @@ public interface MessageTracker { */ void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException; + /** + * Resets the {@link GroupCount} to the given msgCount and unreadCount. + * The latestMsgTime will be set to the current time. + *

+ * Such reset is needed when recalculating the counts + * after deleting messages from a group. + */ + void resetGroupCount(Transaction txn, GroupId g, int msgCount, + int unreadCount) throws DbException; + class GroupCount { private final int msgCount, unreadCount; diff --git a/briar-core/src/main/java/org/briarproject/briar/client/ConversationClientImpl.java b/briar-core/src/main/java/org/briarproject/briar/client/ConversationClientImpl.java index 9d12c5aba..4ba35c020 100644 --- a/briar-core/src/main/java/org/briarproject/briar/client/ConversationClientImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/client/ConversationClientImpl.java @@ -31,15 +31,6 @@ public abstract class ConversationClientImpl extends BdfIncomingMessageHook this.messageTracker = messageTracker; } - /** - * Initializes the group count with zero messages, - * but uses the current time as latest message time for sorting. - */ - protected void initializeGroupCount(Transaction txn, GroupId g) - throws DbException { - messageTracker.initializeGroupCount(txn, g); - } - @Override public GroupCount getGroupCount(Transaction txn, ContactId contactId) throws DbException { diff --git a/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java index ef3fcb702..08a94985a 100644 --- a/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/client/MessageTrackerImpl.java @@ -169,4 +169,12 @@ class MessageTrackerImpl implements MessageTracker { } } + @Override + public void resetGroupCount(Transaction txn, GroupId g, int msgCount, + int unreadCount) throws DbException { + long now = clock.currentTimeMillis(); + GroupCount groupCount = new GroupCount(msgCount, unreadCount, now); + storeGroupCount(txn, g, groupCount); + } + } diff --git a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java index f7083956b..128f73445 100644 --- a/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/introduction/IntroductionManagerImpl.java @@ -603,7 +603,9 @@ class IntroductionManagerImpl extends ConversationClientImpl for (MessageStatus status : db.getMessageStatus(txn, c, g)) { if (!status.isSeen()) notAcked.add(status.getMessageId()); } - return deleteCompletedSessions(txn, sessions, notAcked); + boolean allDeleted = deleteCompletedSessions(txn, sessions, notAcked); + recalculateGroupCount(txn, g); + return allDeleted; } private DeletableSession getDeletableSession(Transaction txn, @@ -671,6 +673,31 @@ class IntroductionManagerImpl extends ConversationClientImpl } } + private void recalculateGroupCount(Transaction txn, GroupId g) + throws DbException { + BdfDictionary query = messageParser.getMessagesVisibleInUiQuery(); + Map results; + try { + results = + clientHelper.getMessageMetadataAsDictionary(txn, g, query); + } catch (FormatException e) { + throw new DbException(e); + } + int msgCount = 0; + int unreadCount = 0; + for (Entry entry : results.entrySet()) { + MessageMetadata meta; + try { + meta = messageParser.parseMetadata(entry.getValue()); + } catch (FormatException e) { + throw new DbException(e); + } + msgCount++; + if (!meta.isRead()) unreadCount++; + } + messageTracker.resetGroupCount(txn, g, msgCount, unreadCount); + } + private static class StoredSession { private final MessageId storageId; diff --git a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java index cd6cbbd3e..969af3864 100644 --- a/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/messaging/MessagingManagerImpl.java @@ -414,6 +414,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook, db.deleteMessage(txn, messageId); db.deleteMessageMetadata(txn, messageId); } + messageTracker.initializeGroupCount(txn, g); return true; } diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java index 84b73c2d4..067f4b08d 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java @@ -1209,15 +1209,24 @@ public class IntroductionIntegrationTest assertTrue(listener1.succeeded); assertTrue(listener2.succeeded); + // check that introducer messages are tracked properly + Group g1 = introductionManager0.getContactGroup(contact1From0); + assertGroupCount(messageTracker0, g1.getId(), 2, 1); + // introducer can now remove messages assertTrue(deleteAllMessages1From0()); assertEquals(0, getMessages1From0().size()); assertTrue(deleteAllMessages1From0()); // a second time returns true + assertGroupCount(messageTracker0, g1.getId(), 0, 0); // introducee1 can not yet remove messages, because last not ACKed assertFalse(deleteAllMessages0From1()); assertEquals(2, getMessages0From1().size()); + // check that introducee1 messages are tracked properly + Group g0 = introductionManager1.getContactGroup(contact0From1); + assertGroupCount(messageTracker1, g0.getId(), 2, 1); + // ACK last message sendAcks(c0, c1, contactId1From0, 1); @@ -1225,11 +1234,17 @@ public class IntroductionIntegrationTest assertTrue(deleteAllMessages0From1()); assertEquals(0, getMessages0From1().size()); assertTrue(deleteAllMessages0From1()); // a second time returns true + assertGroupCount(messageTracker1, g0.getId(), 0, 0); + + // check that introducee2 messages are tracked properly + Group g0From2 = introductionManager2.getContactGroup(contact0From2); + assertGroupCount(messageTracker2, g0From2.getId(), 2, 1); // introducee2 can remove messages (last message was incoming) assertTrue(deleteAllMessages0From2()); assertEquals(0, getMessages0From2().size()); assertTrue(deleteAllMessages0From2()); // a second time returns true + assertGroupCount(messageTracker2, g0From2.getId(), 0, 0); // a new introduction is still possible assertTrue(introductionManager0 @@ -1255,6 +1270,11 @@ public class IntroductionIntegrationTest assertFalse(deleteAllMessages2From0()); assertFalse(deleteAllMessages0From1()); assertFalse(deleteAllMessages0From2()); + + // group counts get counted up again correctly + assertGroupCount(messageTracker0, g1.getId(), 2, 1); + assertGroupCount(messageTracker1, g0.getId(), 2, 1); + assertGroupCount(messageTracker2, g0From2.getId(), 2, 1); } @Test