diff --git a/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift b/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift index e416c1c0e..630568987 100644 --- a/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift +++ b/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift @@ -153,11 +153,11 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { class MediaPreviewItem: NSObject, QLPreviewItem { let file: MediaFileHandleProxy - var previewItemURL: URL? { + nonisolated var previewItemURL: URL? { // nonisolated as QuickLook can call from any thread (macOS 26). file.url } - let previewItemTitle: String? + nonisolated let previewItemTitle: String? // nonisolated as QuickLook can call from any thread (macOS 26). init(file: MediaFileHandleProxy, title: String?) { self.file = file diff --git a/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewDataSource.swift b/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewDataSource.swift index 78b55b9bb..fbd0f75f3 100644 --- a/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewDataSource.swift +++ b/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewDataSource.swift @@ -9,6 +9,7 @@ import Combine import Foundation import QuickLook +import Synchronization /// A dedicated data source for QLPreviewController to support timeline updates. This was added to /// workaround the fact that calling `reloadData` on the controller **always** reloads the current @@ -147,8 +148,14 @@ enum TimelineMediaPreviewItem: Equatable { /// Wraps a media file and title to be previewed with QuickLook. @Observable class Media: NSObject, QLPreviewItem, Identifiable { - fileprivate(set) var timelineItem: EventBasedMessageTimelineItemProtocol - var fileHandle: MediaFileHandleProxy? + fileprivate(set) var timelineItem: EventBasedMessageTimelineItemProtocol { + didSet { updatePreviewItemValues() } + } + + var fileHandle: MediaFileHandleProxy? { + didSet { updatePreviewItemValues() } + } + var downloadError: Error? init(timelineItem: EventBasedMessageTimelineItemProtocol) { @@ -184,15 +191,22 @@ enum TimelineMediaPreviewItem: Equatable { // MARK: QLPreviewItem - var previewItemURL: URL? { - fileHandle?.url + private let _previewItemURL = Mutex(nil) + nonisolated var previewItemURL: URL? { // nonisolated as QuickLook can call from any thread (macOS 26). + _previewItemURL.withLock { $0 } } - var previewItemTitle: String? { - switch fileHandle?.url { - case .some: filename - case .none: " " // Don't show any background text when the preview is still loading. - } + private let _previewItemTitle = Mutex(" ") + nonisolated var previewItemTitle: String? { // nonisolated as QuickLook can call from any thread (macOS 26). + _previewItemTitle.withLock { $0 } + } + + private func updatePreviewItemValues() { + let url = fileHandle?.url + _previewItemURL.withLock { $0 = url } + + // Don't show any background text (" ") while the preview is still loading. + _previewItemTitle.withLock { $0 = url == nil ? " " : filename } } // MARK: Event details diff --git a/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift b/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift index 476c67aaf..aaf26e467 100644 --- a/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift +++ b/ElementX/Sources/Screens/LogViewerScreen/View/LogViewerScreen.swift @@ -63,8 +63,8 @@ private struct PreviewView: UIViewControllerRepresentable { } private class PreviewItem: NSObject, QLPreviewItem { - var previewItemURL: URL? - var previewItemTitle: String? + nonisolated let previewItemURL: URL? // nonisolated as QuickLook can call from any thread (macOS 26). + nonisolated let previewItemTitle: String? // nonisolated as QuickLook can call from any thread (macOS 26). init(previewItemURL: URL?, previewItemTitle: String?) { self.previewItemURL = previewItemURL diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift index 25c1dfc56..3bb7f0e99 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift @@ -289,8 +289,8 @@ private struct PreviewView: UIViewControllerRepresentable { } private class PreviewItem: NSObject, QLPreviewItem { - var previewItemURL: URL? - var previewItemTitle: String? + nonisolated let previewItemURL: URL? // nonisolated as QuickLook can call from any thread (macOS 26). + nonisolated let previewItemTitle: String? // nonisolated as QuickLook can call from any thread (macOS 26). init(previewItemURL: URL?, previewItemTitle: String?) { self.previewItemURL = previewItemURL