Surface refused media deletions in the affected chat

A refused delete/clear (journal write failure, reservation conflict,
path collision, capacity) only logged SecureLogger.error, so a wedged
/clear looked like success. Refusals now post a localized system
message (content.system.media_delete_refused, 30 locales) into the
affected private chat via the existing system-message mechanism, wired
at both the per-bubble delete and /clear refusal sites.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jack
2026-07-26 14:15:38 +02:00
co-authored by Claude Opus 4.8
parent d2e5afd6e7
commit e49cb2f59f
5 changed files with 90 additions and 5 deletions
+19 -5
View File
@@ -1272,9 +1272,13 @@ struct ChatViewModelPrivateMediaDeletionTests {
"images/incoming/\(filename)"
]]
)
let messages = viewModel.privateChats[peerID] ?? []
#expect(messages.prefix(2).map(\.id) == [stableID, legacyID])
// The refusal is surfaced in the affected chat, not just logged.
#expect(messages.last?.sender == "system")
#expect(
viewModel.privateChats[peerID]?.map(\.id)
== [stableID, legacyID]
messages.last?.content
== String(localized: "content.system.media_delete_refused")
)
}
@@ -1374,10 +1378,17 @@ struct ChatViewModelPrivateMediaDeletionTests {
#expect(
transport.deletedPrivateMediaMessageIDBatches == [[incomingID]]
)
let messages = viewModel.privateChats[peerID] ?? []
#expect(
viewModel.privateChats[peerID]?.map(\.id)
messages.prefix(3).map(\.id)
== [incomingID, outgoingID, "ordinary-message"]
)
// The refused /clear is surfaced in the affected chat.
#expect(messages.last?.sender == "system")
#expect(
messages.last?.content
== String(localized: "content.system.media_delete_refused")
)
#expect(transport.cancelledTransfers == ["failed-clear-outgoing"])
#expect(viewModel.messageIDToTransferId[outgoingID] == nil)
}
@@ -1446,9 +1457,12 @@ struct ChatViewModelPrivateMediaDeletionTests {
transport.deletedPrivateMediaRelativePaths
== [[incomingID: "images/incoming/\(filename)"]]
)
let messages = viewModel.privateChats[peerID] ?? []
#expect(messages.prefix(2).map(\.id) == [incomingID, outgoingID])
#expect(messages.last?.sender == "system")
#expect(
viewModel.privateChats[peerID]?.map(\.id)
== [incomingID, outgoingID]
messages.last?.content
== String(localized: "content.system.media_delete_refused")
)
}