diff --git a/lib/controllers/pinned_events_controller.dart b/lib/controllers/room_pins_controller.dart similarity index 57% rename from lib/controllers/pinned_events_controller.dart rename to lib/controllers/room_pins_controller.dart index 54d6196..7925d05 100644 --- a/lib/controllers/pinned_events_controller.dart +++ b/lib/controllers/room_pins_controller.dart @@ -1,15 +1,15 @@ +import "package:collection/collection.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:nexus/controllers/client_controller.dart"; -import "package:nexus/controllers/event_controller.dart"; import "package:nexus/controllers/rooms_controller.dart"; import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/pinned_events.dart"; import "package:nexus/models/event.dart"; -class PinnedEventsController extends AsyncNotifier> { +class RoomPinsController extends AsyncNotifier> { final String roomId; - PinnedEventsController(this.roomId); + RoomPinsController(this.roomId); @override Future> build() async { @@ -26,19 +26,42 @@ class PinnedEventsController extends AsyncNotifier> { if (pinnedStateEvent == null) return .new(); - if (pinnedStateEvent.content case PinnedEventsContent content) { - return (await Future.wait( - content.pinnedEvents.map( - (eventId) => ref.watch( - EventController.provider( - .new(eventId: eventId, roomId: roomId), - ).future, - ), - ), - )).nonNulls.toIList(); + final pinnedContent = switch (pinnedStateEvent.content) { + PinnedEventsContent content => content, + _ => null, + }; + + if (pinnedContent == null || pinnedContent.pinned.isEmpty) { + return .new(); } - return .new(); + final localEvents = []; + final missingIds = []; + + for (final eventId in pinnedContent.pinned) { + final localEvent = room.events.values.firstWhereOrNull( + (e) => e.eventId == eventId, + ); + + if (localEvent != null) { + localEvents.add(localEvent); + } else { + missingIds.add(eventId); + } + } + + if (missingIds.isNotEmpty) { + final client = ref.read(ClientController.provider.notifier); + final fetched = await Future.wait( + missingIds.map( + (id) => client.getEvent(.new(roomId: roomId, eventId: id)), + ), + ); + + localEvents.addAll(fetched.whereType()); + } + + return localEvents.toIList(); } Future togglePin(Event event) async { @@ -63,7 +86,7 @@ class PinnedEventsController extends AsyncNotifier> { } static final provider = AsyncNotifierProvider.family - .autoDispose, String>( - PinnedEventsController.new, + .autoDispose, String>( + RoomPinsController.new, ); } diff --git a/lib/models/content/pinned_events.dart b/lib/models/content/pinned_events.dart index 8aea838..d17a0de 100644 --- a/lib/models/content/pinned_events.dart +++ b/lib/models/content/pinned_events.dart @@ -7,9 +7,8 @@ part "pinned_events.g.dart"; @freezed abstract class PinnedEventsContent extends Content with _$PinnedEventsContent { PinnedEventsContent._(); - factory PinnedEventsContent({ - @Default(IList.empty()) @JsonKey(name: "pinned") IList pinnedEvents, - }) = _PinnedEventsContent; + factory PinnedEventsContent({@Default(IList.empty()) IList pinned}) = + _PinnedEventsContent; factory PinnedEventsContent.fromJson(Map json) => _$PinnedEventsContentFromJson(json); diff --git a/lib/widgets/pinned_events_drawer.dart b/lib/widgets/pinned_messages.dart similarity index 93% rename from lib/widgets/pinned_events_drawer.dart rename to lib/widgets/pinned_messages.dart index e018ce8..5c6bce7 100644 --- a/lib/widgets/pinned_events_drawer.dart +++ b/lib/widgets/pinned_messages.dart @@ -1,19 +1,19 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter/material.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; -import "package:nexus/controllers/pinned_events_controller.dart"; +import "package:nexus/controllers/room_pins_controller.dart"; import "package:nexus/models/event.dart"; import "package:nexus/widgets/loading.dart"; import "package:nexus/widgets/renderers/event.dart"; -class PinnedEventsDrawer extends HookConsumerWidget { +class PinnedMessages extends HookConsumerWidget { final String roomId; final IList Function(Event event)? getEventOptions; - const PinnedEventsDrawer(this.roomId, {this.getEventOptions, super.key}); + const PinnedMessages(this.roomId, {this.getEventOptions, super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final pinsAsync = ref.watch(PinnedEventsController.provider(roomId)); + final pinsAsync = ref.watch(RoomPinsController.provider(roomId)); final theme = Theme.of(context); return Column( diff --git a/lib/widgets/room_chat.dart b/lib/widgets/room_chat.dart index 6c1715b..99d3b10 100644 --- a/lib/widgets/room_chat.dart +++ b/lib/widgets/room_chat.dart @@ -17,7 +17,7 @@ import "package:nexus/models/event.dart"; import "package:nexus/models/relation_type.dart"; import "package:nexus/widgets/composer/composer.dart"; import "package:nexus/widgets/emoji_picker_button.dart"; -import "package:nexus/widgets/pinned_events_drawer.dart"; +import "package:nexus/widgets/pinned_messages.dart"; import "package:nexus/widgets/renderers/event.dart"; import "package:nexus/widgets/member_list.dart"; import "package:nexus/widgets/room_appbar.dart"; @@ -524,10 +524,7 @@ class RoomChat extends HookConsumerWidget { shape: Border(), child: memberListOpened.value ? MemberList(roomId) - : PinnedEventsDrawer( - roomId, - getEventOptions: getEventOptions, - ), + : PinnedMessages(roomId, getEventOptions: getEventOptions), ), ); }