diff --git a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift index 1f909688bb..ad3a4fb75c 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/LoadableImage.swift @@ -11,11 +11,11 @@ import Kingfisher import SwiftUI /// Used to configure animations -enum LoadableImageMediaType { +enum LoadableImageMediaType: Equatable { /// An avatar (can be displayed anywhere within the app). case avatar /// An image displayed in the timeline. - case timelineItem + case timelineItem(uniqueID: String) /// Any other media (can be displayed anywhere within the app). case generic } @@ -77,9 +77,19 @@ struct LoadableImage: View { mediaProvider: mediaProvider, transformer: transformer, placeholder: placeholder) + .id(stableMediaIdentifier) + } + + private var stableMediaIdentifier: String { + switch mediaType { + case .timelineItem(let uniqueID): + // Consider media for the same item to be the same view + uniqueID + default: // Binds the lifecycle of the LoadableImage to the associated URL. // This fixes the problem of the cache returning old values after a change in the URL. - .id(mediaSource.url) + mediaSource.url.absoluteString + } } } @@ -309,33 +319,33 @@ struct LoadableImage_Previews: PreviewProvider, TestablePreview { static var previews: some View { LazyVGrid(columns: [.init(.adaptive(minimum: 110, maximum: 110))], spacing: 24) { LoadableImage(url: "mxc://wherever/1234", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), mediaProvider: mediaProvider, placeholder: placeholder) .layout(title: "Loaded") LoadableImage(url: "mxc://wherever/2345", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), blurhash: "KpE4oyayR5|GbHb];3j@of", mediaProvider: mediaProvider, placeholder: placeholder) .layout(title: "Hidden (blurhash)", hideTimelineMedia: true) LoadableImage(url: "mxc://wherever/3456", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), mediaProvider: mediaProvider, placeholder: placeholder) .layout(title: "Hidden (placeholder)", hideTimelineMedia: true) LoadableImage(url: "mxc://wherever/4567", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), blurhash: "KbLM^j]q$jT|EfR-3rtjXk", mediaProvider: loadingMediaProvider, placeholder: placeholder) .layout(title: "Loading (blurhash)") LoadableImage(url: "mxc://wherever/5678", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), mediaProvider: loadingMediaProvider, placeholder: placeholder) .layout(title: "Loading (placeholder)") @@ -347,7 +357,7 @@ struct LoadableImage_Previews: PreviewProvider, TestablePreview { .layout(title: "Loading (avatar)") LoadableImage(url: "mxc://wherever/345", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), blurhash: "KbLM^j]q$jT|EfR-3rtjXk", mediaProvider: mediaProvider, transformer: transformer, @@ -355,7 +365,7 @@ struct LoadableImage_Previews: PreviewProvider, TestablePreview { .layout(title: "Loaded (transformer)") LoadableImage(url: "mxc://wherever/345", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), blurhash: "KbLM^j]q$jT|EfR-3rtjXk", mediaProvider: loadingMediaProvider, transformer: transformer, @@ -363,7 +373,7 @@ struct LoadableImage_Previews: PreviewProvider, TestablePreview { .layout(title: "Loading (transformer)") LoadableImage(url: "mxc://wherever/234", - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: "id"), blurhash: "KbLM^j]q$jT|EfR-3rtjXk", mediaProvider: mediaProvider, transformer: transformer, diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift index beb06037db..53bd61704b 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/ImageRoomTimelineView.swift @@ -41,7 +41,7 @@ struct ImageRoomTimelineView: View { private var loadableImage: some View { if timelineItem.content.contentType == .gif { LoadableImage(mediaSource: timelineItem.content.imageInfo.source, - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.content.blurhash, size: timelineItem.content.imageInfo.size, mediaProvider: context.mediaProvider) { @@ -50,7 +50,7 @@ struct ImageRoomTimelineView: View { .timelineMediaFrame(imageInfo: timelineItem.content.imageInfo) } else { LoadableImage(mediaSource: timelineItem.content.thumbnailInfo?.source ?? timelineItem.content.imageInfo.source, - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.content.blurhash, size: timelineItem.content.thumbnailInfo?.size ?? timelineItem.content.imageInfo.size, mediaProvider: context.mediaProvider) { diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift index 2763bb1313..b411148670 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/StickerRoomTimelineView.swift @@ -15,7 +15,7 @@ struct StickerRoomTimelineView: View { var body: some View { TimelineStyler(timelineItem: timelineItem) { LoadableImage(mediaSource: timelineItem.imageInfo.source, - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.blurhash, size: timelineItem.imageInfo.size, mediaProvider: context.mediaProvider) { diff --git a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift index d64d93c284..030b584998 100644 --- a/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift +++ b/ElementX/Sources/Screens/Timeline/View/TimelineItemViews/VideoRoomTimelineView.swift @@ -42,7 +42,7 @@ struct VideoRoomTimelineView: View { var thumbnail: some View { if let thumbnailSource = timelineItem.content.thumbnailInfo?.source { LoadableImage(mediaSource: thumbnailSource, - mediaType: .timelineItem, + mediaType: .timelineItem(uniqueID: timelineItem.id.uniqueID.id), blurhash: timelineItem.content.blurhash, size: timelineItem.content.thumbnailInfo?.size, mediaProvider: context.mediaProvider) { imageView in