migrate Content classes to primary constructors

The Riverpod bug preventing us from doing this has been fixed.
This commit is contained in:
Henry Hiles 2026-10-23 20:44:29 -04:00
commit dd01ad9d74
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
17 changed files with 120 additions and 162 deletions

View file

@ -4,11 +4,11 @@ import "package:nexus/models/info/image.dart";
part "avatar.freezed.dart"; part "avatar.freezed.dart";
part "avatar.g.dart"; part "avatar.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class AvatarContent extends Content with _$AvatarContent { @JsonSerializable()
AvatarContent._(); class const AvatarContent({final ImageInfo? info, final Uri? url})
factory AvatarContent({ImageInfo? info, Uri? url}) = _AvatarContent; extends Content
with _$AvatarContent {
factory AvatarContent.fromJson(Map<String, Object?> json) => factory AvatarContent.fromJson(Map<String, Object?> json) =>
_$AvatarContentFromJson(json); _$AvatarContentFromJson(json);
} }

View file

@ -4,15 +4,12 @@ import "package:nexus/models/content/content.dart";
part "canonical_alias.freezed.dart"; part "canonical_alias.freezed.dart";
part "canonical_alias.g.dart"; part "canonical_alias.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class CanonicalAliasContent extends Content @JsonSerializable()
with _$CanonicalAliasContent { class const CanonicalAliasContent({
CanonicalAliasContent._(); @JsonKey(includeIfNull: false) final String? alias,
factory CanonicalAliasContent({ final ISet<String> altAliases = const .empty(),
@JsonKey(includeIfNull: false) String? alias, }) extends Content with _$CanonicalAliasContent {
@Default(ISet.empty()) ISet<String> altAliases,
}) = _CanonicalAliasContent;
factory CanonicalAliasContent.fromJson(Map<String, Object?> json) => factory CanonicalAliasContent.fromJson(Map<String, Object?> json) =>
_$CanonicalAliasContentFromJson(json); _$CanonicalAliasContentFromJson(json);
} }

View file

@ -4,22 +4,16 @@ import "package:nexus/models/content/content.dart";
part "create.freezed.dart"; part "create.freezed.dart";
part "create.g.dart"; part "create.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class CreateContent extends Content with _$CreateContent { @JsonSerializable()
CreateContent._(); class const CreateContent({
factory CreateContent({ @JsonKey(name: "additional_creators")
@JsonKey(name: "additional_creators") final IList<String> additionalCreatorIds = const .empty(),
@Default(IList.empty()) final PreviousRoom? predecessor,
IList<String> additionalCreatorIds, @JsonKey(name: "m.federate") final bool federated = true,
final String roomVersion = "1",
PreviousRoom? predecessor, @JsonKey(unknownEnumValue: RoomType.room) final RoomType? type,
}) extends Content with _$CreateContent {
@JsonKey(name: "m.federate") @Default(true) bool federated,
@Default("1") String roomVersion,
@JsonKey(unknownEnumValue: RoomType.room) RoomType? type,
}) = _CreateContent;
factory CreateContent.fromJson(Map<String, Object?> json) => factory CreateContent.fromJson(Map<String, Object?> json) =>
_$CreateContentFromJson(json); _$CreateContentFromJson(json);
} }

View file

@ -3,10 +3,11 @@ import "package:nexus/models/content/content.dart";
part "encrypted.freezed.dart"; part "encrypted.freezed.dart";
part "encrypted.g.dart"; part "encrypted.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class EncryptedContent extends Content with _$EncryptedContent { @JsonSerializable()
EncryptedContent._(); class const EncryptedContent() extends Content with _$EncryptedContent {
factory EncryptedContent() = _EncryptedContent; @override
Map<String, Object?> toJson() => _$EncryptedContentToJson(this);
factory EncryptedContent.fromJson(Map<String, Object?> json) => factory EncryptedContent.fromJson(Map<String, Object?> json) =>
_$EncryptedContentFromJson(json); _$EncryptedContentFromJson(json);

View file

@ -3,21 +3,13 @@ import "package:nexus/models/content/content.dart";
part "encryption.freezed.dart"; part "encryption.freezed.dart";
part "encryption.g.dart"; part "encryption.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class EncryptionContent extends Content with _$EncryptionContent { @JsonSerializable()
EncryptionContent._(); class const EncryptionContent({
factory EncryptionContent({ required final String algorithm,
required String algorithm, @JsonKey(name: "rotation_period_ms") final int rotationPeriodMS = 604800000,
@JsonKey(name: "rotation_period_msgs") final int rotationPeriodMessages = 100,
@JsonKey(name: "rotation_period_ms") }) extends Content with _$EncryptionContent {
@Default(604800000)
int rotationPeriodMS,
@JsonKey(name: "rotation_period_msgs")
@Default(100)
int rotationPeriodMessages,
}) = _EncryptionContent;
factory EncryptionContent.fromJson(Map<String, Object?> json) => factory EncryptionContent.fromJson(Map<String, Object?> json) =>
_$EncryptionContentFromJson(json); _$EncryptionContentFromJson(json);
} }

View file

@ -3,15 +3,12 @@ import "package:nexus/models/content/content.dart";
part "history_visibility.freezed.dart"; part "history_visibility.freezed.dart";
part "history_visibility.g.dart"; part "history_visibility.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class HistoryVisibilityContent extends Content @JsonSerializable()
with _$HistoryVisibilityContent { class const HistoryVisibilityContent({
HistoryVisibilityContent._(); @JsonKey(unknownEnumValue: HistoryVisibility.unknown)
factory HistoryVisibilityContent({ required final HistoryVisibility historyVisibility,
@JsonKey(unknownEnumValue: HistoryVisibility.unknown) }) extends Content with _$HistoryVisibilityContent {
required HistoryVisibility historyVisibility,
}) = _HistoryVisibilityContent;
factory HistoryVisibilityContent.fromJson(Map<String, Object?> json) => factory HistoryVisibilityContent.fromJson(Map<String, Object?> json) =>
_$HistoryVisibilityContentFromJson(json); _$HistoryVisibilityContentFromJson(json);
} }

View file

@ -6,14 +6,12 @@ part "image_pack.freezed.dart";
part "image_pack.g.dart"; part "image_pack.g.dart";
/// An image pack (MSC2545), from a room's state. /// An image pack (MSC2545), from a room's state.
@freezed @Freezed(toJson: false, fromJson: false)
sealed class ImagePackContent extends Content with _$ImagePackContent { @JsonSerializable()
ImagePackContent._(); class const ImagePackContent({
factory ImagePackContent({ final IMap<String, PackImage> images = const .empty(),
@Default(IMap.empty()) IMap<String, PackImage> images, final PackInfo? pack,
PackInfo? pack, }) extends Content with _$ImagePackContent {
}) = _ImagePackContent;
IMap<String, PackImage> imagesFor(ImageUsage usage) => images.where( IMap<String, PackImage> imagesFor(ImageUsage usage) => images.where(
(_, image) => switch ((image.usage, pack?.usage ?? const .empty())) { (_, image) => switch ((image.usage, pack?.usage ?? const .empty())) {
(final usages, _) when usages.isNotEmpty => usages.contains(usage), (final usages, _) when usages.isNotEmpty => usages.contains(usage),

View file

@ -5,14 +5,12 @@ import "package:nexus/models/join_rule.dart";
part "join_rules.freezed.dart"; part "join_rules.freezed.dart";
part "join_rules.g.dart"; part "join_rules.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class JoinRulesContent extends Content with _$JoinRulesContent { @JsonSerializable()
JoinRulesContent._(); class const JoinRulesContent({
factory JoinRulesContent({ @JsonKey(unknownEnumValue: JoinRule.unknown) required final JoinRule joinRule,
@JsonKey(unknownEnumValue: JoinRule.unknown) required JoinRule joinRule, final ISet<AllowCondition> allow = const .empty(),
@Default(ISet.empty()) ISet<AllowCondition> allow, }) extends Content with _$JoinRulesContent {
}) = _JoinRulesContent;
factory JoinRulesContent.fromJson(Map<String, Object?> json) => factory JoinRulesContent.fromJson(Map<String, Object?> json) =>
_$JoinRulesContentFromJson(json); _$JoinRulesContentFromJson(json);
} }

View file

@ -4,26 +4,20 @@ import "package:nexus/models/membership_status.dart";
part "membership.freezed.dart"; part "membership.freezed.dart";
part "membership.g.dart"; part "membership.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class MembershipContent extends Content with _$MembershipContent { @JsonSerializable()
MembershipContent._(); class const MembershipContent({
@JsonKey(name: "displayname", fromJson: MembershipContent.displaynameFromJson)
required final String? displayName,
@JsonKey(name: "membership", unknownEnumValue: MembershipStatus.unknown)
required final MembershipStatus status,
final Uri? avatarUrl,
final String? reason,
final bool isDirect = false,
}) extends Content with _$MembershipContent {
static String? displaynameFromJson(String? displayName) => static String? displaynameFromJson(String? displayName) =>
displayName?.isEmpty == true ? null : displayName; displayName?.isEmpty == true ? null : displayName;
factory MembershipContent({
@JsonKey(
name: "displayname",
fromJson: MembershipContent.displaynameFromJson,
)
required String? displayName,
@JsonKey(name: "membership", unknownEnumValue: MembershipStatus.unknown)
required MembershipStatus status,
Uri? avatarUrl,
String? reason,
@Default(false) bool isDirect,
}) = _MembershipContent;
factory MembershipContent.fromJson(Map<String, Object?> json) => factory MembershipContent.fromJson(Map<String, Object?> json) =>
_$MembershipContentFromJson(json); _$MembershipContentFromJson(json);
} }

View file

@ -3,11 +3,11 @@ import "package:nexus/models/content/content.dart";
part "name.freezed.dart"; part "name.freezed.dart";
part "name.g.dart"; part "name.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class NameContent extends Content with _$NameContent { @JsonSerializable()
NameContent._(); class const NameContent({required final String name})
factory NameContent({required String name}) = _NameContent; extends Content
with _$NameContent {
factory NameContent.fromJson(Map<String, Object?> json) => factory NameContent.fromJson(Map<String, Object?> json) =>
_$NameContentFromJson(json); _$NameContentFromJson(json);
} }

View file

@ -4,13 +4,11 @@ import "package:nexus/models/content/content.dart";
part "pinned_events.freezed.dart"; part "pinned_events.freezed.dart";
part "pinned_events.g.dart"; part "pinned_events.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class PinnedEventsContent extends Content with _$PinnedEventsContent { @JsonSerializable()
PinnedEventsContent._(); class const PinnedEventsContent({
factory PinnedEventsContent({ @JsonKey(name: "pinned") final IList<String> pinnedEvents = const .empty(),
@Default(IList.empty()) @JsonKey(name: "pinned") IList<String> pinnedEvents, }) extends Content with _$PinnedEventsContent {
}) = _PinnedEventsContent;
factory PinnedEventsContent.fromJson(Map<String, Object?> json) => factory PinnedEventsContent.fromJson(Map<String, Object?> json) =>
_$PinnedEventsContentFromJson(json); _$PinnedEventsContentFromJson(json);
} }

View file

@ -4,22 +4,20 @@ import "package:nexus/models/content/content.dart";
part "power_levels.freezed.dart"; part "power_levels.freezed.dart";
part "power_levels.g.dart"; part "power_levels.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class PowerLevelsContent extends Content with _$PowerLevelsContent { @JsonSerializable()
PowerLevelsContent._(); class const PowerLevelsContent({
factory PowerLevelsContent({ final IMap<String, int> events = const .empty(),
@Default(IMap.empty()) IMap<String, int> events, final IMap<String, int> users = const .empty(),
@Default(IMap.empty()) IMap<String, int> users, @JsonKey(includeIfNull: false) final Notifications? notifications,
@JsonKey(includeIfNull: false) Notifications? notifications, final int ban = 50,
@Default(50) int ban, final int eventsDefault = 0,
@Default(0) int eventsDefault, final int invite = 0,
@Default(0) int invite, final int kick = 50,
@Default(50) int kick, final int redact = 50,
@Default(50) int redact, final int stateDefault = 50,
@Default(50) int stateDefault, final int usersDefault = 0,
@Default(0) int usersDefault, }) extends Content with _$PowerLevelsContent {
}) = _PowerLevelsContent;
factory PowerLevelsContent.fromJson(Map<String, Object?> json) => factory PowerLevelsContent.fromJson(Map<String, Object?> json) =>
_$PowerLevelsContentFromJson(json); _$PowerLevelsContentFromJson(json);
} }

View file

@ -3,19 +3,17 @@ import "package:nexus/models/content/content.dart";
part "reaction.freezed.dart"; part "reaction.freezed.dart";
part "reaction.g.dart"; part "reaction.g.dart";
@Freezed(toJson: false) @Freezed(toJson: false, fromJson: false)
sealed class ReactionContent extends Content with _$ReactionContent { @JsonSerializable()
ReactionContent._(); class const ReactionContent({
@JsonKey(readValue: ReactionContent.keyJsonFromJson) final String? key,
/// For custom emoji reactions
@JsonKey(name: "com.beeper.reaction.shortcode") final String? shortcode,
}) extends Content with _$ReactionContent {
static String? keyJsonFromJson(Map<dynamic, dynamic> json, String key) => static String? keyJsonFromJson(Map<dynamic, dynamic> json, String key) =>
json["m.relates_to"]?["key"]; json["m.relates_to"]?["key"];
factory ReactionContent({
@JsonKey(readValue: ReactionContent.keyJsonFromJson) String? key,
/// For custom emoji reactions
@JsonKey(name: "com.beeper.reaction.shortcode") String? shortcode,
}) = _ReactionContent;
@override @override
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
"m.relates_to": {"key": key}, "m.relates_to": {"key": key},

View file

@ -3,12 +3,11 @@ import "package:nexus/models/content/content.dart";
part "redaction.freezed.dart"; part "redaction.freezed.dart";
part "redaction.g.dart"; part "redaction.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class RedactionContent extends Content with _$RedactionContent { @JsonSerializable()
RedactionContent._(); class const RedactionContent({final String? reason, final String? redacts})
factory RedactionContent({String? reason, String? redacts}) = extends Content
_RedactionContent; with _$RedactionContent {
factory RedactionContent.fromJson(Map<String, Object?> json) => factory RedactionContent.fromJson(Map<String, Object?> json) =>
_$RedactionContentFromJson(json); _$RedactionContentFromJson(json);
} }

View file

@ -4,15 +4,13 @@ import "package:nexus/models/content/content.dart";
part "server_acl.freezed.dart"; part "server_acl.freezed.dart";
part "server_acl.g.dart"; part "server_acl.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class ServerACLContent extends Content with _$ServerACLContent { @JsonSerializable()
ServerACLContent._(); class const ServerACLContent({
factory ServerACLContent({ final IList<String> allow = const .empty(),
@Default(IList.empty()) IList<String> allow, final IList<String> deny = const .empty(),
@Default(IList.empty()) IList<String> deny, final bool allowIpLiterals = true,
@Default(true) allowIpLiterals, }) extends Content with _$ServerACLContent {
}) = _ServerACLContent;
factory ServerACLContent.fromJson(Map<String, Object?> json) => factory ServerACLContent.fromJson(Map<String, Object?> json) =>
_$ServerACLContentFromJson(json); _$ServerACLContentFromJson(json);
} }

View file

@ -4,15 +4,13 @@ import "package:nexus/models/info/image.dart";
part "sticker.freezed.dart"; part "sticker.freezed.dart";
part "sticker.g.dart"; part "sticker.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class StickerContent extends Content with _$StickerContent { @JsonSerializable()
StickerContent._(); class const StickerContent({
factory StickerContent({ required final String body,
required String body, required final ImageInfo info,
required ImageInfo info, required final Uri url,
required Uri url, }) extends Content with _$StickerContent {
}) = _StickerContent;
factory StickerContent.fromJson(Map<String, Object?> json) => factory StickerContent.fromJson(Map<String, Object?> json) =>
_$StickerContentFromJson(json); _$StickerContentFromJson(json);
} }

View file

@ -5,14 +5,12 @@ import "package:nexus/models/content/content.dart";
part "topic.freezed.dart"; part "topic.freezed.dart";
part "topic.g.dart"; part "topic.g.dart";
@freezed @Freezed(toJson: false, fromJson: false)
sealed class TopicContent extends Content with _$TopicContent { @JsonSerializable()
TopicContent._(); class const TopicContent({
factory TopicContent({ required final String topic,
required String topic, @JsonKey(name: "m.topic") final TopicContentBlock? content,
@JsonKey(name: "m.topic") TopicContentBlock? content, }) extends Content with _$TopicContent {
}) = _TopicContent;
factory TopicContent.fromJson(Map<String, Object?> json) => factory TopicContent.fromJson(Map<String, Object?> json) =>
_$TopicContentFromJson(json); _$TopicContentFromJson(json);
} }
@ -20,7 +18,7 @@ sealed class TopicContent extends Content with _$TopicContent {
@Freezed(toJson: false, fromJson: false) @Freezed(toJson: false, fromJson: false)
@JsonSerializable() @JsonSerializable()
class const TopicContentBlock({ class const TopicContentBlock({
final IList<TextualRepresentation> representations = const IList.empty(), final IList<TextualRepresentation> representations = const .empty(),
}) with _$TopicContentBlock { }) with _$TopicContentBlock {
Map<String, Object?> toJson() => _$TopicContentBlockToJson(this); Map<String, Object?> toJson() => _$TopicContentBlockToJson(this);