@@ -417,6 +417,9 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
417417 if (newStreamChannel != streamChannel) {
418418 streamChannel = newStreamChannel;
419419
420+ debouncedMarkRead.cancel ();
421+ debouncedMarkThreadRead.cancel ();
422+
420423 _messageNewListener? .cancel ();
421424 _userReadListener? .cancel ();
422425
@@ -467,8 +470,8 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
467470
468471 @override
469472 void dispose () {
470- debouncedMarkRead? .cancel ();
471- debouncedMarkThreadRead? .cancel ();
473+ debouncedMarkRead.cancel ();
474+ debouncedMarkThreadRead.cancel ();
472475 _messageNewListener? .cancel ();
473476 _userReadListener? .cancel ();
474477 _itemPositionListener.itemPositions
@@ -954,29 +957,23 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
954957 }
955958 }
956959
957- late final debouncedMarkRead = switch (streamChannel) {
958- final streamChannel? => debounce (
959- streamChannel.channel.markRead,
960- const Duration (seconds: 1 ),
961- ),
962- _ => null ,
963- };
960+ late final debouncedMarkRead = debounce (
961+ ([String ? id]) => streamChannel? .channel.markRead (messageId: id),
962+ const Duration (seconds: 1 ),
963+ );
964964
965- late final debouncedMarkThreadRead = switch (streamChannel) {
966- final streamChannel? => debounce (
967- streamChannel.channel.markThreadRead,
968- const Duration (seconds: 1 ),
969- ),
970- _ => null ,
971- };
965+ late final debouncedMarkThreadRead = debounce (
966+ (String parentId) => streamChannel? .channel.markThreadRead (parentId),
967+ const Duration (seconds: 1 ),
968+ );
972969
973970 Future <void > _markMessagesAsRead () async {
974- // Mark regular messages as read.
975- debouncedMarkRead? .call ();
976-
977- // Mark thread messages as read.
978971 if (widget.parentMessage case final parent? ) {
979- debouncedMarkThreadRead? .call ([parent.id]);
972+ // If we are in a thread, mark the thread as read.
973+ debouncedMarkThreadRead.call ([parent.id]);
974+ } else {
975+ // Otherwise, mark the channel as read.
976+ debouncedMarkRead.call ();
980977 }
981978 }
982979
@@ -1473,24 +1470,43 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
14731470 null => true , // Allows setting the initial value.
14741471 };
14751472
1476- // If the channel is upToDate and the last fully visible message has
1477- // been changed, we need to update the value and mark the messages as read.
1478- if (_upToDate && lastFullyVisibleMessageChanged) {
1473+ // If the last fully visible message has been changed, we need to update the
1474+ // value and maybe mark messages as read if needed .
1475+ if (lastFullyVisibleMessageChanged) {
14791476 _lastFullyVisibleMessage = newLastFullyVisibleMessage;
14801477
1481- if (streamChannel? .channel case final channel? ) {
1482- final hasUnread = (channel.state? .unreadCount ?? 0 ) > 0 ;
1483- final allowMarkRead = channel.config? .readEvents == true ;
1484- final canMarkReadAtBottom = widget.markReadWhenAtTheBottom;
1485-
1486- // Mark messages as read if it's allowed.
1487- if (hasUnread && allowMarkRead && canMarkReadAtBottom) {
1488- return _markMessagesAsRead ().ignore ();
1489- }
1478+ // Mark messages as read if needed.
1479+ if (widget.markReadWhenAtTheBottom) {
1480+ _maybeMarkMessagesAsRead ().ignore ();
14901481 }
14911482 }
14921483 }
14931484
1485+ // Marks messages as read if the conditions are met.
1486+ //
1487+ // The conditions are:
1488+ // 1. The channel is up to date or we are in a thread conversation.
1489+ // 2. There are unread messages or we are in a thread conversation.
1490+ //
1491+ // If any of the conditions are not met, the function returns early.
1492+ // Otherwise, it calls the _markMessagesAsRead function to mark the messages
1493+ // as read.
1494+ Future <void > _maybeMarkMessagesAsRead () async {
1495+ final channel = streamChannel? .channel;
1496+ if (channel == null ) return ;
1497+
1498+ final isInThread = widget.parentMessage != null ;
1499+
1500+ final isUpToDate = channel.state? .isUpToDate ?? false ;
1501+ if (! isInThread && ! isUpToDate) return ;
1502+
1503+ final hasUnread = (channel.state? .unreadCount ?? 0 ) > 0 ;
1504+ if (! isInThread && ! hasUnread) return ;
1505+
1506+ // Mark messages as read if it's allowed.
1507+ return _markMessagesAsRead ();
1508+ }
1509+
14941510 void _getOnThreadTap () {
14951511 if (widget.onThreadTap != null ) {
14961512 _onThreadTap = (Message message) {
0 commit comments