forked from Nexus/nexus
Support for pinned messages (#49)
The first draft to support pinned messages. Fixes #39. Co-authored-by: Henry-Hiles <henry@henryhiles.com> Reviewed-on: Nexus/nexus#49
This commit is contained in:
parent
71a4274ff2
commit
818e582ddd
15 changed files with 570 additions and 279 deletions
|
|
@ -28,6 +28,7 @@ import "package:nexus/models/requests/report_request.dart";
|
|||
import "package:nexus/models/requests/send_event_request.dart";
|
||||
import "package:nexus/models/requests/send_message_request.dart";
|
||||
import "package:nexus/models/requests/set_membership_request.dart";
|
||||
import "package:nexus/models/requests/set_state_request.dart";
|
||||
import "package:nexus/models/room.dart";
|
||||
import "package:nexus/models/sync_data.dart";
|
||||
import "package:nexus/src/third_party/gomuks.g.dart";
|
||||
|
|
@ -159,7 +160,10 @@ class ClientController extends AsyncNotifier<int> {
|
|||
calloc.free(bufferPointer);
|
||||
|
||||
final json = response.buf.toJson();
|
||||
if (json is String) throw json;
|
||||
if (response.command.cast<Utf8>().toDartString() == "error") {
|
||||
throw json;
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
|
|
@ -169,8 +173,27 @@ class ClientController extends AsyncNotifier<int> {
|
|||
Future<Event> sendMessage(SendMessageRequest request) async =>
|
||||
Event.fromJson(await _sendCommand("send_message", request.toJson()));
|
||||
|
||||
Future<Event> sendEvent(SendEventRequest request) async =>
|
||||
Event.fromJson(await _sendCommand("send_event", request.toJson()));
|
||||
Future<Event> sendEvent(SendEventRequest request) async {
|
||||
final json = request.toJson();
|
||||
final content = request.content.toJson();
|
||||
|
||||
return Event.fromJson(
|
||||
await _sendCommand("send_event", {
|
||||
...json,
|
||||
"content": {
|
||||
...content,
|
||||
"m.relates_to": {
|
||||
...((content["m.relates_to"] as Map<String, dynamic>?) ?? {}),
|
||||
"event_id": request.relatesTo,
|
||||
"rel_type": request.relationType,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Future<String?> setState(SetStateRequest request) async =>
|
||||
await _sendCommand("set_state", request.toJson());
|
||||
|
||||
Future<String?> verify(String recoveryKey) async {
|
||||
try {
|
||||
|
|
|
|||
30
lib/controllers/pinned_events_controller.dart
Normal file
30
lib/controllers/pinned_events_controller.dart
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:nexus/controllers/event_controller.dart";
|
||||
import "package:nexus/controllers/pinned_ids_controller.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
|
||||
class PinnedEventsController extends AsyncNotifier<IList<Event>> {
|
||||
final String roomId;
|
||||
PinnedEventsController(this.roomId);
|
||||
|
||||
@override
|
||||
Future<IList<Event>> build() async {
|
||||
final pinIds = ref.watch(PinnedIdsController.provider(roomId));
|
||||
|
||||
return (await Future.wait(
|
||||
pinIds.map(
|
||||
(eventId) => ref.watch(
|
||||
EventController.provider(
|
||||
.new(eventId: eventId, roomId: roomId),
|
||||
).future,
|
||||
),
|
||||
),
|
||||
)).nonNulls.toIList();
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider.family
|
||||
.autoDispose<PinnedEventsController, IList<Event>, String>(
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
|
@ -205,15 +205,11 @@ class RoomChatController extends AsyncNotifier<IList<Event>?> {
|
|||
.new(
|
||||
roomId: roomId,
|
||||
type: EventType.reaction.type,
|
||||
content: {
|
||||
"m.relates_to": {
|
||||
"event_id": event.eventId,
|
||||
"rel_type": "m.annotation",
|
||||
"key": reaction,
|
||||
},
|
||||
},
|
||||
content: ReactionContent(key: reaction),
|
||||
synchronous: true,
|
||||
disableEncryption: true,
|
||||
relatesTo: event.eventId,
|
||||
relationType: "m.annotation",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue