add GomuksEvent model
This commit is contained in:
parent
b4d5a632dd
commit
b154b4ee2e
8 changed files with 114 additions and 93 deletions
|
|
@ -8,6 +8,7 @@ import "package:nexus/controllers/client.dart";
|
||||||
import "package:nexus/models/account_data.dart";
|
import "package:nexus/models/account_data.dart";
|
||||||
import "package:nexus/models/push_rules.dart";
|
import "package:nexus/models/push_rules.dart";
|
||||||
import "package:nexus/models/requests/update_push_rule.dart";
|
import "package:nexus/models/requests/update_push_rule.dart";
|
||||||
|
import "package:nexus/models/sync_data.dart";
|
||||||
|
|
||||||
class AccountDataController extends Notifier<AccountData> {
|
class AccountDataController extends Notifier<AccountData> {
|
||||||
@override
|
@override
|
||||||
|
|
@ -26,6 +27,11 @@ class AccountDataController extends Notifier<AccountData> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
void handleSync(SyncData sync) {
|
||||||
|
if (sync.clearState) state = .new();
|
||||||
|
update(sync.accountData);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> setEnabledImagePacks(ImagePackRooms packs) {
|
Future<void> setEnabledImagePacks(ImagePackRooms packs) {
|
||||||
ISet<(String, String)> keysOf(ImagePackRooms rooms) => rooms.rooms.entries
|
ISet<(String, String)> keysOf(ImagePackRooms rooms) => rooms.rooms.entries
|
||||||
.expand((entry) => entry.value.keys.map((key) => (entry.key, key)))
|
.expand((entry) => entry.value.keys.map((key) => (entry.key, key)))
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import "dart:io";
|
||||||
import "dart:isolate";
|
import "dart:isolate";
|
||||||
|
|
||||||
import "package:collection/collection.dart";
|
import "package:collection/collection.dart";
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
|
||||||
import "package:flutter/foundation.dart";
|
import "package:flutter/foundation.dart";
|
||||||
import "package:nexus/controllers/account_data.dart";
|
import "package:nexus/controllers/account_data.dart";
|
||||||
import "package:nexus/controllers/accounts.dart";
|
import "package:nexus/controllers/accounts.dart";
|
||||||
|
|
@ -22,9 +21,7 @@ import "package:nexus/controllers/typing.dart";
|
||||||
import "package:nexus/helpers/extensions/gomuks_buffer.dart";
|
import "package:nexus/helpers/extensions/gomuks_buffer.dart";
|
||||||
import "package:nexus/main.dart";
|
import "package:nexus/main.dart";
|
||||||
import "package:ffi/ffi.dart";
|
import "package:ffi/ffi.dart";
|
||||||
import "package:nexus/models/event.dart";
|
import "package:nexus/models/gomuks_event.dart";
|
||||||
import "package:nexus/models/events_decrypted.dart";
|
|
||||||
import "package:nexus/models/sync_data.dart";
|
|
||||||
import "package:nexus/src/third_party/gomuks.g.dart";
|
import "package:nexus/src/third_party/gomuks.g.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
|
|
||||||
|
|
@ -42,100 +39,43 @@ class GomuksListenerController extends AsyncNotifier<void> {
|
||||||
int requestId,
|
int requestId,
|
||||||
GomuksOwnedBuffer data,
|
GomuksOwnedBuffer data,
|
||||||
) {
|
) {
|
||||||
|
final type = command.cast<Utf8>().toDartString();
|
||||||
try {
|
try {
|
||||||
final muksEventType = command.cast<Utf8>().toDartString();
|
debugPrint("Handling $type...");
|
||||||
debugPrint("Handling $muksEventType...");
|
switch (GomuksEvent.parse(type, data.toJsonAndFree())) {
|
||||||
final decodedMuksEvent = data.toJsonAndFree();
|
case ClientStateEvent(:final state):
|
||||||
|
ref.read(ClientStateController.provider.notifier).set(state);
|
||||||
switch (muksEventType) {
|
case SyncStatusEvent(:final status):
|
||||||
case "client_state":
|
ref.read(SyncStatusController.provider.notifier).set(status);
|
||||||
ref
|
case InitCompleteEvent():
|
||||||
.read(ClientStateController.provider.notifier)
|
|
||||||
.set(.fromJson(decodedMuksEvent));
|
|
||||||
case "sync_status":
|
|
||||||
ref
|
|
||||||
.read(SyncStatusController.provider.notifier)
|
|
||||||
.set(.fromJson(decodedMuksEvent));
|
|
||||||
case "init_complete":
|
|
||||||
ref.read(InitCompleteController.provider.notifier).complete();
|
ref.read(InitCompleteController.provider.notifier).complete();
|
||||||
case "send_complete":
|
case SendCompleteEvent(:final event):
|
||||||
final event = Event.fromJson(decodedMuksEvent["event"]);
|
ref.read(RoomsController.provider.notifier).storeEvents([
|
||||||
|
event,
|
||||||
|
]);
|
||||||
|
case TypingEvent(:final typing):
|
||||||
|
ref.read(TypingController.provider.notifier).set(typing);
|
||||||
|
case EventsDecryptedEvent(:final decrypted):
|
||||||
ref
|
ref
|
||||||
.read(RoomsController.provider.notifier)
|
.read(RoomsController.provider.notifier)
|
||||||
.update(
|
.handleDecrypted(decrypted);
|
||||||
.new({
|
case SyncCompleteEvent(:final sync):
|
||||||
event.roomId: .new(events: .new({event.rowId: event})),
|
ref.read(RoomsController.provider.notifier).handleSync(sync);
|
||||||
}),
|
|
||||||
);
|
|
||||||
case "typing":
|
|
||||||
ref
|
ref
|
||||||
.read(TypingController.provider.notifier)
|
.read(AccountDataController.provider.notifier)
|
||||||
.set(.fromJson(decodedMuksEvent));
|
.handleSync(sync);
|
||||||
case "events_decrypted":
|
ref.read(InvitesController.provider.notifier).handleSync(sync);
|
||||||
final decrypted = EventsDecrypted.fromJson(decodedMuksEvent);
|
ref.read(TypingController.provider.notifier).handleSync(sync);
|
||||||
final metadata = ref
|
|
||||||
.read(RoomsController.provider)[decrypted.roomId]
|
|
||||||
?.metadata;
|
|
||||||
|
|
||||||
ref
|
ref
|
||||||
.read(RoomsController.provider.notifier)
|
.read(TopLevelSpacesController.provider.notifier)
|
||||||
.update(
|
.handleSync(sync);
|
||||||
.new({
|
|
||||||
decrypted.roomId: .new(
|
|
||||||
events: decrypted.events,
|
|
||||||
metadata: metadata?.copyWith(
|
|
||||||
previewEventRowID:
|
|
||||||
decrypted.previewEventRowID ??
|
|
||||||
metadata.previewEventRowID,
|
|
||||||
sortingTimestamp:
|
|
||||||
decrypted.sortingTimestamp ??
|
|
||||||
metadata.sortingTimestamp,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
case "sync_complete":
|
|
||||||
final syncData = SyncData.fromJson(decodedMuksEvent);
|
|
||||||
final roomProvider = RoomsController.provider;
|
|
||||||
final accountDataProvider = AccountDataController.provider;
|
|
||||||
final invitesProvider = InvitesController.provider;
|
|
||||||
|
|
||||||
if (syncData.clearState) {
|
|
||||||
ref.invalidate(roomProvider);
|
|
||||||
ref.invalidate(accountDataProvider);
|
|
||||||
ref.invalidate(invitesProvider);
|
|
||||||
ref.invalidate(TypingController.provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
ref
|
ref
|
||||||
.read(roomProvider.notifier)
|
.read(SpaceEdgesController.provider.notifier)
|
||||||
.update(syncData.rooms, syncData.leftRooms);
|
.handleSync(sync);
|
||||||
ref
|
case UnknownGomuksEvent():
|
||||||
.read(accountDataProvider.notifier)
|
debugPrint("Unhandled event: $type");
|
||||||
.update(syncData.accountData);
|
|
||||||
ref
|
|
||||||
.read(invitesProvider.notifier)
|
|
||||||
.update(
|
|
||||||
syncData.invitedRooms,
|
|
||||||
joinedRooms: syncData.rooms.keys.toISet(),
|
|
||||||
leftRooms: syncData.leftRooms,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (syncData.topLevelSpaces case final topLevelSpaces?) {
|
|
||||||
ref
|
|
||||||
.read(TopLevelSpacesController.provider.notifier)
|
|
||||||
.set(topLevelSpaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syncData.spaceEdges case final spaceEdges?) {
|
|
||||||
ref
|
|
||||||
.read(SpaceEdgesController.provider.notifier)
|
|
||||||
.set(spaceEdges);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
debugPrint("Unhandled event: $muksEventType");
|
|
||||||
}
|
}
|
||||||
debugPrint("Finished handling $muksEventType...");
|
debugPrint("Finished handling $type...");
|
||||||
} catch (error, stackTrace) {
|
} catch (error, stackTrace) {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
debugPrintStack(stackTrace: stackTrace, label: error.toString());
|
debugPrintStack(stackTrace: stackTrace, label: error.toString());
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import "package:nexus/models/content/name.dart";
|
||||||
import "package:nexus/models/content/topic.dart";
|
import "package:nexus/models/content/topic.dart";
|
||||||
import "package:nexus/models/invited_room.dart";
|
import "package:nexus/models/invited_room.dart";
|
||||||
import "package:nexus/models/room_summary.dart";
|
import "package:nexus/models/room_summary.dart";
|
||||||
|
import "package:nexus/models/sync_data.dart";
|
||||||
|
|
||||||
/// Pending invites, newest first.
|
/// Pending invites, newest first.
|
||||||
class InvitesController extends Notifier<IList<RoomSummary>> {
|
class InvitesController extends Notifier<IList<RoomSummary>> {
|
||||||
|
|
@ -103,6 +104,15 @@ class InvitesController extends Notifier<IList<RoomSummary>> {
|
||||||
.removeWhere((invite) => removed.contains(invite.roomId));
|
.removeWhere((invite) => removed.contains(invite.roomId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleSync(SyncData sync) {
|
||||||
|
if (sync.clearState) state = .new();
|
||||||
|
update(
|
||||||
|
sync.invitedRooms,
|
||||||
|
joinedRooms: sync.rooms.keys.toISet(),
|
||||||
|
leftRooms: sync.leftRooms,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void remove(String roomId) =>
|
void remove(String roomId) =>
|
||||||
state = state.removeWhere((invite) => invite.roomId == roomId);
|
state = state.removeWhere((invite) => invite.roomId == roomId);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@ import "package:collection/collection.dart";
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/models/event.dart";
|
import "package:nexus/models/event.dart";
|
||||||
|
import "package:nexus/models/events_decrypted.dart";
|
||||||
import "package:nexus/models/read_receipt.dart";
|
import "package:nexus/models/read_receipt.dart";
|
||||||
import "package:nexus/models/room.dart";
|
import "package:nexus/models/room.dart";
|
||||||
|
import "package:nexus/models/sync_data.dart";
|
||||||
|
|
||||||
class RoomsController extends Notifier<IMap<String, Room>> {
|
class RoomsController extends Notifier<IMap<String, Room>> {
|
||||||
@override
|
@override
|
||||||
|
|
@ -82,6 +84,29 @@ class RoomsController extends Notifier<IMap<String, Room>> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void handleSync(SyncData sync) {
|
||||||
|
if (sync.clearState) state = .new();
|
||||||
|
update(sync.rooms, sync.leftRooms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleDecrypted(EventsDecrypted decrypted) {
|
||||||
|
final metadata = state[decrypted.roomId]?.metadata;
|
||||||
|
|
||||||
|
update(
|
||||||
|
.new({
|
||||||
|
decrypted.roomId: .new(
|
||||||
|
events: decrypted.events,
|
||||||
|
metadata: metadata?.copyWith(
|
||||||
|
previewEventRowID:
|
||||||
|
decrypted.previewEventRowID ?? metadata.previewEventRowID,
|
||||||
|
sortingTimestamp:
|
||||||
|
decrypted.sortingTimestamp ?? metadata.sortingTimestamp,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static IMap<String, ISet<int>> addRelations(
|
static IMap<String, ISet<int>> addRelations(
|
||||||
IMap<String, ISet<int>> relations,
|
IMap<String, ISet<int>> relations,
|
||||||
Iterable<Event> events,
|
Iterable<Event> events,
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/models/space_edge.dart";
|
import "package:nexus/models/space_edge.dart";
|
||||||
|
import "package:nexus/models/sync_data.dart";
|
||||||
|
|
||||||
class SpaceEdgesController extends Notifier<IMap<String, IList<SpaceEdge>>> {
|
class SpaceEdgesController extends Notifier<IMap<String, IList<SpaceEdge>>> {
|
||||||
@override
|
@override
|
||||||
IMap<String, IList<SpaceEdge>> build() => .new();
|
IMap<String, IList<SpaceEdge>> build() => .new();
|
||||||
|
|
||||||
void set(IMap<String, IList<SpaceEdge>> newEdges) =>
|
void handleSync(SyncData sync) => state = sync.spaceEdges ?? state;
|
||||||
state = state.addAll(newEdges);
|
|
||||||
|
|
||||||
static final provider =
|
static final provider =
|
||||||
NotifierProvider<SpaceEdgesController, IMap<String, IList<SpaceEdge>>>(
|
NotifierProvider<SpaceEdgesController, IMap<String, IList<SpaceEdge>>>(
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
|
import "package:nexus/models/sync_data.dart";
|
||||||
|
|
||||||
class TopLevelSpacesController extends Notifier<IList<String>> {
|
class TopLevelSpacesController extends Notifier<IList<String>> {
|
||||||
@override
|
@override
|
||||||
IList<String> build() => .new();
|
IList<String> build() => .new();
|
||||||
|
|
||||||
void set(IList<String> newSpaces) => state = newSpaces;
|
void handleSync(SyncData sync) => state = sync.topLevelSpaces ?? state;
|
||||||
|
|
||||||
static final provider =
|
static final provider =
|
||||||
NotifierProvider<TopLevelSpacesController, IList<String>>(
|
NotifierProvider<TopLevelSpacesController, IList<String>>(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
|
import "package:nexus/models/sync_data.dart";
|
||||||
import "package:nexus/models/typing.dart";
|
import "package:nexus/models/typing.dart";
|
||||||
|
|
||||||
class TypingController extends Notifier<IMap<String, IList<String>>> {
|
class TypingController extends Notifier<IMap<String, IList<String>>> {
|
||||||
|
|
@ -8,6 +9,10 @@ class TypingController extends Notifier<IMap<String, IList<String>>> {
|
||||||
|
|
||||||
void set(Typing typing) => state = state.add(typing.roomId, typing.userIds);
|
void set(Typing typing) => state = state.add(typing.roomId, typing.userIds);
|
||||||
|
|
||||||
|
void handleSync(SyncData sync) {
|
||||||
|
if (sync.clearState) state = .new();
|
||||||
|
}
|
||||||
|
|
||||||
static final provider =
|
static final provider =
|
||||||
NotifierProvider<TypingController, IMap<String, IList<String>>>(
|
NotifierProvider<TypingController, IMap<String, IList<String>>>(
|
||||||
TypingController.new,
|
TypingController.new,
|
||||||
|
|
|
||||||
34
lib/models/gomuks_event.dart
Normal file
34
lib/models/gomuks_event.dart
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import "package:freezed_annotation/freezed_annotation.dart";
|
||||||
|
import "package:nexus/models/client_state.dart";
|
||||||
|
import "package:nexus/models/event.dart";
|
||||||
|
import "package:nexus/models/events_decrypted.dart";
|
||||||
|
import "package:nexus/models/sync_data.dart";
|
||||||
|
import "package:nexus/models/sync_status.dart";
|
||||||
|
import "package:nexus/models/typing.dart";
|
||||||
|
|
||||||
|
part "gomuks_event.freezed.dart";
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class GomuksEvent with _$GomuksEvent {
|
||||||
|
const factory GomuksEvent.clientState(ClientState state) = ClientStateEvent;
|
||||||
|
const factory GomuksEvent.syncStatus(SyncStatus status) = SyncStatusEvent;
|
||||||
|
const factory GomuksEvent.initComplete() = InitCompleteEvent;
|
||||||
|
const factory GomuksEvent.sendComplete(Event event) = SendCompleteEvent;
|
||||||
|
const factory GomuksEvent.typing(Typing typing) = TypingEvent;
|
||||||
|
const factory GomuksEvent.eventsDecrypted(EventsDecrypted decrypted) =
|
||||||
|
EventsDecryptedEvent;
|
||||||
|
const factory GomuksEvent.syncComplete(SyncData sync) = SyncCompleteEvent;
|
||||||
|
const factory GomuksEvent.unknown(String type) = UnknownGomuksEvent;
|
||||||
|
|
||||||
|
factory GomuksEvent.parse(String type, Map<String, dynamic> json) =>
|
||||||
|
switch (type) {
|
||||||
|
"client_state" => .clientState(.fromJson(json)),
|
||||||
|
"sync_status" => .syncStatus(.fromJson(json)),
|
||||||
|
"init_complete" => const .initComplete(),
|
||||||
|
"send_complete" => .sendComplete(.fromJson(json["event"])),
|
||||||
|
"typing" => .typing(.fromJson(json)),
|
||||||
|
"events_decrypted" => .eventsDecrypted(.fromJson(json)),
|
||||||
|
"sync_complete" => .syncComplete(.fromJson(json)),
|
||||||
|
_ => .unknown(type),
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue