create a seperate PinnedIdsController from PinnedEventsController

This commit is contained in:
Henry Hiles 2026-07-14 22:46:41 +00:00
commit 624a3f3861
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
3 changed files with 87 additions and 99 deletions

View file

@ -1,10 +1,7 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:hooks_riverpod/hooks_riverpod.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/event_controller.dart";
import "package:nexus/controllers/rooms_controller.dart"; import "package:nexus/controllers/pinned_ids_controller.dart";
import "package:nexus/models/content/content.dart";
import "package:nexus/models/content/pinned_events.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
class PinnedEventsController extends AsyncNotifier<IList<Event>> { class PinnedEventsController extends AsyncNotifier<IList<Event>> {
@ -13,22 +10,10 @@ class PinnedEventsController extends AsyncNotifier<IList<Event>> {
@override @override
Future<IList<Event>> build() async { Future<IList<Event>> build() async {
final room = ref.watch( final pinIds = ref.watch(PinnedIdsController.provider(roomId));
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 == null) return .new();
if (pinnedStateEvent.content case PinnedEventsContent content) {
return (await Future.wait( return (await Future.wait(
content.pinnedEvents.map( pinIds.map(
(eventId) => ref.watch( (eventId) => ref.watch(
EventController.provider( EventController.provider(
.new(eventId: eventId, roomId: roomId), .new(eventId: eventId, roomId: roomId),
@ -38,50 +23,6 @@ class PinnedEventsController extends AsyncNotifier<IList<Event>> {
)).nonNulls.toIList(); )).nonNulls.toIList();
} }
return .new();
}
Future<void> addPin(Event event) async {
final current = await future;
return setPinned(
.new(
pinnedEvents: .new(
current
.map((element) => element.eventId)
.toIList()
.add(event.eventId),
),
),
);
}
Future<void> removePin(Event event) async {
final current = await future;
return setPinned(
.new(
pinnedEvents: .new(
current
.map((element) => element.eventId)
.toIList()
.remove(event.eventId),
),
),
);
}
Future<void> setPinned(PinnedEventsContent content) => ref
.read(ClientController.provider.notifier)
.setState(
.new(
roomId: roomId,
type: EventType.pinnedEvents.type,
stateKey: "",
content: content,
),
);
static final provider = AsyncNotifierProvider.family static final provider = AsyncNotifierProvider.family
.autoDispose<PinnedEventsController, IList<Event>, String>( .autoDispose<PinnedEventsController, IList<Event>, String>(
PinnedEventsController.new, PinnedEventsController.new,

View file

@ -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<IList<String>> {
final String roomId;
PinnedIdsController(this.roomId);
@override
IList<String> 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<void> addPin(String eventId) async =>
setPinned(.new(pinnedEvents: .new(state.add(eventId))));
Future<void> removePin(String eventId) async =>
setPinned(.new(pinnedEvents: .new(state.remove(eventId))));
Future<void> 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<PinnedIdsController, IList<String>, String>(
PinnedIdsController.new,
);
}

View file

@ -7,7 +7,7 @@ import "package:measure_size/measure_size.dart";
import "package:nexus/controllers/account_data_controller.dart"; import "package:nexus/controllers/account_data_controller.dart";
import "package:nexus/controllers/client_controller.dart"; import "package:nexus/controllers/client_controller.dart";
import "package:nexus/controllers/client_state_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/power_level_controller.dart";
import "package:nexus/controllers/rooms_controller.dart"; import "package:nexus/controllers/rooms_controller.dart";
import "package:nexus/controllers/room_chat_controller.dart"; import "package:nexus/controllers/room_chat_controller.dart";
@ -178,13 +178,6 @@ class RoomChat extends HookConsumerWidget {
final danger = theme.colorScheme.error; final danger = theme.colorScheme.error;
final isSentByMe = event.sender == userId; final isSentByMe = event.sender == userId;
final isPinned = ref
.watch(PinnedEventsController.provider(roomId))
.whenOrNull(
data: (pinnedEvents) =>
pinnedEvents.any((ev) => ev.eventId == event.eventId),
);
return [ return [
if (ref.watch( if (ref.watch(
PowerLevelController.provider( PowerLevelController.provider(
@ -262,19 +255,19 @@ class RoomChat extends HookConsumerWidget {
.state(eventType: .pinnedEvents, roomId: roomId), .state(eventType: .pinnedEvents, roomId: roomId),
), ),
)) ))
PopupMenuItem( switch (ref
enabled: isPinned != null, .watch(PinnedIdsController.provider(roomId))
onTap: isPinned == null .contains(event.eventId)) {
? null bool isPinned => PopupMenuItem(
: () async { onTap: () async {
try { try {
final notifier = ref.read( final notifier = ref.read(
PinnedEventsController.provider(roomId).notifier, PinnedIdsController.provider(roomId).notifier,
); );
if (isPinned) { if (isPinned) {
await notifier.removePin(event); await notifier.removePin(event.eventId);
} else { } else {
await notifier.addPin(event); await notifier.addPin(event.eventId);
} }
} catch (error, stackTrace) { } catch (error, stackTrace) {
showError(error, stackTrace); showError(error, stackTrace);
@ -285,6 +278,7 @@ class RoomChat extends HookConsumerWidget {
title: Text(isPinned == true ? "Unpin Event" : "Pin Event"), title: Text(isPinned == true ? "Unpin Event" : "Pin Event"),
), ),
), ),
},
PopupMenuItem( PopupMenuItem(
onTap: () async { onTap: () async {
final room = ref.watch( final room = ref.watch(