From 138cd432af454f5144b3e0d362e43c23ad98ac72 Mon Sep 17 00:00:00 2001 From: Sarafaraj Nasardi Date: Thu, 11 Dec 2025 13:56:41 +0530 Subject: [PATCH] model: Prevent duplicate flags when processing update_message_flags. Fixes #1986. --- lib/model/message.dart | 14 ++++++++++---- test/model/message_test.dart | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/lib/model/message.dart b/lib/model/message.dart index 936bc3bb1f..95014c8c30 100644 --- a/lib/model/message.dart +++ b/lib/model/message.dart @@ -736,7 +736,9 @@ class MessageStoreImpl extends HasChannelStore with MessageStore, _OutboxMessage if (isAdd && (event as UpdateMessageFlagsAddEvent).all) { for (final message in messages.values) { - message.flags.add(event.flag); + if (!message.flags.contains(event.flag)) { + message.flags.add(event.flag); + } } for (final view in _messageListViews) { @@ -750,9 +752,13 @@ class MessageStoreImpl extends HasChannelStore with MessageStore, _OutboxMessage if (message == null) continue; // a message we don't know about yet anyMessageFound = true; - isAdd - ? message.flags.add(event.flag) - : message.flags.remove(event.flag); + if (isAdd) { + if (!message.flags.contains(event.flag)) { + message.flags.add(event.flag); + } + } else { + message.flags.remove(event.flag); + } } if (anyMessageFound) { // TODO(#818): Support MentionsNarrow live-updates when handling diff --git a/test/model/message_test.dart b/test/model/message_test.dart index 96d95c0c04..7fc8a626b7 100644 --- a/test/model/message_test.dart +++ b/test/model/message_test.dart @@ -1702,6 +1702,34 @@ void main() { check(store).messages.values .single.flags.deepEquals([MessageFlag.starred, MessageFlag.read]); }); + + test('avoid duplicate flags', () async { + // Regression test for https://github.com/zulip/zulip-flutter/issues/1986 + await prepare(); + final message = eg.streamMessage(flags: [MessageFlag.read]); + await prepareMessages([message]); + + await store.handleEvent(mkAddEvent(MessageFlag.read, [message.id])); + check(store).messages.values.single.flags.deepEquals([MessageFlag.read]); + }); + + test('handle update_message_flags: add flag "all" is idempotent', () async { + // Regression test for https://github.com/zulip/zulip-flutter/issues/1986 + await prepare(); + final m1 = eg.streamMessage(flags: [MessageFlag.read]); + final m2 = eg.streamMessage(flags: []); + await prepareMessages([m1, m2]); + + await store.handleEvent(UpdateMessageFlagsAddEvent( + id: 1, + all: true, + flag: MessageFlag.read, + messages: [], + )); + + check(store.messages[m1.id]!.flags).deepEquals([MessageFlag.read]); + check(store.messages[m2.id]!.flags).deepEquals([MessageFlag.read]); + }); }); group('remove flag', () {