forked from Henry-Hiles/nexus
dont fail to parse on invalid reply
This commit is contained in:
parent
95d3d2c0b9
commit
4087d6ca11
1 changed files with 190 additions and 181 deletions
|
|
@ -14,150 +14,169 @@ class MessageController extends AsyncNotifier<Message?> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Message?> build() async {
|
Future<Message?> build() async {
|
||||||
if (config.event.relationType == "m.replace" && !config.includeEdits) {
|
try {
|
||||||
return null;
|
if (config.event.relationType == "m.replace" && !config.includeEdits) {
|
||||||
}
|
return null;
|
||||||
final client = ref.watch(ClientController.provider.notifier);
|
}
|
||||||
|
final client = ref.watch(ClientController.provider.notifier);
|
||||||
|
|
||||||
if (!ref.mounted) return null;
|
if (!ref.mounted) return null;
|
||||||
final event = config.event.lastEditRowId == null
|
final event = config.event.lastEditRowId == null
|
||||||
? config.event
|
? config.event
|
||||||
: config.room.events.firstWhereOrNull(
|
: config.room.events.firstWhereOrNull(
|
||||||
(e) => e.rowId == config.event.lastEditRowId,
|
(e) => e.rowId == config.event.lastEditRowId,
|
||||||
) ??
|
) ??
|
||||||
config.event;
|
config.event;
|
||||||
|
|
||||||
final replyId =
|
final replyId =
|
||||||
config.event.content["m.relates_to"]?["m.in_reply_to"]?["event_id"];
|
config.event.content["m.relates_to"]?["m.in_reply_to"]?["event_id"];
|
||||||
final replyEvent = replyId == null
|
final replyEvent = replyId == null
|
||||||
? null
|
? null
|
||||||
: await client.getEvent(
|
: await client
|
||||||
GetEventRequest(room: config.room, eventId: replyId),
|
.getEvent(GetEventRequest(room: config.room, eventId: replyId))
|
||||||
);
|
.onError((_, _) => null);
|
||||||
|
|
||||||
if (!ref.mounted) return null;
|
if (!ref.mounted) return null;
|
||||||
|
|
||||||
final members = ref.watch(MembersController.provider(config.room));
|
final members = ref.watch(MembersController.provider(config.room));
|
||||||
final author = members.firstWhereOrNull(
|
final author = members.firstWhereOrNull(
|
||||||
(member) => member.stateKey == event.authorId,
|
(member) => member.stateKey == event.authorId,
|
||||||
);
|
);
|
||||||
if (!ref.mounted) return null;
|
if (!ref.mounted) return null;
|
||||||
|
|
||||||
final content = (event.decrypted ?? event.content);
|
final content = (event.decrypted ?? event.content);
|
||||||
final type = (config.event.decryptedType ?? config.event.type);
|
final type = (config.event.decryptedType ?? config.event.type);
|
||||||
final newContent = content["m.new_content"] as Map?;
|
final newContent = content["m.new_content"] as Map?;
|
||||||
|
|
||||||
final homeserver = ref.read(ClientStateController.provider)?.homeserverUrl;
|
final homeserver = ref
|
||||||
final source = homeserver == null || content["url"] == null
|
.read(ClientStateController.provider)
|
||||||
? "null"
|
?.homeserverUrl;
|
||||||
: Uri.parse(content["url"]).mxcToHttps(homeserver).toString();
|
final source = homeserver == null || content["url"] == null
|
||||||
|
? "null"
|
||||||
|
: Uri.parse(content["url"]).mxcToHttps(homeserver).toString();
|
||||||
|
|
||||||
final metadata = {
|
final metadata = {
|
||||||
"body": config.event.redactedBy == null
|
"body": config.event.redactedBy == null
|
||||||
? (newContent?["body"] ?? content["body"] ?? "")
|
? (newContent?["body"] ?? content["body"] ?? "")
|
||||||
: "Deleted Message",
|
: "Deleted Message",
|
||||||
if (replyEvent != null)
|
if (replyEvent != null)
|
||||||
"reply": await ref.watch(
|
"reply": await ref.watch(
|
||||||
MessageController.provider(
|
MessageController.provider(
|
||||||
MessageConfig(
|
MessageConfig(
|
||||||
event: replyEvent,
|
event: replyEvent,
|
||||||
room: config.room,
|
room: config.room,
|
||||||
alwaysReturn: true,
|
alwaysReturn: true,
|
||||||
),
|
),
|
||||||
).future,
|
).future,
|
||||||
|
),
|
||||||
|
"flashing": false,
|
||||||
|
"timelineId": event.timelineRowId,
|
||||||
|
"big": event.localContent?.bigEmoji == true,
|
||||||
|
"eventType": type,
|
||||||
|
"avatarUrl": author?.content["avatar_url"],
|
||||||
|
"editSource":
|
||||||
|
event.localContent?.editSource ??
|
||||||
|
newContent?["body"] ??
|
||||||
|
content["body"],
|
||||||
|
"displayName": author?.content["displayname"]?.isNotEmpty == true
|
||||||
|
? author?.content["displayname"]
|
||||||
|
: event.authorId.substring(1).split(":")[0],
|
||||||
|
"txnId": config.event.transactionId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!ref.mounted) return null;
|
||||||
|
|
||||||
|
final editedAt = event.relationType == "m.replace"
|
||||||
|
? event.timestamp
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if ((event.redactedBy != null && !config.alwaysReturn) ||
|
||||||
|
(!config.includeEdits &&
|
||||||
|
(config.event.relationType == "m.replace"))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Use server-generated preview if enabled
|
||||||
|
|
||||||
|
// final match = Uri.tryParse(
|
||||||
|
// RegExp(regexLink, caseSensitive: false).firstMatch(body)?.group(0) ?? "",
|
||||||
|
// );
|
||||||
|
|
||||||
|
final asText =
|
||||||
|
Message.text(
|
||||||
|
metadata: metadata,
|
||||||
|
id: config.event.eventId,
|
||||||
|
authorId: event.authorId,
|
||||||
|
text:
|
||||||
|
newContent?["formatted_body"] ??
|
||||||
|
newContent?["body"] ??
|
||||||
|
content["formatted_body"] ??
|
||||||
|
content["body"] ??
|
||||||
|
"",
|
||||||
|
replyToMessageId: replyId,
|
||||||
|
deliveredAt: config.event.timestamp,
|
||||||
|
editedAt: editedAt,
|
||||||
|
)
|
||||||
|
as TextMessage;
|
||||||
|
|
||||||
|
return switch (type) {
|
||||||
|
"m.room.encrypted" => asText.copyWith(
|
||||||
|
text: "Unable to decrypt message.",
|
||||||
|
metadata: {...metadata, "body": "Unable to decrypt message."},
|
||||||
),
|
),
|
||||||
"flashing": false,
|
// "org.matrix.msc3381.poll.start" => Message.custom(
|
||||||
"timelineId": event.timelineRowId,
|
// metadata: {
|
||||||
"big": event.localContent?.bigEmoji == true,
|
// ...metadata,
|
||||||
"eventType": type,
|
// "poll": event.parsedPollEventContent.pollStartContent,
|
||||||
"avatarUrl": author?.content["avatar_url"],
|
// "responses": event.getPollResponses(timeline),
|
||||||
"editSource":
|
// },
|
||||||
event.localContent?.editSource ??
|
// id: eventId,
|
||||||
newContent?["body"] ??
|
// deliveredAt: originServerTs,
|
||||||
content["body"],
|
// authorId: senderId,
|
||||||
"displayName": author?.content["displayname"]?.isNotEmpty == true
|
// ),
|
||||||
? author?.content["displayname"]
|
("m.sticker" || "m.room.message") => switch (content["msgtype"]) {
|
||||||
: event.authorId.substring(1).split(":")[0],
|
null || "m.image" => Message.image(
|
||||||
"txnId": config.event.transactionId,
|
id: config.event.eventId,
|
||||||
};
|
authorId: event.authorId,
|
||||||
|
source: source,
|
||||||
if (!ref.mounted) return null;
|
replyToMessageId: replyId,
|
||||||
|
metadata: metadata,
|
||||||
final editedAt = event.relationType == "m.replace" ? event.timestamp : null;
|
text: asText.text,
|
||||||
|
deliveredAt: config.event.timestamp,
|
||||||
if ((event.redactedBy != null && !config.alwaysReturn) ||
|
blurhash: (content["info"] as Map?)?["xyz.amorgan.blurhash"],
|
||||||
(!config.includeEdits && (config.event.relationType == "m.replace"))) {
|
),
|
||||||
return null;
|
"m.audio" || "m.file" => Message.file(
|
||||||
}
|
name: content["filename"].toString(),
|
||||||
|
size: content["info"]["size"],
|
||||||
// TODO: Use server-generated preview if enabled
|
metadata: metadata,
|
||||||
|
id: config.event.eventId,
|
||||||
// final match = Uri.tryParse(
|
authorId: event.authorId,
|
||||||
// RegExp(regexLink, caseSensitive: false).firstMatch(body)?.group(0) ?? "",
|
source: source,
|
||||||
// );
|
replyToMessageId: replyId,
|
||||||
|
deliveredAt: config.event.timestamp,
|
||||||
final asText =
|
),
|
||||||
Message.text(
|
_ => asText,
|
||||||
metadata: metadata,
|
},
|
||||||
id: config.event.eventId,
|
"m.room.member" =>
|
||||||
authorId: event.authorId,
|
content["membership"] == event.unsigned["prev_content"]?["membership"]
|
||||||
text:
|
? null
|
||||||
newContent?["formatted_body"] ??
|
: Message.system(
|
||||||
newContent?["body"] ??
|
metadata: {
|
||||||
content["formatted_body"] ??
|
...metadata,
|
||||||
content["body"] ??
|
"body":
|
||||||
"",
|
"${content["displayname"] ?? event.stateKey} ${switch (content["membership"]) {
|
||||||
replyToMessageId: replyId,
|
"invite" => "was invited to",
|
||||||
deliveredAt: config.event.timestamp,
|
"join" => "joined",
|
||||||
editedAt: editedAt,
|
"leave" => "left",
|
||||||
)
|
"knock" => "asked to join",
|
||||||
as TextMessage;
|
"ban" => "was banned from",
|
||||||
|
_ => "did something relating to",
|
||||||
return switch (type) {
|
}} the room.",
|
||||||
"m.room.encrypted" => asText.copyWith(
|
},
|
||||||
text: "Unable to decrypt message.",
|
id: config.event.eventId,
|
||||||
metadata: {...metadata, "body": "Unable to decrypt message."},
|
authorId: event.authorId,
|
||||||
),
|
deliveredAt: config.event.timestamp,
|
||||||
// "org.matrix.msc3381.poll.start" => Message.custom(
|
text:
|
||||||
// metadata: {
|
|
||||||
// ...metadata,
|
|
||||||
// "poll": event.parsedPollEventContent.pollStartContent,
|
|
||||||
// "responses": event.getPollResponses(timeline),
|
|
||||||
// },
|
|
||||||
// id: eventId,
|
|
||||||
// deliveredAt: originServerTs,
|
|
||||||
// authorId: senderId,
|
|
||||||
// ),
|
|
||||||
("m.sticker" || "m.room.message") => switch (content["msgtype"]) {
|
|
||||||
null || "m.image" => Message.image(
|
|
||||||
id: "${config.event.eventId}-image",
|
|
||||||
authorId: event.authorId,
|
|
||||||
source: source,
|
|
||||||
replyToMessageId: replyId,
|
|
||||||
metadata: metadata,
|
|
||||||
text: asText.text,
|
|
||||||
deliveredAt: config.event.timestamp,
|
|
||||||
blurhash: (content["info"] as Map?)?["xyz.amorgan.blurhash"],
|
|
||||||
),
|
|
||||||
"m.audio" || "m.file" => Message.file(
|
|
||||||
name: content["filename"].toString(),
|
|
||||||
size: content["info"]["size"],
|
|
||||||
metadata: metadata,
|
|
||||||
id: config.event.eventId,
|
|
||||||
authorId: event.authorId,
|
|
||||||
source: source,
|
|
||||||
replyToMessageId: replyId,
|
|
||||||
deliveredAt: config.event.timestamp,
|
|
||||||
),
|
|
||||||
_ => asText,
|
|
||||||
},
|
|
||||||
"m.room.member" =>
|
|
||||||
content["membership"] == event.unsigned["prev_content"]?["membership"]
|
|
||||||
? null
|
|
||||||
: Message.system(
|
|
||||||
metadata: {
|
|
||||||
...metadata,
|
|
||||||
"body":
|
|
||||||
"${content["displayname"] ?? event.stateKey} ${switch (content["membership"]) {
|
"${content["displayname"] ?? event.stateKey} ${switch (content["membership"]) {
|
||||||
"invite" => "was invited to",
|
"invite" => "was invited to",
|
||||||
"join" => "joined",
|
"join" => "joined",
|
||||||
|
|
@ -166,45 +185,35 @@ class MessageController extends AsyncNotifier<Message?> {
|
||||||
"ban" => "was banned from",
|
"ban" => "was banned from",
|
||||||
_ => "did something relating to",
|
_ => "did something relating to",
|
||||||
}} the room.",
|
}} the room.",
|
||||||
},
|
),
|
||||||
id: config.event.eventId,
|
|
||||||
authorId: event.authorId,
|
|
||||||
deliveredAt: config.event.timestamp,
|
|
||||||
text:
|
|
||||||
"${content["displayname"] ?? event.stateKey} ${switch (content["membership"]) {
|
|
||||||
"invite" => "was invited to",
|
|
||||||
"join" => "joined",
|
|
||||||
"leave" => "left",
|
|
||||||
"knock" => "asked to join",
|
|
||||||
"ban" => "was banned from",
|
|
||||||
_ => "did something relating to",
|
|
||||||
}} the room.",
|
|
||||||
),
|
|
||||||
|
|
||||||
"m.room.redaction" =>
|
"m.room.redaction" =>
|
||||||
config.alwaysReturn
|
config.alwaysReturn
|
||||||
? asText.copyWith(
|
? asText.copyWith(
|
||||||
metadata: {
|
metadata: {
|
||||||
...(asText.metadata ?? {}),
|
...(asText.metadata ?? {}),
|
||||||
"body": "Deleted Message",
|
"body": "Deleted Message",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
_ =>
|
_ =>
|
||||||
config.alwaysReturn
|
config.alwaysReturn
|
||||||
? asText
|
? asText
|
||||||
: (
|
: (
|
||||||
// Turn this on for debugging purposes
|
// Turn this on for debugging purposes
|
||||||
false
|
false
|
||||||
// ignore: dead_code
|
// ignore: dead_code
|
||||||
? Message.unsupported(
|
? Message.unsupported(
|
||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
id: config.event.eventId,
|
id: config.event.eventId,
|
||||||
authorId: event.authorId,
|
authorId: event.authorId,
|
||||||
replyToMessageId: replyId,
|
replyToMessageId: replyId,
|
||||||
)
|
)
|
||||||
: null),
|
: null),
|
||||||
};
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final provider = AsyncNotifierProvider.family
|
static final provider = AsyncNotifierProvider.family
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue