Surface failed reactions as a send failure on their message

A reaction that fails to send can now block the room's send queue, but the
timeline only surfaced failures for the item itself, its edit or its
redaction. EventTimelineItemProxy.pendingSend now also falls back to our
first failed reaction, targeting it with SendTarget.reaction(key:), so the
message shows the red exclamation mark and the sending failed alert can
retry or remove it.

In-flight reactions are deliberately ignored so reacting doesn't flash a
sending indicator on the message.
This commit is contained in:
Stefan Ceriu
2026-09-30 13:57:03 +03:00
parent 4c71cae0f5
commit a87d65b05a
@@ -107,7 +107,7 @@ final nonisolated class EventTimelineItemProxy: Sendable {
}
}
/// The item's own pending send or, when it has already gone out, our pending edit or redaction of it.
/// The item's own pending send or, when it has already gone out, our pending edit, redaction or failed reaction on it.
var pendingSend: (target: SendTarget, state: EventSendState)? {
if let state = item.localSendState {
(.event, state)
@@ -115,11 +115,25 @@ final nonisolated class EventTimelineItemProxy: Sendable {
(.edit, state)
} else if let state = item.redactionSendState {
(.redaction, state)
} else if let (key, state) = failedReaction {
(.reaction(key: key), state)
} else {
nil
}
}
/// Only failed reactions are surfaced as they block the send queue, in-flight ones would flash a sending indicator on every tap.
private var failedReaction: (key: String, state: EventSendState)? {
for reaction in item.reactions {
for sender in reaction.senders {
if let state = sender.sendState, case .sendingFailed = state {
return (reaction.key, state)
}
}
}
return nil
}
var canBeRepliedTo: Bool {
item.canBeRepliedTo
}