From 7c3ee0b49424854b6deab4071b63b8890dd9a455 Mon Sep 17 00:00:00 2001 From: Doug Date: Mon, 16 Dec 2024 14:20:25 +0000 Subject: [PATCH] Try prevent the zoom transition being upside down. --- .../MediaEventsTimelineFlowCoordinator.swift | 4 +++- .../TimelineMediaPreviewCoordinator.swift | 5 +++++ .../MediaEventsTimelineScreenModels.swift | 2 ++ .../MediaEventsTimelineScreenViewModel.swift | 10 +++++++++- .../View/MediaEventsTimelineScreen.swift | 13 +++++++++++-- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/ElementX/Sources/FlowCoordinators/MediaEventsTimelineFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/MediaEventsTimelineFlowCoordinator.swift index c76f97731f..1d2878d98d 100644 --- a/ElementX/Sources/FlowCoordinators/MediaEventsTimelineFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/MediaEventsTimelineFlowCoordinator.swift @@ -125,6 +125,8 @@ class MediaEventsTimelineFlowCoordinator: FlowCoordinatorProtocol { } .store(in: &cancellables) - navigationStackCoordinator.setFullScreenCoverCoordinator(coordinator) + navigationStackCoordinator.setFullScreenCoverCoordinator(coordinator) { + previewContext.completion?() + } } } diff --git a/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewCoordinator.swift b/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewCoordinator.swift index b6d0f073a0..2575108dbe 100644 --- a/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewCoordinator.swift +++ b/ElementX/Sources/Screens/FilePreviewScreen/TimelineMediaPreviewCoordinator.swift @@ -16,6 +16,11 @@ struct TimelineMediaPreviewContext { let viewModel: TimelineViewModelProtocol /// The namespace that the navigation transition's `sourceID` should be defined in. let namespace: Namespace.ID + /// A completion to be called immediately *after* the preview has been dismissed. + /// + /// This helps work around a bug caused by the flipped scrollview where the zoomed + /// thumbnail starts off upside down while loading the preview screen. + var completion: (() -> Void)? } struct TimelineMediaPreviewCoordinatorParameters { diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenModels.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenModels.swift index 81f7850743..38b12d8cbc 100644 --- a/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenModels.swift +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenModels.swift @@ -29,6 +29,8 @@ struct MediaEventsTimelineScreenViewState: BindableState { var activeTimelineContextProvider: (() -> TimelineViewModel.Context)! var bindings: MediaEventsTimelineScreenViewStateBindings + + var currentPreviewItemID: TimelineItemIdentifier? } struct MediaEventsTimelineScreenViewStateBindings { diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenViewModel.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenViewModel.swift index e272d5c5ae..09ede04cf1 100644 --- a/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenViewModel.swift +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/MediaEventsTimelineScreenViewModel.swift @@ -154,7 +154,15 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType return } - actionsSubject.send(.viewItem(.init(item: item, viewModel: activeTimelineViewModel, namespace: namespace))) + actionsSubject.send(.viewItem(.init(item: item, + viewModel: activeTimelineViewModel, + namespace: namespace, + completion: { [weak self] in + self?.state.currentPreviewItemID = nil + }))) + + // 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 { diff --git a/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/MediaEventsTimelineScreen.swift b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/MediaEventsTimelineScreen.swift index 5b59078286..d13523376a 100644 --- a/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/MediaEventsTimelineScreen.swift +++ b/ElementX/Sources/Screens/MediaEventsTimelineScreen/View/MediaEventsTimelineScreen.swift @@ -82,7 +82,7 @@ struct MediaEventsTimelineScreen: View { viewForTimelineItem(item) } .clipped() - .scaleEffect(.init(width: -1, height: -1)) + .scaleEffect(scale(for: item, isGridLayout: true)) } .zoomTransitionSource(id: item.identifier, in: zoomTransition) } @@ -109,7 +109,7 @@ struct MediaEventsTimelineScreen: View { tappedItem(item) } label: { viewForTimelineItem(item) - .scaleEffect(.init(width: 1, height: -1)) + .scaleEffect(scale(for: item, isGridLayout: false)) } .zoomTransitionSource(id: item.identifier, in: zoomTransition) } @@ -214,6 +214,15 @@ struct MediaEventsTimelineScreen: View { func tappedItem(_ item: RoomTimelineItemViewState) { context.send(viewAction: .tappedItem(item: item, namespace: zoomTransition)) } + + func scale(for item: RoomTimelineItemViewState, isGridLayout: Bool) -> CGSize { + guard item.identifier != context.viewState.currentPreviewItemID else { + // Remove the flip when presenting a preview so that the zoom transition is the right way up 🙃 + return CGSize(width: 1, height: 1) + } + + return CGSize(width: isGridLayout ? -1 : 1, height: -1) + } } // MARK: - Previews