diff --git a/lib/controllers/pinned_events_controller.dart b/lib/controllers/pinned_events_controller.dart index aaaebe6..402dc30 100644 --- a/lib/controllers/pinned_events_controller.dart +++ b/lib/controllers/pinned_events_controller.dart @@ -1,10 +1,7 @@ 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/controllers/pinned_ids_controller.dart"; import "package:nexus/models/event.dart"; class PinnedEventsController extends AsyncNotifier> { @@ -13,75 +10,19 @@ class PinnedEventsController extends AsyncNotifier> { @override Future> build() async { - final room = ref.watch( - RoomsController.provider.select((rooms) => rooms[roomId]), - ); + final pinIds = ref.watch(PinnedIdsController.provider(roomId)); - if (room == null) return .new(); - - final pinnedRowId = room.state[EventType.pinnedEvents.type]?[""]; - final pinnedStateEvent = pinnedRowId == null - ? null - : room.events[pinnedRowId]; - - 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(); - } - - return .new(); - } - - Future addPin(Event event) async { - final current = await future; - - return setPinned( - .new( - pinnedEvents: .new( - current - .map((element) => element.eventId) - .toIList() - .add(event.eventId), + return (await Future.wait( + pinIds.map( + (eventId) => ref.watch( + EventController.provider( + .new(eventId: eventId, roomId: roomId), + ).future, ), ), - ); + )).nonNulls.toIList(); } - Future removePin(Event event) async { - final current = await future; - - return setPinned( - .new( - pinnedEvents: .new( - current - .map((element) => element.eventId) - .toIList() - .remove(event.eventId), - ), - ), - ); - } - - Future setPinned(PinnedEventsContent content) => ref - .read(ClientController.provider.notifier) - .setState( - .new( - roomId: roomId, - type: EventType.pinnedEvents.type, - stateKey: "", - content: content, - ), - ); - static final provider = AsyncNotifierProvider.family .autoDispose, String>( PinnedEventsController.new, diff --git a/lib/controllers/pinned_ids_controller.dart b/lib/controllers/pinned_ids_controller.dart new file mode 100644 index 0000000..4ec5af0 --- /dev/null +++ b/lib/controllers/pinned_ids_controller.dart @@ -0,0 +1,53 @@ +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/rooms_controller.dart"; +import "package:nexus/models/content/content.dart"; +import "package:nexus/models/content/pinned_events.dart"; + +class PinnedIdsController extends Notifier> { + final String roomId; + PinnedIdsController(this.roomId); + + @override + IList build() { + final room = ref.watch( + RoomsController.provider.select((rooms) => rooms[roomId]), + ); + + if (room == null) return .new(); + + final pinnedRowId = room.state[EventType.pinnedEvents.type]?[""]; + final pinnedStateEvent = pinnedRowId == null + ? null + : room.events[pinnedRowId]; + + if (pinnedStateEvent?.content case PinnedEventsContent content) { + return content.pinnedEvents; + } + + return .new(); + } + + Future addPin(String eventId) async => + setPinned(.new(pinnedEvents: .new(state.add(eventId)))); + + Future removePin(String eventId) async => + setPinned(.new(pinnedEvents: .new(state.remove(eventId)))); + + Future setPinned(PinnedEventsContent content) => ref + .read(ClientController.provider.notifier) + .setState( + .new( + roomId: roomId, + type: EventType.pinnedEvents.type, + stateKey: "", + content: content, + ), + ); + + static final provider = NotifierProvider.family + .autoDispose, String>( + PinnedIdsController.new, + ); +} diff --git a/lib/widgets/room_chat.dart b/lib/widgets/room_chat.dart index 4a1c096..c0c76b4 100644 --- a/lib/widgets/room_chat.dart +++ b/lib/widgets/room_chat.dart @@ -7,7 +7,7 @@ import "package:measure_size/measure_size.dart"; import "package:nexus/controllers/account_data_controller.dart"; import "package:nexus/controllers/client_controller.dart"; import "package:nexus/controllers/client_state_controller.dart"; -import "package:nexus/controllers/pinned_events_controller.dart"; +import "package:nexus/controllers/pinned_ids_controller.dart"; import "package:nexus/controllers/power_level_controller.dart"; import "package:nexus/controllers/rooms_controller.dart"; import "package:nexus/controllers/room_chat_controller.dart"; @@ -178,13 +178,6 @@ class RoomChat extends HookConsumerWidget { final danger = theme.colorScheme.error; final isSentByMe = event.sender == userId; - final isPinned = ref - .watch(PinnedEventsController.provider(roomId)) - .whenOrNull( - data: (pinnedEvents) => - pinnedEvents.any((ev) => ev.eventId == event.eventId), - ); - return [ if (ref.watch( PowerLevelController.provider( @@ -262,29 +255,30 @@ class RoomChat extends HookConsumerWidget { .state(eventType: .pinnedEvents, roomId: roomId), ), )) - PopupMenuItem( - enabled: isPinned != null, - onTap: isPinned == null - ? null - : () async { - try { - final notifier = ref.read( - PinnedEventsController.provider(roomId).notifier, - ); - if (isPinned) { - await notifier.removePin(event); - } else { - await notifier.addPin(event); - } - } catch (error, stackTrace) { - showError(error, stackTrace); - } - }, - child: ListTile( - leading: Icon(Icons.push_pin), - title: Text(isPinned == true ? "Unpin Event" : "Pin Event"), + switch (ref + .watch(PinnedIdsController.provider(roomId)) + .contains(event.eventId)) { + bool isPinned => PopupMenuItem( + onTap: () async { + try { + final notifier = ref.read( + PinnedIdsController.provider(roomId).notifier, + ); + if (isPinned) { + await notifier.removePin(event.eventId); + } else { + await notifier.addPin(event.eventId); + } + } catch (error, stackTrace) { + showError(error, stackTrace); + } + }, + child: ListTile( + leading: Icon(Icons.push_pin), + title: Text(isPinned == true ? "Unpin Event" : "Pin Event"), + ), ), - ), + }, PopupMenuItem( onTap: () async { final room = ref.watch(