nexus/lib/models/event.dart

107 lines
3.6 KiB
Dart

import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/content.dart";
import "package:nexus/models/epoch_date_time_converter.dart";
import "package:nexus/models/profile_response.dart";
part "event.freezed.dart";
part "event.g.dart";
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const Event({
@JsonKey(name: "rowid") required final int rowId,
@JsonKey(name: "timeline_rowid") required final int timelineRowId,
final String? stateKey,
required final String roomId,
required final String eventId,
required final String sender,
@JsonKey(readValue: Event.typeJsonFromJson) required final String type,
@EpochDateTimeConverter() required final DateTime timestamp,
final IMap<String, dynamic> unsigned = const IMap.empty(),
final LocalContent? localContent,
final String? transactionId,
final String? redactedBy,
final String? relatesTo,
final String? relationType,
final String? replyTo,
final String? decryptionError,
final String? sendError,
final IMap<String, int> reactions = const IMap.empty(),
@JsonKey(name: "last_edit_rowid") final int lastEditRowId = 0,
final UnreadType? unreadType,
final Profile? pmp,
required final Content content,
required final Content? previousContent,
}) with _$Event {
Map<String, Object?> toJson() => _$EventToJson(this);
static String typeJsonFromJson(Map<dynamic, dynamic> json, _) =>
json["decrypted_type"] ?? json["type"];
static Map<String, dynamic> getContentFromJson(Map<dynamic, dynamic> json) {
final content = json["decrypted"] ?? json["content"];
return content["m.new_content"] ?? content;
}
static String? replyToFromJson(Map<dynamic, dynamic> json) {
try {
return json["m.relates_to"]?["m.in_reply_to"]?["event_id"];
} catch (_) {
return null;
}
}
factory Event.fromJson(Map<String, dynamic> json) =>
_$EventFromJson(json).copyWith(
replyTo: replyToFromJson(getContentFromJson(json)),
pmp: json["content"]?["com.beeper.per_message_profile"] == null
? null
: Profile.fromJsonWithCatch(
json["content"]?["com.beeper.per_message_profile"],
),
content: Content.fromEventJson(
getContentFromJson(json),
json["decrypted_type"] ?? json["type"],
),
previousContent: json["unsigned"]?["prev_content"] == null
? null
: Content.fromEventJson(
json["unsigned"]?["prev_content"],
json["decrypted_type"] ?? json["type"],
),
);
}
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const LocalContent({
final String? sanitizedHtml,
final String? editSource,
final bool? wasPlaintext,
final bool? bigEmoji,
final bool? hasMath,
final bool? replyFallbackRemoved,
}) with _$LocalContent {
Map<String, Object?> toJson() => _$LocalContentToJson(this);
@override
factory LocalContent.fromJson(Map<String, Object?> json) =>
_$LocalContentFromJson(json);
}
@Freezed(toJson: false, fromJson: false)
class const UnreadType(final int value) with _$UnreadType {
factory UnreadType.fromJson(int json) => UnreadType(json);
int toJson() => 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 has(UnreadType flag) => value & flag.value != 0;
UnreadType operator |(UnreadType other) => UnreadType(value | other.value);
}