diff --git a/README.md b/README.md index 73f00de..702fd89 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ A simple and user-friendly Matrix client made with Flutter and a Gomuks backend. - [x] Member list - [ ] Colors based off of power level - [ ] Sort by power level -- [ ] Notifications using UnifiedPush ([#35](https://git.federated.nexus/Nexus/nexus/issues/35)) +- [ ] Notifications using UnifiedPush - [ ] Group calls using [MSC4195](https://github.com/matrix-org/matrix-spec-proposals/pull/4195) - [ ] Invites - [ ] Settings diff --git a/lib/controllers/emoji_controller.dart b/lib/controllers/emoji_controller.dart index caea3de..7d00ac6 100644 --- a/lib/controllers/emoji_controller.dart +++ b/lib/controllers/emoji_controller.dart @@ -78,7 +78,8 @@ class EmojiController extends AsyncNotifier { return (customCategories, customKeywords); } - static final provider = AsyncNotifierProvider( - EmojiController.new, - ); + static final provider = + AsyncNotifierProvider.autoDispose( + EmojiController.new, + ); } diff --git a/lib/controllers/room_chat_controller.dart b/lib/controllers/room_chat_controller.dart index 84ac7b0..03caa04 100644 --- a/lib/controllers/room_chat_controller.dart +++ b/lib/controllers/room_chat_controller.dart @@ -38,13 +38,16 @@ class RoomChatController extends AsyncNotifier> { loadOlder(); } - return room.timeline - .toEntryIList(compare: (a, b) => (a?.key ?? 0).compareTo(b?.key ?? 0)) - .map((element) => element.value) - .toIList() - .addAll(room.sticky) + return IMap.fromValues( + keyMapper: (id) => 9999999999 + (id ?? 0), + values: room.sticky, + ) + .addAll(room.timeline) + .toEntryIList(compare: (a, b) => (b?.key ?? 0).compareTo(a?.key ?? 0)) .map((entry) { - final foundEvent = entry == null ? null : room.events[entry]; + final foundEvent = entry.value == null + ? null + : room.events[entry.value!]; final editedEvent = foundEvent == null || foundEvent.lastEditRowId == 0 diff --git a/lib/pages/chat_page.dart b/lib/pages/chat_page.dart index 2c0ef97..d90d3d4 100644 --- a/lib/pages/chat_page.dart +++ b/lib/pages/chat_page.dart @@ -1,6 +1,5 @@ import "package:flutter/material.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; -import "package:nexus/controllers/emoji_controller.dart"; import "package:nexus/controllers/init_complete_controller.dart"; import "package:nexus/controllers/key_controller.dart"; import "package:nexus/widgets/appbar.dart"; @@ -18,7 +17,6 @@ class ChatPage extends ConsumerWidget { final showMembersByDefault = constraints.maxWidth > 1000; final initComplete = ref.watch(InitCompleteController.provider); final roomId = ref.watch(KeyController.provider(KeyController.roomKey)); - ref.read(EmojiController.provider); return Scaffold( appBar: initComplete ? null : Appbar(), diff --git a/lib/widgets/room_chat.dart b/lib/widgets/room_chat.dart index 9e3d281..95e7514 100644 --- a/lib/widgets/room_chat.dart +++ b/lib/widgets/room_chat.dart @@ -77,73 +77,10 @@ class RoomChat extends HookConsumerWidget { final listController = useRef(ListController()); final scrollController = useScrollController(); - final controllerData = ref.watch(controllerProvider); - - final topEventBeforeLoad = useState(null); - - Future loadOlder() async { - if (controllerData case AsyncData(:final value)) { - topEventBeforeLoad.value = value.firstOrNull?.eventId; - await notifier.loadOlder(); - } - } - - useEffect(() { - ref - .read(controllerProvider.future) - .then( - (_) => WidgetsBinding.instance.addPostFrameCallback((_) { - if (scrollController.hasClients) { - scrollController.jumpTo( - scrollController.position.maxScrollExtent - .000001, - ); - } - }), - ); - - return null; - }, [scrollController.hasClients]); - - useEffect(() { - if (controllerData case AsyncData( - :final value, - ) when scrollController.hasClients) { - if (topEventBeforeLoad.value != null) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (scrollController.hasClients) { - final index = value.indexWhere( - (event) => event.eventId == topEventBeforeLoad.value, - ); - if (index != -1) { - listController.value.jumpToItem( - index: index, - scrollController: scrollController, - alignment: 0, - ); - } - } - topEventBeforeLoad.value = null; - }); - } else if (scrollController.position.atEdge && - scrollController.position.pixels != 0) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (scrollController.hasClients) { - scrollController.jumpTo( - scrollController.position.maxScrollExtent, - ); - } - }); - } - } - - return null; - }, [controllerData]); useEffect(() { Future listener() async { - if (!scrollController.hasClients || !scrollController.position.atEdge) { - return; - } + if (!scrollController.position.atEdge) return; final room = ref.watch( RoomsController.provider.select((value) => value[roomId]), @@ -151,17 +88,15 @@ class RoomChat extends HookConsumerWidget { if (room == null) return; if (scrollController.position.pixels == 0) { - if (room.hasMore) { - await loadOlder(); - } - } else { await client.markRead(room); + } else { + if (room.hasMore) await notifier.loadOlder(); } } scrollController.addListener(listener); return () => scrollController.removeListener(listener); - }, [roomId, controllerData]); + }, [roomId]); final composerNode = useFocusNode( onKeyEvent: (_, event) { @@ -381,6 +316,8 @@ class RoomChat extends HookConsumerWidget { ].toIList(); } + final controllerData = ref.watch(controllerProvider); + return Scaffold( appBar: RoomAppbar( roomId: roomId, @@ -402,20 +339,11 @@ class RoomChat extends HookConsumerWidget { child: switch (controllerData) { AsyncData(:final value) || AsyncLoading(:final value?) => CustomScrollView( + reverse: true, controller: scrollController, slivers: [ - SliverToBoxAdapter( - child: Padding( - padding: .symmetric(vertical: 36), - child: Center( - child: ElevatedButton( - onPressed: controllerData is AsyncData - ? loadOlder - : null, - child: Text("Load More"), - ), - ), - ), + SliverPadding( + padding: .only(bottom: composerSize.value), ), SuperSliverList.builder( @@ -423,7 +351,7 @@ class RoomChat extends HookConsumerWidget { itemCount: value.length, itemBuilder: (_, index) { final event = value[index]; - final previousEvent = value.getOrNull(index - 1); + final previousEvent = value.getOrNull(index + 1); return FlashWrapper( EventRenderer( event, @@ -461,8 +389,18 @@ class RoomChat extends HookConsumerWidget { }, ), - SliverPadding( - padding: .only(bottom: composerSize.value), + SliverToBoxAdapter( + child: Padding( + padding: .symmetric(vertical: 36), + child: Center( + child: controllerData is AsyncLoading + ? Loading() + : ElevatedButton( + onPressed: notifier.loadOlder, + child: Text("Load More"), + ), + ), + ), ), ], ),