From fd0b0209575fe2749678389cf2e3a8f10b9b3edb Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Tue, 18 Nov 2025 17:54:58 -0500 Subject: [PATCH] wip read indicators --- lib/controllers/room_chat_controller.dart | 5 +++ lib/widgets/room_chat.dart | 22 ++++++-------- lib/widgets/sidebar.dart | 37 +++++++++++++++-------- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/lib/controllers/room_chat_controller.dart b/lib/controllers/room_chat_controller.dart index 1b73492..101b57e 100644 --- a/lib/controllers/room_chat_controller.dart +++ b/lib/controllers/room_chat_controller.dart @@ -62,6 +62,11 @@ class RoomChatController extends AsyncNotifier { ); } + Future markRead() async { + final controller = await future; + await room.setReadMarker(controller.messages.last.id); + } + Future updateMessage(Message message, Message newMessage) async => (await future).updateMessage(message, newMessage); diff --git a/lib/widgets/room_chat.dart b/lib/widgets/room_chat.dart index 0bffe27..357a6f6 100644 --- a/lib/widgets/room_chat.dart +++ b/lib/widgets/room_chat.dart @@ -62,6 +62,7 @@ class RoomChat extends HookConsumerWidget { final controllerProvider = RoomChatController.provider( room.roomData, ); + final notifier = ref.watch(controllerProvider.notifier); return Scaffold( appBar: RoomAppbar( room, @@ -112,9 +113,8 @@ class RoomChat extends HookConsumerWidget { chatAnimatedListBuilder: (_, itemBuilder) => ChatAnimatedList( itemBuilder: itemBuilder, - onEndReached: ref - .watch(controllerProvider.notifier) - .loadOlder, + onEndReached: notifier.loadOlder, + onStartReached: () => notifier.markRead(), ), composerBuilder: (_) => ChatBox( replyToMessage: replyToMessage.value, @@ -217,9 +217,8 @@ class RoomChat extends HookConsumerWidget { ), linkPreviewData: message.linkPreviewData, onLinkPreviewDataFetched: - (linkPreviewData) => ref - .watch(controllerProvider.notifier) - .updateMessage( + (linkPreviewData) => + notifier.updateMessage( message, message.copyWith( linkPreviewData: @@ -292,14 +291,13 @@ class RoomChat extends HookConsumerWidget { : SizedBox.shrink(), ), onMessageSend: (message) { - ref - .watch(controllerProvider.notifier) - .send(message, replyTo: replyToMessage.value); + notifier.send( + message, + replyTo: replyToMessage.value, + ); replyToMessage.value = null; }, - resolveUser: ref - .watch(controllerProvider.notifier) - .resolveUser, + resolveUser: notifier.resolveUser, chatController: controller, ), ), diff --git a/lib/widgets/sidebar.dart b/lib/widgets/sidebar.dart index 89d5d2f..7df0860 100644 --- a/lib/widgets/sidebar.dart +++ b/lib/widgets/sidebar.dart @@ -1,3 +1,4 @@ +import "package:collection/collection.dart"; import "package:flutter/material.dart"; import "package:flutter_hooks/flutter_hooks.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; @@ -72,11 +73,18 @@ class Sidebar extends HookConsumerWidget { return Scaffold( backgroundColor: Colors.transparent, appBar: AppBar( - leading: AvatarOrHash( - space.avatar, - fallback: space.icon, - space.title, - headers: space.client.headers, + leading: Badge( + isLabelVisible: + space.children.firstWhereOrNull( + (room) => room.roomData.isUnread, + ) != + null, + child: AvatarOrHash( + space.avatar, + fallback: space.icon, + space.title, + headers: space.client.headers, + ), ), title: Text( space.title, @@ -94,15 +102,18 @@ class Sidebar extends HookConsumerWidget { destinations: space.children .map( (room) => NavigationRailDestination( - icon: AvatarOrHash( - room.avatar, - room.title, - fallback: selectedSpace.value == 1 - ? null - : Icon(Icons.numbers), - headers: space.client.headers, - ), label: Text(room.title), + icon: Badge( + isLabelVisible: room.roomData.isUnread, + child: AvatarOrHash( + room.avatar, + room.title, + fallback: selectedSpace.value == 1 + ? null + : Icon(Icons.numbers), + headers: space.client.headers, + ), + ), ), ) .toList(),