Rework the presentation of the media browser quick look view to use SwiftUI. (#3619)

* Embed the media preview quick look inside a full screen cover

With a zoom transition on iOS 18.

* Use a the representable coordinator properly.

* Fix a bug with the toolbar appearance.

* Format

* Try prevent the zoom transition being upside down.

* Fix the snapshot test configuration.
This commit is contained in:
Doug
2024-12-16 15:27:50 +00:00
committed by GitHub
parent 45a630dd85
commit 3a82b88859
23 changed files with 593 additions and 473 deletions
@@ -84,8 +84,8 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
backPaginateIfNecessary(paginationStatus: activeTimelineViewModel.context.viewState.timelineState.paginationState.backward)
case .oldestItemDidDisappear:
isOldestItemVisible = false
case .tappedItem(let item):
handleItemTapped(item)
case .tappedItem(let item, let namespace):
handleItemTapped(item, namespace: namespace)
}
}
@@ -140,7 +140,7 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
}
}
private func handleItemTapped(_ item: RoomTimelineItemViewState) {
private func handleItemTapped(_ item: RoomTimelineItemViewState, namespace: Namespace.ID) {
let item: EventBasedMessageTimelineItemProtocol? = switch item.type {
case .audio(let audioItem): audioItem
case .file(let fileItem): fileItem
@@ -149,31 +149,20 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
default: nil
}
guard let item, let mediaProvider = context.mediaProvider else {
MXLog.error("Unexpected item type (or the media provider is missing).")
guard let item else {
MXLog.error("Unexpected item type tapped.")
return
}
let viewModel = TimelineMediaPreviewViewModel(initialItem: item,
timelineViewModel: activeTimelineViewModel,
mediaProvider: mediaProvider,
userIndicatorController: userIndicatorController)
actionsSubject.send(.viewItem(.init(item: item,
viewModel: activeTimelineViewModel,
namespace: namespace,
completion: { [weak self] in
self?.state.currentPreviewItemID = nil
})))
mediaPreviewCancellable = viewModel.actions
.sink { [weak self] action in
guard let self else { return }
switch action {
case .viewInRoomTimeline(let itemID):
state.bindings.mediaPreviewViewModel = nil
actionsSubject.send(.viewInRoomTimeline(itemID))
case .dismiss:
state.bindings.mediaPreviewViewModel = nil
case .loadedMediaFile:
break // Handled by the preview controller
}
}
state.bindings.mediaPreviewViewModel = viewModel
// Set the current item in the next run loop so that (hopefully) the presentation will be ready before we flip the thumbnail.
Task { state.currentPreviewItemID = item.id }
}
private func titleForDate(_ date: Date) -> String {