Skip to content

Commit

Permalink
Improve scrollToIndex and highlightToIndex
Browse files Browse the repository at this point in the history
  • Loading branch information
nqhhdev authored and hoangdat committed Dec 12, 2023
1 parent a99c52b commit 0590cee
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 35 deletions.
48 changes: 20 additions & 28 deletions lib/pages/chat/chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ class ChatController extends State<Chat>
widget.jumpToEventIdStream?.stream.listen(scrollToEventIdAndHighlight);
inputFocus.addListener(_inputFocusListener);
_loadDraft();
_tryLoadTimeline();
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) async {
if (room == null) {
Expand All @@ -325,6 +326,24 @@ class ChatController extends State<Chat>
});
}

void _tryLoadTimeline() async {
loadTimelineFuture = _getTimeline();
try {
await loadTimelineFuture;
final fullyRead = room?.fullyRead;
if (fullyRead == null || fullyRead == '') return;
if (timeline!.events.any((event) => event.eventId == fullyRead)) {
Logs().v('Scroll up to visible event', fullyRead);
setReadMarker();
return;
}
if (!mounted) return;
} catch (e, s) {
Logs().e('Unable to load timeline', e, s);
rethrow;
}
}

void updateView() {
if (!mounted) return;
setState(() {});
Expand All @@ -334,33 +353,6 @@ class ChatController extends State<Chat>
context.pop();
}

Future<bool> getTimeline() async {
if (timeline == null) {
await Matrix.of(context).client.roomsLoading;
await Matrix.of(context).client.accountDataLoading;
timeline = await room!.getTimeline(onUpdate: updateView);
if (timeline!.events.isNotEmpty) {
if (room!.markedUnread) room!.markUnread(false);
setReadMarker();
}

// 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 = GoRouterState.of(context).pathParameters['event'];
if (event != null) {
scrollToEventId(event);
}
_updateScrollController();
}
});
}
timeline!.requestKeys(onlineKeyBackupOnly: false);
return true;
}

Future<void>? _setReadMarkerFuture;

void setReadMarker([_]) {
Expand Down Expand Up @@ -892,7 +884,7 @@ class ChatController extends State<Chat>
);
await loadTimelineFuture;
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
scrollToEventId(eventId);
scrollToEventId(eventId, highlight: highlight);
});
setState(() {});
return;
Expand Down
4 changes: 1 addition & 3 deletions lib/pages/chat/chat_event_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ class ChatEventList extends StatelessWidget {
Widget build(BuildContext context) {
final horizontalPadding = TwakeThemes.isColumnMode(context) ? 8.0 : 0.0;

final events = controller.timeline!.events
.where((event) => event.isVisibleInGui)
.toList();
final events = controller.timeline!.events;
// create a map of eventId --> index to greatly improve performance of
// ListView's findChildIndexCallback
final thisEventsKeyMap = <String, int>{};
Expand Down
6 changes: 4 additions & 2 deletions lib/pages/chat/chat_pinned_events/pinned_events_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ class PinnedEventsView extends StatelessWidget {
onTap: () => controller.pinnedEventsController
.jumpToPinnedMessageAction(
data.pinnedEvents,
scrollToEventId: (eventId) =>
controller.scrollToEventId(eventId),
scrollToEventId: (eventId) => controller.scrollToEventId(
eventId,
highlight: true,
),
),
child: Container(
margin: PinnedEventsStyle.marginPinnedEventsWidget,
Expand Down
4 changes: 2 additions & 2 deletions lib/pages/chat/chat_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ class ChatView extends StatelessWidget with MessageContentMixin {
child: StreamBuilder(
stream: controller.room!.onUpdate.stream
.rateLimit(const Duration(seconds: 1)),
builder: (context, snapshot) => FutureBuilder<bool>(
future: controller.getTimeline(),
builder: (context, snapshot) => FutureBuilder(
future: controller.loadTimelineFuture,
builder: (BuildContext context, snapshot) {
return Scaffold(
backgroundColor: LinagoraSysColors.material().onPrimary,
Expand Down

0 comments on commit 0590cee

Please sign in to comment.