Skip to content

Commit

Permalink
Rework the presentation of the media browser quick look view to use S…
Browse files Browse the repository at this point in the history
…wiftUI. (#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.
  • Loading branch information
pixlwave authored Dec 16, 2024
1 parent 45a630d commit 3a82b88
Show file tree
Hide file tree
Showing 23 changed files with 593 additions and 473 deletions.
28 changes: 20 additions & 8 deletions ElementX.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ class MediaEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
coordinator.actions
.sink { [weak self] action in
switch action {
case .viewInRoomTimeline(let itemID):
self?.actionsSubject.send(.viewInRoomTimeline(itemID))
case .viewItem(let previewContext):
self?.presentMediaPreview(for: previewContext)
}
}
.store(in: &cancellables)
Expand All @@ -105,4 +105,28 @@ class MediaEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
self?.actionsSubject.send(.finished)
}
}

private func presentMediaPreview(for previewContext: TimelineMediaPreviewContext) {
let parameters = TimelineMediaPreviewCoordinatorParameters(context: previewContext,
mediaProvider: userSession.mediaProvider,
userIndicatorController: userIndicatorController)

let coordinator = TimelineMediaPreviewCoordinator(parameters: parameters)
coordinator.actionsPublisher
.sink { [weak self] action in
switch action {
case .viewInRoomTimeline(let itemID):
self?.navigationStackCoordinator.pop(animated: false)
self?.actionsSubject.send(.viewInRoomTimeline(itemID))
self?.navigationStackCoordinator.setFullScreenCoverCoordinator(nil)
case .dismiss:
self?.navigationStackCoordinator.setFullScreenCoverCoordinator(nil)
}
}
.store(in: &cancellables)

navigationStackCoordinator.setFullScreenCoverCoordinator(coordinator) {
previewContext.completion?()
}
}
}
4 changes: 2 additions & 2 deletions ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1583,8 +1583,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
MXLog.error("Unable to present room timeline for event \(itemID)")
return
}
stateMachine.tryEvent(.dismissMediaEventsTimeline)
stateMachine.tryEvent(.presentRoom(presentationAction: .eventFocus(.init(eventID: eventID, shouldSetPin: false))))
stateMachine.tryEvent(.presentRoom(presentationAction: .eventFocus(.init(eventID: eventID, shouldSetPin: false))),
userInfo: EventUserInfo(animated: false)) // No animation so the timeline visible when the preview animates away.
case .finished:
stateMachine.tryEvent(.dismissMediaEventsTimeline)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,24 @@ import SwiftUIIntrospect

extension PlatformViewVersionPredicate<TextFieldType, UITextField> {
static var supportedVersions: Self {
.iOS(.v16, .v17, .v18)
.iOS(.v17, .v18)
}
}

extension PlatformViewVersionPredicate<ScrollViewType, UIScrollView> {
static var supportedVersions: Self {
.iOS(.v16, .v17, .v18)
.iOS(.v17, .v18)
}
}

extension PlatformViewVersionPredicate<ViewControllerType, UIViewController> {
static var supportedVersions: Self {
.iOS(.v16, .v17, .v18)
.iOS(.v17, .v18)
}
}

extension PlatformViewVersionPredicate<NavigationStackType, UINavigationController> {
static var supportedVersions: Self {
.iOS(.v17, .v18)
}
}
30 changes: 30 additions & 0 deletions ElementX/Sources/Other/SwiftUI/Animation/ZoomTransition.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// Copyright 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
//

import SwiftUI

extension View {
/// A convenience modifier to conditionally apply `.navigationTransition(.zoom(…))` when available.
@ViewBuilder
func zoomTransition(sourceID: some Hashable, in namespace: Namespace.ID) -> some View {
if #available(iOS 18.0, *) {
navigationTransition(.zoom(sourceID: sourceID, in: namespace))
} else {
self
}
}

/// A convenience modifier to conditionally apply `.matchedTransitionSource(…)` when available.
@ViewBuilder
func zoomTransitionSource(id: some Hashable, in namespace: Namespace.ID) -> some View {
if #available(iOS 18.0, *) {
matchedTransitionSource(id: id, in: namespace)
} else {
self
}
}
}
22 changes: 22 additions & 0 deletions ElementX/Sources/Other/SwiftUI/Views/BlurEffectView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// Copyright 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
//

import SwiftUI

/// A view that renders a `UIBlurEffect` as there is a larger range of
/// effects available compared to using SwiftUI's `Material` type.
struct BlurEffectView: UIViewRepresentable {
var style: UIBlurEffect.Style

func makeUIView(context: Context) -> UIVisualEffectView {
UIVisualEffectView(effect: UIBlurEffect(style: style))
}

func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
uiView.effect = UIBlurEffect(style: style)
}
}
1 change: 0 additions & 1 deletion ElementX/Sources/Screens/CallScreen/View/CallScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ struct CallScreen: View {
Image(systemSymbol: .chevronBackward)
.fontWeight(.semibold)
}
// .padding(.leading, -8) // Fixes the button alignment, but harder to tap.
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//
// Copyright 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
//

import Foundation

This file was deleted.

Loading

0 comments on commit 3a82b88

Please sign in to comment.