From fc8fe606133616e5927b33e4c6701d6144703f53 Mon Sep 17 00:00:00 2001 From: Krille Date: Sat, 25 Mar 2023 15:23:14 +0100 Subject: [PATCH] chore: Follow up jump to unread message --- lib/pages/chat/chat.dart | 62 ++++++++++++++++------------- lib/pages/chat/chat_event_list.dart | 3 +- lib/pages/chat/chat_view.dart | 4 +- lib/pages/chat/events/message.dart | 28 ++++++++++--- 4 files changed, 60 insertions(+), 37 deletions(-) diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 8d9c17ed..93177319 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -276,6 +276,8 @@ class ChatController extends State { _loadDraft(); super.initState(); sendingClient = Matrix.of(context).client; + readMarkerEventId = room.fullyRead; + loadTimelineFuture = _getTimeline(); } void updateView() { @@ -283,33 +285,34 @@ class ChatController extends State { setState(() {}); } - Future getTimeline([String? eventContextId]) async { - if (timeline == null) { - await Matrix.of(context).client.roomsLoading; - await Matrix.of(context).client.accountDataLoading; - timeline = await room.getTimeline( - onUpdate: updateView, - eventContextId: eventContextId, - ); - if (timeline!.events.isNotEmpty) { - if (room.markedUnread) room.markUnread(false); - setReadMarker(); - } + Future? loadTimelineFuture; - // when the scroll controller is attached we want to scroll to an event id, if specified - // and update the scroll controller...which will trigger a request history, if the - // "load more" button is visible on the screen - SchedulerBinding.instance.addPostFrameCallback((_) async { - if (mounted) { - final event = VRouter.of(context).queryParameters['event']; - if (event != null) { - scrollToEventId(event); - } - _updateScrollController(); - } - }); + Future _getTimeline([String? eventContextId]) async { + await Matrix.of(context).client.roomsLoading; + await Matrix.of(context).client.accountDataLoading; + final timeline = this.timeline = await room.getTimeline( + onUpdate: updateView, + eventContextId: eventContextId, + ); + if (timeline.events.isNotEmpty) { + if (room.markedUnread) room.markUnread(false); + setReadMarker(); } - timeline!.requestKeys(onlineKeyBackupOnly: false); + + // when the scroll controller is attached we want to scroll to an event id, if specified + // and update the scroll controller...which will trigger a request history, if the + // "load more" button is visible on the screen + SchedulerBinding.instance.addPostFrameCallback((_) async { + if (mounted) { + final event = VRouter.of(context).queryParameters['event']; + if (event != null) { + scrollToEventId(event); + } + _updateScrollController(); + } + }); + + timeline.requestKeys(onlineKeyBackupOnly: false); return; } @@ -317,7 +320,8 @@ class ChatController extends State { void setReadMarker({String? eventId}) { if (_setReadMarkerFuture != null) return; - if (lastReadEventVisible && + if (eventId == null && + lastReadEventVisible && !room.hasNewMessages && room.notificationCount == 0) { return; @@ -784,8 +788,9 @@ class ChatController extends State { if (eventIndex == -1) { setState(() { timeline = null; + loadTimelineFuture = _getTimeline(eventId); }); - await getTimeline(eventId); + await loadTimelineFuture; eventIndex = timeline!.events.indexWhere((e) => e.eventId == eventId); } if (!mounted) { @@ -802,8 +807,9 @@ class ChatController extends State { if (!timeline!.allowNewEvent) { setState(() { timeline = null; + loadTimelineFuture = _getTimeline(); }); - await getTimeline(); + await loadTimelineFuture; setReadMarker(eventId: timeline!.events.first.eventId); } scrollController.jumpTo(0); diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 71e5dfd2..6f5ad659 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -124,7 +124,8 @@ class ChatEventList extends StatelessWidget { .any((e) => e.eventId == event.eventId), timeline: controller.timeline!, displayReadMarker: - controller.readMarkerEventId == event.eventId, + controller.readMarkerEventId == event.eventId && + controller.timeline?.allowNewEvent == false, nextEvent: i < controller.timeline!.events.length ? controller.timeline!.events[i] : null, diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index 65c0bafd..d2ff66c2 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -139,8 +139,6 @@ class ChatView extends StatelessWidget { @override Widget build(BuildContext context) { - controller.readMarkerEventId ??= controller.room.fullyRead; - if (controller.room.membership == Membership.invite) { showFutureLoadingDialog( context: context, @@ -167,7 +165,7 @@ class ChatView extends StatelessWidget { stream: controller.room.onUpdate.stream .rateLimit(const Duration(seconds: 1)), builder: (context, snapshot) => FutureBuilder( - future: controller.getTimeline(), + future: controller.loadTimelineFuture, builder: (BuildContext context, snapshot) { return Scaffold( appBar: AppBar( diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 836e70a2..d3e2ef0e 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -354,12 +354,30 @@ class Message extends StatelessWidget { if (displayReadMarker) Row( children: [ - const Expanded(child: Divider()), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(L10n.of(context)!.readUpToHere), + Expanded( + child: Divider(color: Theme.of(context).colorScheme.primary), + ), + Container( + decoration: BoxDecoration( + border: Border.all( + color: Theme.of(context).colorScheme.primary, + ), + color: Theme.of(context).colorScheme.primaryContainer, + borderRadius: BorderRadius.circular(4), + ), + margin: const EdgeInsets.all(8.0), + padding: const EdgeInsets.symmetric( + horizontal: 8, + ), + child: Text( + L10n.of(context)!.readUpToHere, + style: + TextStyle(color: Theme.of(context).colorScheme.primary), + ), + ), + Expanded( + child: Divider(color: Theme.of(context).colorScheme.primary), ), - const Expanded(child: Divider()), ], ), ],