Skip to content

Commit 6d89782

Browse files
committed
unreads: Fix topic case-sensitivity.
Maps canoncalized topic names to a variant of the actual topic name. Fixes zulip#980.
1 parent 449f326 commit 6d89782

File tree

4 files changed

+40
-12
lines changed

4 files changed

+40
-12
lines changed

lib/model/unreads.dart

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,14 @@ class Unreads extends ChangeNotifier {
4242
}) {
4343
final streams = <int, Map<TopicName, QueueList<int>>>{};
4444
final dms = <DmNarrow, QueueList<int>>{};
45+
// Maps the lowercased version of topic to one of the actual versions
46+
final topicMapper = <String, TopicName>{};
4547
final mentions = Set.of(initial.mentions);
4648

4749
for (final unreadChannelSnapshot in initial.channels) {
4850
final streamId = unreadChannelSnapshot.streamId;
4951
final topic = unreadChannelSnapshot.topic;
52+
topicMapper[topic.canonicalize()] = topic;
5053
(streams[streamId] ??= {})[topic] = QueueList.from(unreadChannelSnapshot.unreadMessageIds);
5154
}
5255

@@ -64,6 +67,7 @@ class Unreads extends ChangeNotifier {
6467
return Unreads._(
6568
channelStore: channelStore,
6669
streams: streams,
70+
topicMapper: topicMapper,
6771
dms: dms,
6872
mentions: mentions,
6973
oldUnreadsMissing: initial.oldUnreadsMissing,
@@ -74,6 +78,7 @@ class Unreads extends ChangeNotifier {
7478
Unreads._({
7579
required this.channelStore,
7680
required this.streams,
81+
required this.topicMapper,
7782
required this.dms,
7883
required this.mentions,
7984
required this.oldUnreadsMissing,
@@ -91,6 +96,9 @@ class Unreads extends ChangeNotifier {
9196
/// Unread DM messages, as: DM narrow → message IDs (sorted).
9297
final Map<DmNarrow, QueueList<int>> dms;
9398

99+
// Maps lowercase topic names for lookup to one of the variants of the topic (case preserving).
100+
final Map<String, TopicName> topicMapper;
101+
94102
/// Unread messages with the self-user @-mentioned, directly or by wildcard.
95103
///
96104
/// At initialization, if a message is:
@@ -380,9 +388,19 @@ class Unreads extends ChangeNotifier {
380388
}
381389
switch (detail.type) {
382390
case MessageType.stream:
391+
final topicKey = detail.topic!.canonicalize();
392+
TopicName actualTopicName;
393+
if (topicMapper[topicKey] != null) {
394+
actualTopicName = topicMapper[topicKey] as TopicName;
395+
} else {
396+
topicMapper[topicKey] = detail.topic!;
397+
actualTopicName = detail.topic!;
398+
}
399+
383400
final topics = (newlyUnreadInStreams[detail.streamId!] ??= {});
384-
final messageIds = (topics[detail.topic!] ??= QueueList());
401+
final messageIds = (topics[actualTopicName!] ??= QueueList());
385402
messageIds.add(messageId);
403+
386404
case MessageType.direct:
387405
final narrow = DmNarrow.ofUpdateMessageFlagsMessageDetail(selfUserId: selfUserId,
388406
detail);
@@ -450,7 +468,12 @@ class Unreads extends ChangeNotifier {
450468
}
451469

452470
void _addLastInStreamTopic(int messageId, int streamId, TopicName topic) {
453-
((streams[streamId] ??= {})[topic] ??= QueueList()).addLast(messageId);
471+
if (topicMapper[topic.canonicalize()] != null && topic.isSameAs(topicMapper[topic.canonicalize()]!)) {
472+
((streams[streamId] ??= {})[topicMapper[topic.canonicalize()]!] ??= QueueList()).addLast(messageId);
473+
} else {
474+
topicMapper[topic.canonicalize()] = topic;
475+
((streams[streamId] ??= {})[topic] ??= QueueList()).addLast(messageId);
476+
}
454477
}
455478

456479
// [messageIds] must be sorted ascending and without duplicates.

lib/widgets/inbox.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class _InboxPageState extends State<InboxPageBody> with PerAccountStoreAwareStat
136136
int countInStream = 0;
137137
bool streamHasMention = false;
138138
for (final MapEntry(key: topic, value: messageIds) in topics.entries) {
139-
if (!store.isTopicVisible(streamId, topic)) continue;
139+
if (!store.isTopicVisible(streamId, unreadsModel!=null ? (unreadsModel?.topicMapper[topic.canonicalize()])! : topic!)) continue;
140140
final countInTopic = messageIds.length;
141141
final hasMention = messageIds.any((messageId) => unreadsModel!.mentions.contains(messageId));
142142
if (hasMention) streamHasMention = true;

pubspec.lock

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -291,10 +291,10 @@ packages:
291291
dependency: "direct dev"
292292
description:
293293
name: fake_async
294-
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
294+
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
295295
url: "https://pub.dev"
296296
source: hosted
297-
version: "1.3.2"
297+
version: "1.3.3"
298298
ffi:
299299
dependency: transitive
300300
description:
@@ -647,10 +647,10 @@ packages:
647647
dependency: transitive
648648
description:
649649
name: leak_tracker
650-
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
650+
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
651651
url: "https://pub.dev"
652652
source: hosted
653-
version: "10.0.8"
653+
version: "10.0.9"
654654
leak_tracker_flutter_testing:
655655
dependency: transitive
656656
description:
@@ -1244,10 +1244,10 @@ packages:
12441244
dependency: transitive
12451245
description:
12461246
name: vm_service
1247-
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
1247+
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
12481248
url: "https://pub.dev"
12491249
source: hosted
1250-
version: "14.3.1"
1250+
version: "15.0.0"
12511251
wakelock_plus:
12521252
dependency: "direct main"
12531253
description:
@@ -1300,10 +1300,10 @@ packages:
13001300
dependency: transitive
13011301
description:
13021302
name: webdriver
1303-
sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8"
1303+
sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade"
13041304
url: "https://pub.dev"
13051305
source: hosted
1306-
version: "3.0.4"
1306+
version: "3.1.0"
13071307
webkit_inspection_protocol:
13081308
dependency: transitive
13091309
description:

test/model/unreads_test.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ void main() {
6060

6161
final Map<int, Map<TopicName, QueueList<int>>> expectedStreams = {};
6262
final Map<DmNarrow, QueueList<int>> expectedDms = {};
63+
final Map<String, TopicName> topicMapper = {};
6364
final Set<int> expectedMentions = {};
6465
for (final message in messages) {
6566
if (message.flags.contains(MessageFlag.read)) {
@@ -68,7 +69,10 @@ void main() {
6869
switch (message) {
6970
case StreamMessage():
7071
final perTopic = expectedStreams[message.streamId] ??= {};
71-
final messageIds = perTopic[message.topic] ??= QueueList();
72+
if (topicMapper[message.topic.canonicalize()] == null) {
73+
topicMapper[message.topic.canonicalize()] = message.topic;
74+
}
75+
final messageIds = perTopic[topicMapper[message.topic.canonicalize()]!] ??= QueueList();
7276
messageIds.add(message.id);
7377
case DmMessage():
7478
final narrow = DmNarrow.ofMessage(message, selfUserId: eg.selfUser.userId);
@@ -332,6 +336,7 @@ void main() {
332336
final stream2 = eg.stream(streamId: 2);
333337
for (final (oldStream, newStream, oldTopic, newTopic) in [
334338
(stream1, stream1, 'a', 'a'),
339+
(stream1, stream1, 'a', 'A'),
335340
(stream1, stream1, 'a', 'b'),
336341
(stream1, stream2, 'a', 'a'),
337342
(stream1, stream2, 'a', 'b'),

0 commit comments

Comments
 (0)