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.g.dart";
@freezed
sealed class AvatarContent extends Content with _$AvatarContent {
AvatarContent._();
factory AvatarContent({ImageInfo? info, Uri? url}) = _AvatarContent;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const AvatarContent({final ImageInfo? info, final Uri? url})
extends Content
with _$AvatarContent {
factory AvatarContent.fromJson(Map<String, Object?> json) =>
_$AvatarContentFromJson(json);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,14 +6,12 @@ part "image_pack.freezed.dart";
part "image_pack.g.dart";
/// An image pack (MSC2545), from a room's state.
@freezed
sealed class ImagePackContent extends Content with _$ImagePackContent {
ImagePackContent._();
factory ImagePackContent({
@Default(IMap.empty()) IMap<String, PackImage> images,
PackInfo? pack,
}) = _ImagePackContent;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const ImagePackContent({
final IMap<String, PackImage> images = const .empty(),
final PackInfo? pack,
}) extends Content with _$ImagePackContent {
IMap<String, PackImage> imagesFor(ImageUsage usage) => images.where(
(_, image) => switch ((image.usage, pack?.usage ?? const .empty())) {
(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.g.dart";
@freezed
sealed class JoinRulesContent extends Content with _$JoinRulesContent {
JoinRulesContent._();
factory JoinRulesContent({
@JsonKey(unknownEnumValue: JoinRule.unknown) required JoinRule joinRule,
@Default(ISet.empty()) ISet<AllowCondition> allow,
}) = _JoinRulesContent;
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const JoinRulesContent({
@JsonKey(unknownEnumValue: JoinRule.unknown) required final JoinRule joinRule,
final ISet<AllowCondition> allow = const .empty(),
}) extends Content with _$JoinRulesContent {
factory JoinRulesContent.fromJson(Map<String, Object?> json) =>
_$JoinRulesContentFromJson(json);
}

View file

@ -4,26 +4,20 @@ import "package:nexus/models/membership_status.dart";
part "membership.freezed.dart";
part "membership.g.dart";
@freezed
sealed class MembershipContent extends Content with _$MembershipContent {
MembershipContent._();
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
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) =>
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) =>
_$MembershipContentFromJson(json);
}

View file

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

View file

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

View file

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

View file

@ -3,19 +3,17 @@ import "package:nexus/models/content/content.dart";
part "reaction.freezed.dart";
part "reaction.g.dart";
@Freezed(toJson: false)
sealed class ReactionContent extends Content with _$ReactionContent {
ReactionContent._();
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
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) =>
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
Map<String, dynamic> toJson() => {
"m.relates_to": {"key": key},

View file

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

View file

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

View file

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

View file

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