Support for pinned messages #49
3 changed files with 87 additions and 99 deletions
create a seperate PinnedIdsController from PinnedEventsController
commit
624a3f3861
|
|
@ -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,75 +10,19 @@ 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();
|
return (await Future.wait(
|
||||||
|
pinIds.map(
|
||||||
final pinnedRowId = room.state[EventType.pinnedEvents.type]?[""];
|
(eventId) => ref.watch(
|
||||||
final pinnedStateEvent = pinnedRowId == null
|
EventController.provider(
|
||||||
? null
|
.new(eventId: eventId, roomId: roomId),
|
||||||
: room.events[pinnedRowId];
|
).future,
|
||||||
|
|
||||||
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<void> addPin(Event event) async {
|
|
||||||
final current = await future;
|
|
||||||
|
|
||||||
return setPinned(
|
|
||||||
.new(
|
|
||||||
pinnedEvents: .new(
|
|
||||||
current
|
|
||||||
.map((element) => element.eventId)
|
|
||||||
.toIList()
|
|
||||||
.add(event.eventId),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
)).nonNulls.toIList();
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
|
|
||||||
53
lib/controllers/pinned_ids_controller.dart
Normal file
53
lib/controllers/pinned_ids_controller.dart
Normal 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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,29 +255,30 @@ 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);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: Icon(Icons.push_pin),
|
leading: Icon(Icons.push_pin),
|
||||||
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(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue