added the strings for the pin banner, the room list and the notification content builder

This commit is contained in:
Mauro Romito
2026-07-30 16:13:03 +02:00
committed by Mauro
parent 9a1db7e664
commit d7127562d7
2 changed files with 44 additions and 1 deletions
@@ -66,7 +66,7 @@ nonisolated struct RoomMessageEventStringBuilder {
message = AttributedString(content.body)
}
case .gallery(let content):
message = AttributedString(content.body)
message = buildGalleryMessage(for: style, content: content)
case .other(_, let body):
message = AttributedString(body)
}
@@ -91,6 +91,21 @@ nonisolated struct RoomMessageEventStringBuilder {
}
}
/// A gallery's body is its caption. Notifications fall back to counting the attachments when
/// there isn't one, whilst elsewhere it is treated as any other media's caption.
private func buildGalleryMessage(for style: Style, content: GalleryMessageContent) -> AttributedString {
switch style {
case .plain:
if content.body.isBlank {
AttributedString(L10n.notificationGalleryBody(content.itemtypes.count))
} else {
AttributedString(content.body)
}
case .senderPrefixed, .typeBolded:
buildMessage(for: style, caption: content.body, type: L10n.commonGallery)
}
}
private func buildMessage(for style: Style, caption: String?, type: String) -> AttributedString {
guard let caption else {
return AttributedString(type)
@@ -207,6 +207,13 @@ nonisolated struct NotificationContentBuilder {
using: mediaProvider,
mediaSource: .init(source: content.source,
mimeType: content.info?.mimetype))
case .gallery(content: let content):
// A notification can only show one attachment, so the gallery is represented by its first.
if let mediaSource = content.itemtypes.firstPreviewableMediaSource {
await addMediaAttachment(notificationContent: &notificationContent,
using: mediaProvider,
mediaSource: mediaSource)
}
default:
break
}
@@ -362,3 +369,24 @@ private nonisolated struct NotificationIcon {
groupInfo != nil
}
}
private nonisolated extension [GalleryItemType] {
/// The media source of the first attachment that a notification is able to show, skipping the
/// types that it can't such as documents.
var firstPreviewableMediaSource: MediaSourceProxy? {
for itemType in self {
switch itemType {
case .image(let content):
return .init(source: content.source, mimeType: content.info?.mimetype)
case .video(let content):
return .init(source: content.source, mimeType: content.info?.mimetype)
case .audio(let content):
return .init(source: content.source, mimeType: content.info?.mimetype)
case .file, .other:
continue
}
}
return nil
}
}