Repository navigation
feat(mobile): opening a channel quiets its list row #9271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import '../../shared/read_state/read_state_format.dart'; | ||
| import '../../shared/read_state/read_state_provider.dart'; | ||
| import 'channel.dart'; | ||
| import 'channels_provider.dart'; | ||
|
|
@@ -21,7 +22,9 @@ Set<String> computeUnreadChannelIds({ | |
| /// Unread thread replies, mentions and broadcasts only add an attention dot | ||
| /// ([attention]), so a channel the reader caught up on stays regular. An | ||
| /// unread DM bolds and dots. Marking a channel unread bolds it without | ||
| /// fabricating attention, but keeps any real attention's dot. | ||
| /// fabricating attention, but keeps any real attention's dot. What the row | ||
| /// has seen ([rowSawObservedUnreadEvent]) neither bolds nor dots it, unless | ||
| /// the reader marked the channel or one of its messages unread. | ||
| ({Set<String> unread, Set<String> attention}) computeChannelListHighlights({ | ||
| required Iterable<Channel> channels, | ||
| required ReadStateState readState, | ||
|
|
@@ -31,13 +34,15 @@ Set<String> computeUnreadChannelIds({ | |
| readState: readState, | ||
| channelsNotifier: channelsNotifier, | ||
| separateAttention: true, | ||
| rowCut: true, | ||
| ); | ||
|
|
||
| ({Set<String> unread, Set<String> attention}) _computeHighlights({ | ||
| required Iterable<Channel> channels, | ||
| required ReadStateState readState, | ||
| required ChannelsNotifier channelsNotifier, | ||
| required bool separateAttention, | ||
| bool rowCut = false, | ||
| }) { | ||
| final unread = <String>{}; | ||
| final attention = <String>{}; | ||
|
|
@@ -60,13 +65,23 @@ Set<String> computeUnreadChannelIds({ | |
|
|
||
| final observedEvents = observedEventsByChannel[channel.id]; | ||
| if (observedEvents == null) continue; | ||
| final cut = | ||
| rowCut && !readState.locallyForcedChannelIds.contains(channel.id); | ||
| for (final event in observedEvents.values) { | ||
| final readAt = observedUnreadEventReadAt( | ||
| event, | ||
| channel.id, | ||
| readState.effectiveTimestamp, | ||
| ); | ||
| if (readAt != null && event.createdAt <= readAt) continue; | ||
| if (cut && | ||
| rowSawObservedUnreadEvent( | ||
| event, | ||
| channel.id, | ||
| (key) => readState.contexts[key], | ||
| )) { | ||
| continue; | ||
| } | ||
| if (!separateAttention || channel.isDm || event.channelCatchUp) { | ||
| unread.add(channel.id); | ||
| } | ||
|
|
@@ -78,3 +93,60 @@ Set<String> computeUnreadChannelIds({ | |
|
|
||
| return (unread: unread, attention: attention); | ||
| } | ||
|
|
||
| /// The observed events [channelId]'s row and the app badge still show: the | ||
| /// unread ones its row has not seen, or all of them when the reader marked | ||
| /// the channel or one of its messages unread. | ||
| Map<String, ObservedUnreadEvent> rowObservedUnreadEvents( | ||
| Map<String, ObservedUnreadEvent> events, | ||
| String channelId, | ||
| ReadStateState readState, | ||
| ) { | ||
| if (readState.locallyForcedChannelIds.contains(channelId)) return events; | ||
| return { | ||
| for (final MapEntry(key: id, value: event) in events.entries) | ||
| if (!rowSawObservedUnreadEvent( | ||
| event, | ||
| channelId, | ||
| (key) => readState.contexts[key], | ||
| )) | ||
| id: event, | ||
| }; | ||
| } | ||
|
|
||
| /// The row hints that quiet [channelId]'s row through what it shows now, | ||
| /// without reading anything: a receipt for each attention message and the | ||
| /// newest shown time for ordinary ones. Empty when the row shows nothing | ||
| /// the saved hints do not already hide. | ||
| Map<String, int> channelRowSeenMarks({ | ||
| required String channelId, | ||
| required Map<String, ObservedUnreadEvent> events, | ||
| required ReadStateState readState, | ||
| }) { | ||
| final marks = <String, int>{}; | ||
| var newest = -1; | ||
| var ordinary = false; | ||
| for (final event in events.values) { | ||
| final readAt = observedUnreadEventReadAt( | ||
| event, | ||
| channelId, | ||
| readState.effectiveTimestamp, | ||
| ); | ||
| if (readAt != null && event.createdAt <= readAt) continue; | ||
| if (rowSawObservedUnreadEvent( | ||
| event, | ||
| channelId, | ||
| (key) => readState.contexts[key], | ||
| )) { | ||
| continue; | ||
| } | ||
| if (event.createdAt > newest) newest = event.createdAt; | ||
| if (event.channelCatchUp) { | ||
| ordinary = true; | ||
| } else { | ||
| marks[seenMessageContextKey(event.id)] = event.createdAt; | ||
|
Comment on lines
+146
to
+147
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For every attention event observed while a channel is open, this creates a unique AGENTS.md reference: AGENTS.md:L249-L256 Useful? React with 👍 / 👎.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P2] Prune expired row receipts from live state
Posted by Codex (gpt-6.1-sol) on behalf of kylez |
||
| } | ||
| } | ||
| if (ordinary) marks[seenContextKey(channelId)] = newest; | ||
| return marks; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the observed set contains an ordinary message plus a newer mention or reply,
newestadvances to the attention event's timestamp and that value is stored asseen:<channel>. If an ordinary event is subsequently delivered with a timestamp between those two values—such as after reconnect or from a sender with a slower clock—rowSawObservedUnreadEventtreats it as already seen, so the newly arrived activity never highlights the row. Update the channel frontier only while processingevent.channelCatchUp; attention events already have their per-message receipts.AGENTS.md reference: AGENTS.md:L266-L271
Useful? React with 👍 / 👎.