Open a full-screen preview when tapping a gallery item

Tapping a gallery tile/row opens the existing media preview scoped to that gallery's attachments, paging between them. Introduces a typed MediaPreviewItemID (replacing the stringly-typed preview identifier) and a gallery-scoped TimelineMediaPreviewDataSource; the tap routes through TimelineInteractionHandler/TimelineViewModel. Non-previewable (.other) items are skipped without shifting the tapped index.

Co-authored-by: svetoslav.mitov <svetoslav.mitov@sportinno.com>

just use id instead of previewID

removed horrible multiline ternary

pr suggestions

remove redundant code

remove empty caption display + gallery uses the appropriate media timeline actions
This commit is contained in:
Mauro Romito
2026-07-27 19:14:23 +02:00
committed by Mauro
parent b4f397ed6a
commit 7ea9aeb174
15 changed files with 343 additions and 112 deletions
@@ -227,6 +227,7 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
case .file: .file
case .image: .image
case .video: .video
case .gallery: .gallery
}
}
@@ -26,6 +26,7 @@ enum TimelineControllerAction {
}
case displayMediaPreview(item: EventBasedMessageTimelineItemProtocol, timelineViewModel: TimelineViewModelKind)
case displayGalleryPreview(galleryItem: GalleryRoomTimelineItem, initialIndex: Int)
case displayLocation(StaticLocationData)
case displayLiveLocation(sender: TimelineItemSender, initialLiveLocationShare: LiveLocationShare)
case none
@@ -36,7 +36,7 @@ nonisolated extension EventBasedMessageTimelineItemProtocol {
}
var hasMediaCaption: Bool {
mediaCaption != nil
mediaCaption?.isBlank == false
}
var mediaCaption: String? {
@@ -111,6 +111,16 @@ nonisolated enum GalleryItem: Hashable, Identifiable {
}
}
var fileSize: UInt? {
switch self {
case .image(_, let content): content.imageInfo.fileSize
case .video(_, let content): content.videoInfo.fileSize
case .audio(_, let content): content.fileSize
case .file(_, let content): content.fileSize
case .other: nil
}
}
var blurhash: String? {
switch self {
case .image(_, let content): content.blurhash
@@ -41,7 +41,7 @@ enum TimelineFocus {
}
enum TimelineAllowedMessageType {
case audio, file, image, video
case audio, file, image, video, gallery
}
enum TimelineProxyError: Error {