diff --git a/lib/controllers/client_controller.dart b/lib/controllers/client_controller.dart index 59bb0b9..d0e1633 100644 --- a/lib/controllers/client_controller.dart +++ b/lib/controllers/client_controller.dart @@ -1,3 +1,5 @@ +import "dart:convert"; +import "dart:developer"; import "dart:ffi"; import "dart:isolate"; import "package:ffi/ffi.dart"; @@ -7,6 +9,7 @@ import "package:nexus/controllers/sync_status_controller.dart"; import "package:nexus/helpers/extensions/gomuks_buffer.dart"; import "package:nexus/models/client_state.dart"; import "package:nexus/models/login.dart"; +import "package:nexus/models/sync_complete.dart"; import "package:nexus/models/sync_status.dart"; import "package:nexus/src/third_party/gomuks.g.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; @@ -42,10 +45,16 @@ class ClientController extends AsyncNotifier { .set(SyncStatus.fromJson(decodedMuksEvent)); break; case "sync_complete": + debugger(message: jsonEncode(decodedMuksEvent)); + final thing = SyncComplete.fromJson(decodedMuksEvent); + debugger(message: jsonEncode(thing.toJson())); // ref // .watch(SyncStatusController.provider.notifier) // .set(SyncStatus.fromJson(decodedMuksEvent)); break; + case "typing": + //TODO: IMPL + break; default: debugPrint("Unhandled event: $muksEventType"); } diff --git a/lib/controllers/database_controller.dart b/lib/controllers/database_controller.dart deleted file mode 100644 index 706560b..0000000 --- a/lib/controllers/database_controller.dart +++ /dev/null @@ -1,18 +0,0 @@ -import "package:flutter_riverpod/flutter_riverpod.dart"; -import "package:path/path.dart"; -import "package:path_provider/path_provider.dart"; -import "package:sqflite_common_ffi/sqflite_ffi.dart"; - -class DatabaseController extends AsyncNotifier { - @override - Future build() async { - databaseFactory = databaseFactoryFfi; - return databaseFactoryFfi.openDatabase( - join((await getApplicationSupportDirectory()).path, "database.db"), - ); - } - - static final provider = AsyncNotifierProvider( - DatabaseController.new, - ); -} diff --git a/lib/models/content_uri.dart b/lib/models/content_uri.dart new file mode 100644 index 0000000..92d3a44 --- /dev/null +++ b/lib/models/content_uri.dart @@ -0,0 +1,14 @@ +import "package:freezed_annotation/freezed_annotation.dart"; +part "content_uri.freezed.dart"; +part "content_uri.g.dart"; + +@freezed +abstract class ContentUri with _$ContentUri { + const factory ContentUri({ + required String homeserver, + required String fileID, + }) = _ContentUri; + + factory ContentUri.fromJson(Map json) => + _$ContentUriFromJson(json); +} diff --git a/lib/models/epoch_date_time_converter.dart b/lib/models/epoch_date_time_converter.dart new file mode 100644 index 0000000..c26d020 --- /dev/null +++ b/lib/models/epoch_date_time_converter.dart @@ -0,0 +1,11 @@ +import "package:freezed_annotation/freezed_annotation.dart"; + +class EpochDateTimeConverter implements JsonConverter { + const EpochDateTimeConverter(); + + @override + DateTime fromJson(int json) => DateTime.fromMillisecondsSinceEpoch(json); + + @override + int toJson(DateTime object) => object.millisecondsSinceEpoch; +} diff --git a/lib/models/event.dart b/lib/models/event.dart new file mode 100644 index 0000000..3a3ecbd --- /dev/null +++ b/lib/models/event.dart @@ -0,0 +1,79 @@ +import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/models/epoch_date_time_converter.dart"; +part "event.freezed.dart"; +part "event.g.dart"; + +@freezed +abstract class Event with _$Event { + const factory Event({ + @JsonKey(name: "rowid") required int rowId, + @JsonKey(name: "timeline_rowid") required int timelineRowId, + required String roomId, + required int eventId, + @JsonKey(name: "sender") required int authorId, + required String type, + required String stateKey, + @EpochDateTimeConverter() required DateTime timestamp, + required Map content, + required Map decrypted, + required Map decryptedType, + required Map unsigned, + required LocalContent localContent, + required String transactionId, + required String redactedBy, + required String relatesTo, + required String relatesType, + required String decryptionError, + required String sendError, + required Map reactions, + required int lastEditRowId, + @UnreadTypeConverter() UnreadType? unreadType, + }) = _Event; + + factory Event.fromJson(Map json) => _$EventFromJson(json); +} + +@freezed +abstract class LocalContent with _$LocalContent { + const factory LocalContent({ + required String sanitizedHtml, + required String htmlVersion, + required bool wasPlaintext, + required bool bigEmoji, + required bool hasMath, + required String editSource, + required String replyFallbackRemoved, + }) = _LocalContent; + + factory LocalContent.fromJson(Map json) => + _$LocalContentFromJson(json); +} + +class UnreadTypeConverter implements JsonConverter { + const UnreadTypeConverter(); + + @override + UnreadType? fromJson(int? json) => json == null ? null : UnreadType(json); + + @override + int? toJson(UnreadType? object) => object?.value; +} + +@immutable +class UnreadType { + final int value; + + const UnreadType(this.value); + + static const none = UnreadType(0); + static const normal = UnreadType(1); + static const notify = UnreadType(2); + static const highlight = UnreadType(4); + static const sound = UnreadType(8); + + bool get isNone => value == 0; + bool get isNormal => (value & 1) != 0; + bool get shouldNotify => (value & 2) != 0; + bool get isHighlighted => (value & 4) != 0; + bool get playsSound => (value & 8) != 0; +} diff --git a/lib/models/lazy_load_summary.dart b/lib/models/lazy_load_summary.dart new file mode 100644 index 0000000..5d7db14 --- /dev/null +++ b/lib/models/lazy_load_summary.dart @@ -0,0 +1,15 @@ +import "package:freezed_annotation/freezed_annotation.dart"; +part "lazy_load_summary.freezed.dart"; +part "lazy_load_summary.g.dart"; + +@freezed +abstract class LazyLoadSummary with _$LazyLoadSummary { + const factory LazyLoadSummary({ + required List heroes, + required int? joinedMemberCount, + required int? invitedMemberCount, + }) = _LazyLoadSummary; + + factory LazyLoadSummary.fromJson(Map json) => + _$LazyLoadSummaryFromJson(json); +} diff --git a/lib/models/read_receipt.dart b/lib/models/read_receipt.dart new file mode 100644 index 0000000..d533e2d --- /dev/null +++ b/lib/models/read_receipt.dart @@ -0,0 +1,18 @@ +import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/models/epoch_date_time_converter.dart"; +part "read_receipt.freezed.dart"; +part "read_receipt.g.dart"; + +@freezed +abstract class ReadReceipt with _$ReadReceipt { + const factory ReadReceipt({ + String? roomId, + required String userId, + String? threadId, + required String eventId, + @EpochDateTimeConverter() required DateTime timestamp, + }) = _ReadReceipt; + + factory ReadReceipt.fromJson(Map json) => + _$ReadReceiptFromJson(json); +} diff --git a/lib/models/room.dart b/lib/models/room.dart new file mode 100644 index 0000000..c186863 --- /dev/null +++ b/lib/models/room.dart @@ -0,0 +1,34 @@ +import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/models/event.dart"; +import "package:nexus/models/read_receipt.dart"; +import "package:nexus/models/room_metadata.dart"; +part "room.freezed.dart"; +part "room.g.dart"; + +@freezed +abstract class Room with _$Room { + const factory Room({ + @JsonKey(name: "meta") RoomMetadata? metadata, + required List timeline, + required bool reset, + required Map state, + // required Map accountData, + required List events, + required Map> receipts, + required bool dismissNotifications, + // required List notifications, + }) = _Room; + + factory Room.fromJson(Map json) => _$RoomFromJson(json); +} + +@freezed +abstract class TimelineRowTuple with _$TimelineRowTuple { + const factory TimelineRowTuple({ + @JsonKey(name: "timeline_rowid") required int timelineRowId, + @JsonKey(name: "timeline_eventid") required int eventRowId, + }) = _TimelineRowTuple; + + factory TimelineRowTuple.fromJson(Map json) => + _$TimelineRowTupleFromJson(json); +} diff --git a/lib/models/room_metadata.dart b/lib/models/room_metadata.dart new file mode 100644 index 0000000..cfbc5d9 --- /dev/null +++ b/lib/models/room_metadata.dart @@ -0,0 +1,27 @@ +import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/models/content_uri.dart"; +import "package:nexus/models/epoch_date_time_converter.dart"; +import "package:nexus/models/lazy_load_summary.dart"; +part "room_metadata.freezed.dart"; +part "room_metadata.g.dart"; + +@freezed +abstract class RoomMetadata with _$RoomMetadata { + const factory RoomMetadata({ + @JsonKey(name: "room_id") required String id, + // required CreateEventContent creationContent, + // required TombstoneEventContent tombstoneEventContent, + String? name, + ContentUri? avatar, + String? topic, + String? canonicalAlias, + LazyLoadSummary? lazyLoadSummary, + required bool hasMemberList, + @JsonKey(name: "preview_event_rowid") required String previewEventRowID, + @EpochDateTimeConverter() required DateTime sortingTimestamp, + @Default(false) bool markedUnread, + }) = _RoomMetadata; + + factory RoomMetadata.fromJson(Map json) => + _$RoomMetadataFromJson(json); +} diff --git a/lib/models/sync_complete.dart b/lib/models/sync_complete.dart new file mode 100644 index 0000000..f01f533 --- /dev/null +++ b/lib/models/sync_complete.dart @@ -0,0 +1,20 @@ +import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/models/room.dart"; +part "sync_complete.freezed.dart"; +part "sync_complete.g.dart"; + +@freezed +abstract class SyncComplete with _$SyncComplete { + const factory SyncComplete({ + @Default(false) bool clearState, + // required Map accountData, + required Map rooms, + required List leftRooms, + // required List invitedRooms, + // required List spaceEdges, + required List topLevelSpaces, + }) = _SyncComplete; + + factory SyncComplete.fromJson(Map json) => + _$SyncCompleteFromJson(json); +} diff --git a/lib/models/sync_status.dart b/lib/models/sync_status.dart index fc70139..42c5f2a 100644 --- a/lib/models/sync_status.dart +++ b/lib/models/sync_status.dart @@ -6,8 +6,8 @@ part "sync_status.g.dart"; abstract class SyncStatus with _$SyncStatus { const factory SyncStatus({ required SyncStatusType type, + String? error, required int errorCount, - required int lastSync, }) = _SyncStatus; factory SyncStatus.fromJson(Map json) =>