From b3db9bea6f4b46e27b0c02468ac609292521ca85 Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Wed, 13 May 2026 14:32:12 -0400 Subject: [PATCH] possible way to union event --- README.md | 2 +- lib/controllers/client_controller.dart | 2 +- lib/controllers/event_controller.dart | 2 +- lib/controllers/room_chat_controller.dart | 2 +- lib/controllers/via_controller.dart | 1 + lib/models/configs/message_config.dart | 2 +- lib/models/configs/messages_config.dart | 2 +- lib/models/event.dart | 80 ----------------------- lib/models/event/content/membership.dart | 38 +++++++++++ lib/models/event/event.dart | 18 +++++ lib/models/event/info.dart | 38 +++++++++++ lib/models/event/local_content.dart | 18 +++++ lib/models/event/unread_type.dart | 29 ++++++++ lib/models/paginate.dart | 2 +- lib/models/room.dart | 2 +- pubspec.lock | 24 +++---- pubspec.yaml | 14 +++- 17 files changed, 175 insertions(+), 101 deletions(-) delete mode 100644 lib/models/event.dart create mode 100644 lib/models/event/content/membership.dart create mode 100644 lib/models/event/event.dart create mode 100644 lib/models/event/info.dart create mode 100644 lib/models/event/local_content.dart create mode 100644 lib/models/event/unread_type.dart diff --git a/README.md b/README.md index 2c44fc8..08d479f 100644 --- a/README.md +++ b/README.md @@ -212,7 +212,7 @@ dart scripts/generate.dart Build generated files, and watch for new changes: ```sh -flutter pub run build_runner watch --delete-conflicting-outputs +flutter pub run build_runner watch ``` Run the app: diff --git a/lib/controllers/client_controller.dart b/lib/controllers/client_controller.dart index bbadd8e..c666c87 100644 --- a/lib/controllers/client_controller.dart +++ b/lib/controllers/client_controller.dart @@ -17,7 +17,7 @@ import "package:nexus/controllers/top_level_spaces_controller.dart"; import "package:nexus/helpers/extensions/gomuks_buffer.dart"; import "package:nexus/main.dart"; import "package:nexus/models/client_state.dart"; -import "package:nexus/models/event.dart"; +import "package:nexus/models/event/event.dart"; import "package:nexus/models/paginate.dart"; import "package:nexus/models/requests/get_event_request.dart"; import "package:nexus/models/requests/get_related_events_request.dart"; diff --git a/lib/controllers/event_controller.dart b/lib/controllers/event_controller.dart index 4f72963..6db926f 100644 --- a/lib/controllers/event_controller.dart +++ b/lib/controllers/event_controller.dart @@ -1,6 +1,6 @@ import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:nexus/controllers/client_controller.dart"; -import "package:nexus/models/event.dart"; +import "package:nexus/models/event/event.dart"; import "package:nexus/models/requests/get_event_request.dart"; class EventController extends AsyncNotifier { diff --git a/lib/controllers/room_chat_controller.dart b/lib/controllers/room_chat_controller.dart index a9e838b..70b4745 100644 --- a/lib/controllers/room_chat_controller.dart +++ b/lib/controllers/room_chat_controller.dart @@ -10,7 +10,7 @@ import "package:nexus/controllers/rooms_controller.dart"; import "package:nexus/controllers/selected_room_controller.dart"; import "package:nexus/models/configs/messages_config.dart"; import "package:nexus/models/configs/message_config.dart"; -import "package:nexus/models/event.dart"; +import "package:nexus/models/event/event.dart"; import "package:nexus/models/requests/get_related_events_request.dart"; import "package:nexus/models/requests/get_room_state_request.dart"; import "package:nexus/models/requests/paginate_request.dart"; diff --git a/lib/controllers/via_controller.dart b/lib/controllers/via_controller.dart index b423947..fdd38dc 100644 --- a/lib/controllers/via_controller.dart +++ b/lib/controllers/via_controller.dart @@ -2,6 +2,7 @@ import "package:collection/collection.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:nexus/controllers/client_state_controller.dart"; +import "package:nexus/models/event/event.dart"; import "package:nexus/models/room.dart"; class ViaController extends Notifier { diff --git a/lib/models/configs/message_config.dart b/lib/models/configs/message_config.dart index 66a437c..767372d 100644 --- a/lib/models/configs/message_config.dart +++ b/lib/models/configs/message_config.dart @@ -1,5 +1,5 @@ import "package:freezed_annotation/freezed_annotation.dart"; -import "package:nexus/models/event.dart"; +import "package:nexus/models/event/event.dart"; import "package:nexus/models/room.dart"; part "message_config.freezed.dart"; part "message_config.g.dart"; diff --git a/lib/models/configs/messages_config.dart b/lib/models/configs/messages_config.dart index b33a71c..5944df8 100644 --- a/lib/models/configs/messages_config.dart +++ b/lib/models/configs/messages_config.dart @@ -1,6 +1,6 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:freezed_annotation/freezed_annotation.dart"; -import "package:nexus/models/event.dart"; +import "package:nexus/models/event/event.dart"; import "package:nexus/models/room.dart"; part "messages_config.freezed.dart"; part "messages_config.g.dart"; diff --git a/lib/models/event.dart b/lib/models/event.dart deleted file mode 100644 index 4a72817..0000000 --- a/lib/models/event.dart +++ /dev/null @@ -1,80 +0,0 @@ -import "package:fast_immutable_collections/fast_immutable_collections.dart"; -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 String eventId, - required String sender, - required String type, - String? stateKey, - @EpochDateTimeConverter() required DateTime timestamp, - required IMap content, - IMap? decrypted, - String? decryptedType, - @Default(IMap.empty()) IMap unsigned, - LocalContent? localContent, - String? transactionId, - String? redactedBy, - String? relatesTo, - String? relationType, - String? decryptionError, - String? sendError, - @Default(IMap.empty()) IMap reactions, - @JsonKey(name: "last_edit_rowid") int? lastEditRowId, - @UnreadTypeConverter() UnreadType? unreadType, - }) = _Event; - - factory Event.fromJson(Map json) => _$EventFromJson(json); -} - -@freezed -abstract class LocalContent with _$LocalContent { - const factory LocalContent({ - String? sanitizedHtml, - String? editSource, - bool? wasPlaintext, - bool? bigEmoji, - bool? hasMath, - bool? 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; -} - -// I think this is correct but I'm not sure, its some type of bitmask. -@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/event/content/membership.dart b/lib/models/event/content/membership.dart new file mode 100644 index 0000000..4f09584 --- /dev/null +++ b/lib/models/event/content/membership.dart @@ -0,0 +1,38 @@ +import "package:fast_immutable_collections/fast_immutable_collections.dart"; +import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/models/epoch_date_time_converter.dart"; +import "package:nexus/models/event/local_content.dart"; +import "package:nexus/models/event/unread_type.dart"; +part "info.freezed.dart"; +part "info.g.dart"; + +@Freezed(unionKey: "type") +abstract class EventInfo with _$EventInfo { + const factory EventInfo({ + @JsonKey(name: "rowid") required int rowId, + @JsonKey(name: "timeline_rowid") required int timelineRowId, + required String type, + required String roomId, + required String eventinfoId, + required String sender, + String? stateKey, + @EpochDateTimeConverter() required DateTime timestamp, + @JsonKey(name: "content") required IMap rawContent, + IMap? decrypted, + String? decryptedType, + @Default(IMap.empty()) IMap unsigned, + LocalContent? localContent, + String? transactionId, + String? redactedBy, + String? relatesTo, + String? relationType, + String? decryptionError, + String? sendError, + @Default(IMap.empty()) IMap reactions, + @JsonKey(name: "last_edit_rowid") int? lastEditRowId, + @UnreadTypeConverter() UnreadType? unreadType, + }) = _EventInfo; + + factory EventInfo.fromJson(Map json) => + _$EventInfoFromJson(json); +} diff --git a/lib/models/event/event.dart b/lib/models/event/event.dart new file mode 100644 index 0000000..b081e18 --- /dev/null +++ b/lib/models/event/event.dart @@ -0,0 +1,18 @@ +import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/models/event/info.dart"; +part "event.freezed.dart"; +part "event.g.dart"; + +@Freezed(unionKey: "type") +abstract class Event with _$Event { + const factory Event({@JsonKey(flatten: true) required EventInfo info}) = + _GenericEvent; + + @FreezedUnionValue("m.room.member") + const factory Event.membership({ + @JsonKey(flatten: true) required EventInfo info, + required String content, + }) = _MemberEvent; + + factory Event.fromJson(Map json) => _$EventFromJson(json); +} diff --git a/lib/models/event/info.dart b/lib/models/event/info.dart new file mode 100644 index 0000000..4f09584 --- /dev/null +++ b/lib/models/event/info.dart @@ -0,0 +1,38 @@ +import "package:fast_immutable_collections/fast_immutable_collections.dart"; +import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/models/epoch_date_time_converter.dart"; +import "package:nexus/models/event/local_content.dart"; +import "package:nexus/models/event/unread_type.dart"; +part "info.freezed.dart"; +part "info.g.dart"; + +@Freezed(unionKey: "type") +abstract class EventInfo with _$EventInfo { + const factory EventInfo({ + @JsonKey(name: "rowid") required int rowId, + @JsonKey(name: "timeline_rowid") required int timelineRowId, + required String type, + required String roomId, + required String eventinfoId, + required String sender, + String? stateKey, + @EpochDateTimeConverter() required DateTime timestamp, + @JsonKey(name: "content") required IMap rawContent, + IMap? decrypted, + String? decryptedType, + @Default(IMap.empty()) IMap unsigned, + LocalContent? localContent, + String? transactionId, + String? redactedBy, + String? relatesTo, + String? relationType, + String? decryptionError, + String? sendError, + @Default(IMap.empty()) IMap reactions, + @JsonKey(name: "last_edit_rowid") int? lastEditRowId, + @UnreadTypeConverter() UnreadType? unreadType, + }) = _EventInfo; + + factory EventInfo.fromJson(Map json) => + _$EventInfoFromJson(json); +} diff --git a/lib/models/event/local_content.dart b/lib/models/event/local_content.dart new file mode 100644 index 0000000..98d69d2 --- /dev/null +++ b/lib/models/event/local_content.dart @@ -0,0 +1,18 @@ +import "package:freezed_annotation/freezed_annotation.dart"; +part "local_content.g.dart"; +part "local_content.freezed.dart"; + +@freezed +abstract class LocalContent with _$LocalContent { + const factory LocalContent({ + String? sanitizedHtml, + String? editSource, + bool? wasPlaintext, + bool? bigEmoji, + bool? hasMath, + bool? replyFallbackRemoved, + }) = _LocalContent; + + factory LocalContent.fromJson(Map json) => + _$LocalContentFromJson(json); +} diff --git a/lib/models/event/unread_type.dart b/lib/models/event/unread_type.dart new file mode 100644 index 0000000..bc40718 --- /dev/null +++ b/lib/models/event/unread_type.dart @@ -0,0 +1,29 @@ +import "package:freezed_annotation/freezed_annotation.dart"; + +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/paginate.dart b/lib/models/paginate.dart index df0a0f6..64fb5ec 100644 --- a/lib/models/paginate.dart +++ b/lib/models/paginate.dart @@ -1,6 +1,6 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:freezed_annotation/freezed_annotation.dart"; -import "package:nexus/models/event.dart"; +import "package:nexus/models/event/event.dart"; part "paginate.freezed.dart"; part "paginate.g.dart"; diff --git a/lib/models/room.dart b/lib/models/room.dart index 3c3eec0..a369f2b 100644 --- a/lib/models/room.dart +++ b/lib/models/room.dart @@ -1,6 +1,6 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:freezed_annotation/freezed_annotation.dart"; -import "package:nexus/models/event.dart"; +import "package:nexus/models/event/event.dart"; import "package:nexus/models/read_receipt.dart"; import "package:nexus/models/room_metadata.dart"; part "room.freezed.dart"; diff --git a/pubspec.lock b/pubspec.lock index 10f28bd..bd98a0d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -680,21 +680,23 @@ packages: source: hosted version: "1.0.5" json_annotation: - dependency: "direct main" + dependency: "direct overridden" description: - name: json_annotation - sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 - url: "https://pub.dev" - source: hosted - version: "4.11.0" + path: json_annotation + ref: "feature/json-key-flatten-2" + resolved-ref: "292d155b643b5f6fd956399d16a45711a0512ecd" + url: "https://github.com/helgoboss/json_serializable.dart" + source: git + version: "4.9.1-wip" json_serializable: dependency: "direct dev" description: - name: json_serializable - sha256: "44729f5c45748e6748f6b9a57ab8f7e4336edc8ae41fc295070e3814e616a6c0" - url: "https://pub.dev" - source: hosted - version: "6.13.0" + path: json_serializable + ref: "feature/json-key-flatten-2" + resolved-ref: "292d155b643b5f6fd956399d16a45711a0512ecd" + url: "https://github.com/helgoboss/json_serializable.dart" + source: git + version: "6.11.4" leak_tracker: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4e8d609..91fa146 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,6 +11,13 @@ flutter: environment: sdk: "3.11.4" +dependency_overrides: + json_annotation: + git: + url: https://github.com/helgoboss/json_serializable.dart + ref: feature/json-key-flatten-2 + path: json_annotation + dependencies: flutter: sdk: flutter @@ -35,7 +42,6 @@ dependencies: color_hash: 1.0.1 flutter_widget_from_html_core: 0.17.2 flutter_svg: 2.3.0 - json_annotation: 4.11.0 shared_preferences: 2.5.5 fluttertagger: 2.3.2 dynamic_polls: 0.0.7 @@ -59,7 +65,11 @@ dev_dependencies: freezed: 3.2.5 riverpod_lint: 3.1.3 flutter_launcher_icons: 0.14.4 - json_serializable: 6.13.0 + json_serializable: + git: + url: https://github.com/helgoboss/json_serializable.dart + ref: feature/json-key-flatten-2 + path: json_serializable flutter_launcher_icons: ios: true