From d3bb07ae440df8534745bfe8928d7d6df4fe005f Mon Sep 17 00:00:00 2001 From: Varun Santhanam Date: Sat, 6 Apr 2024 09:35:40 -0700 Subject: [PATCH] Add presentation style argument to item presentation modifiers (#43) --- .../Presentation/ItemPresentation.swift | 44 ++++++++++++++++++- .../Presentation/URLPresentation.swift | 7 +++ .../WrappedItemPresentation.swift | 11 ++++- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/Sources/SafariView/Presentation/ItemPresentation.swift b/Sources/SafariView/Presentation/ItemPresentation.swift index daeb2369c..2727dff3f 100644 --- a/Sources/SafariView/Presentation/ItemPresentation.swift +++ b/Sources/SafariView/Presentation/ItemPresentation.swift @@ -82,11 +82,13 @@ public extension View { /// /// - Parameters: /// - item: A binding to an optional source of truth for the ``SafariView``. When item is non-nil, the system passes the item’s content to the modifier’s closure. You display this content in a ``SafariView`` that you create that the system displays to the user. If item changes, the system dismisses the ``SafariView`` and replaces it with a new one using the same process. + /// - presentationStyle: The ``SafariView/PresentationStyle`` used to present the ``SafariView``. /// - onDismiss: The closure to execute when dismissing the ``SafariView`` /// - safariView: A closure that returns the ``SafariView`` to present /// - Returns: The modified view func safari( item: Binding, + presentationStyle: SafariView.PresentationStyle = .default, onDismiss: (() -> Void)? = nil, safariView: @escaping (Item) -> SafariView ) -> some View where Item: Identifiable { @@ -94,6 +96,7 @@ public extension View { content: self, modifier: ItemModifier( item: item, + presentationStyle: presentationStyle, safariView: safariView ) ) @@ -107,10 +110,12 @@ private struct ItemModifier: ViewModifier where Item: Identifiable { init( item: Binding, + presentationStyle: SafariView.PresentationStyle, safariView: @escaping (Item) -> SafariView, onDismiss: (() -> Void)? = nil ) { _item = item + self.presentationStyle = presentationStyle self.safariView = safariView self.onDismiss = onDismiss } @@ -124,6 +129,7 @@ private struct ItemModifier: ViewModifier where Item: Identifiable { .background( Presenter( item: $item, + presentationStyle: presentationStyle, safariView: safariView, onDismiss: onDismiss ) @@ -138,10 +144,12 @@ private struct ItemModifier: ViewModifier where Item: Identifiable { init( item: Binding, + presentationStyle: SafariView.PresentationStyle, safariView: @escaping (Item) -> SafariView, onDismiss: (() -> Void)? ) { _item = item + self.presentationStyle = presentationStyle self.safariView = safariView self.onDismiss = onDismiss } @@ -156,11 +164,13 @@ private struct ItemModifier: ViewModifier where Item: Identifiable { init( item: Item? = nil, + presentationStyle: SafariView.PresentationStyle, safariView: @escaping (Item) -> SafariView, bindingSetter: @escaping (Item?) -> Void, onDismiss: (() -> Void)? ) { self.item = item + self.presentationStyle = presentationStyle self.safariView = safariView self.bindingSetter = bindingSetter self.onDismiss = onDismiss @@ -238,6 +248,7 @@ private struct ItemModifier: ViewModifier where Item: Identifiable { // MARK: - Private private weak var safariViewController: SFSafariViewController? + private let presentationStyle: SafariView.PresentationStyle private let safariView: (Item) -> SafariView private var bindingSetter: (Item?) -> Void private var onInitialLoad: ((Bool) -> Void)? @@ -259,6 +270,14 @@ private struct ItemModifier: ViewModifier where Item: Identifiable { vc.preferredBarTintColor = barTintColor.map(UIColor.init) vc.preferredControlTintColor = UIColor(controlTintColor) vc.dismissButtonStyle = dismissButtonStyle.uikit + switch presentationStyle { + case .standard: + break + case .formSheet: + vc.modalPresentationStyle = .formSheet + case .pageSheet: + vc.modalPresentationStyle = .pageSheet + } guard let presenting = view.controller else { bindingSetter(nil) return @@ -296,6 +315,8 @@ private struct ItemModifier: ViewModifier where Item: Identifiable { func makeCoordinator() -> Coordinator { .init( + item: item, + presentationStyle: presentationStyle, safariView: safariView, bindingSetter: { newValue in item = newValue }, onDismiss: onDismiss @@ -303,10 +324,27 @@ private struct ItemModifier: ViewModifier where Item: Identifiable { } func makeUIView(context: Context) -> UIViewType { - context.coordinator.view + context.coordinator.entersReaderIfAvailable = entersReaderIfAvailable + context.coordinator.barCollapsingEnabled = barCollapsingEnabled + context.coordinator.barTintColor = barTintColor + context.coordinator.controlTintColor = controlTintColor + context.coordinator.dismissButtonStyle = dismissButtonStyle + context.coordinator.includedActivities = includedActivities + context.coordinator.excludedActivityTypes = excludedActivityTypes + context.coordinator.item = item + return context.coordinator.view } - func updateUIView(_ uiView: UIViewType, context: Context) {} + func updateUIView(_ uiView: UIViewType, context: Context) { + context.coordinator.entersReaderIfAvailable = entersReaderIfAvailable + context.coordinator.barCollapsingEnabled = barCollapsingEnabled + context.coordinator.barTintColor = barTintColor + context.coordinator.controlTintColor = controlTintColor + context.coordinator.dismissButtonStyle = dismissButtonStyle + context.coordinator.includedActivities = includedActivities + context.coordinator.excludedActivityTypes = excludedActivityTypes + context.coordinator.item = item + } // MARK: - Private @@ -334,6 +372,7 @@ private struct ItemModifier: ViewModifier where Item: Identifiable { @Environment(\.safariViewExcludedActivityTypes) private var excludedActivityTypes: SafariView.ExcludedActivityTypes + private let presentationStyle: SafariView.PresentationStyle private let safariView: (Item) -> SafariView private let onDismiss: (() -> Void)? @@ -342,6 +381,7 @@ private struct ItemModifier: ViewModifier where Item: Identifiable { @Binding private var item: Item? + private let presentationStyle: SafariView.PresentationStyle private let safariView: (Item) -> SafariView private let onDismiss: (() -> Void)? diff --git a/Sources/SafariView/Presentation/URLPresentation.swift b/Sources/SafariView/Presentation/URLPresentation.swift index d0d525cb6..d0a66a2b7 100644 --- a/Sources/SafariView/Presentation/URLPresentation.swift +++ b/Sources/SafariView/Presentation/URLPresentation.swift @@ -61,16 +61,19 @@ public extension View { /// ``` /// - Parameters: /// - url: The URL used to load the view + /// - presentationStyle: The ``SafariView/PresentationStyle`` used to present the ``SafariView``. /// - onDismiss: The closure to execute when dismissing the ``SafariView`` /// - Returns: The modified view func safari( url: Binding, + presentationStyle: SafariView.PresentationStyle = .default, onDismiss: (() -> Void)? = nil ) -> some View { ModifiedContent( content: self, modifier: URLPresentation( url: url, + presentationStyle: presentationStyle, onDismiss: onDismiss ) ) @@ -82,9 +85,11 @@ private struct URLPresentation: ViewModifier { init( url: Binding, + presentationStyle: SafariView.PresentationStyle, onDismiss: (() -> Void)? ) { _url = url + self.presentationStyle = presentationStyle self.onDismiss = onDismiss } @@ -95,6 +100,7 @@ private struct URLPresentation: ViewModifier { .safari( item: $url, id: \.hashValue, + presentationStyle: presentationStyle, onDismiss: onDismiss ) { url in SafariView(url: url) @@ -103,6 +109,7 @@ private struct URLPresentation: ViewModifier { @Binding private var url: URL? + private let presentationStyle: SafariView.PresentationStyle private let onDismiss: (() -> Void)? } diff --git a/Sources/SafariView/Presentation/WrappedItemPresentation.swift b/Sources/SafariView/Presentation/WrappedItemPresentation.swift index f88c3c9e3..60b69097b 100644 --- a/Sources/SafariView/Presentation/WrappedItemPresentation.swift +++ b/Sources/SafariView/Presentation/WrappedItemPresentation.swift @@ -80,12 +80,14 @@ public extension View { /// - Parameters: /// - item: A binding to an optional source of truth for the ``SafariView``. When item is non-nil, the system passes the item’s content to the modifier’s closure. You display this content in a ``SafariView`` that you create that the system displays to the user. If item changes, the system dismisses the ``SafariView`` and replaces it with a new one using the same process. /// - id: A keypath used to generate stable identifier for instances of Item. + /// - presentationStyle: The ``SafariView/PresentationStyle`` used to present the ``SafariView``. /// - onDismiss: The closure to execute when dismissing the ``SafariView`` /// - safariView: A closure that returns the ``SafariView`` to present /// - Returns: The modified view func safari( item: Binding, id: KeyPath, + presentationStyle: SafariView.PresentationStyle = .default, onDismiss: (() -> Void)? = nil, safariView: @escaping (Item) -> SafariView ) -> some View where ID: Hashable { @@ -94,6 +96,7 @@ public extension View { modifier: WrappedItemPresentation( item: item, id: id, + presentationStyle: presentationStyle, onDismiss: onDismiss, safariView: safariView ) @@ -109,11 +112,13 @@ private struct WrappedItemPresentation: ViewModifier where ID: Hashabl init( item: Binding, id: KeyPath, + presentationStyle: SafariView.PresentationStyle, onDismiss: (() -> Void)? = nil, safariView: @escaping (Item) -> SafariView ) { _item = item self.id = id + self.presentationStyle = presentationStyle self.onDismiss = onDismiss self.safariView = safariView } @@ -124,7 +129,10 @@ private struct WrappedItemPresentation: ViewModifier where ID: Hashabl @ViewBuilder func body(content: Content) -> some View { content - .safari(item: wrappedItem) { item in + .safari( + item: wrappedItem, + presentationStyle: presentationStyle + ) { item in safariView(item.value) } } @@ -134,6 +142,7 @@ private struct WrappedItemPresentation: ViewModifier where ID: Hashabl @Binding private var item: Item? private let id: KeyPath + private let presentationStyle: SafariView.PresentationStyle private let onDismiss: (() -> Void)? private let safariView: (Item) -> SafariView