Skip to content

Commit

Permalink
Add additional presentation modifier for SafariView (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
vsanthanam authored Mar 23, 2024
1 parent d05f53d commit 518296c
Show file tree
Hide file tree
Showing 9 changed files with 279 additions and 86 deletions.
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/nicklockwood/SwiftFormat",
"state" : {
"revision" : "507d63f6e890621f055397c9503bfc9468e8bcb6",
"version" : "0.51.15"
"revision" : "9e5d0d588ab6e271fe9887ec3dde21d544d4b080",
"version" : "0.53.5"
}
}
],
Expand Down
1 change: 1 addition & 0 deletions Sources/SafariUI/SafariUI.docc/SafariView.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ You can present a `SafariView` using the built-in presentation view modifiers:
- ``SwiftUI/View/safari(isPresented:url:onDismiss:)``
- ``SwiftUI/View/safari(item:onDismiss:safariView:)``
- ``SwiftUI/View/safari(item:id:onDismiss:safariView:)``
- ``SwiftUI/View/safari(url:onDismiss:)``

You can also use sheet presentation, or any other presentation mechanism of your choice.

Expand Down
1 change: 1 addition & 0 deletions Sources/SafariUI/SafariUI.docc/View.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ SwiftUI view modifiers used to configure a ``SafariView`` or a ``WebAuthenticati
- ``SwiftUI/View/safari(isPresented:url:onDismiss:)``
- ``SwiftUI/View/safari(item:onDismiss:safariView:)``
- ``SwiftUI/View/safari(item:id:onDismiss:safariView:)``
- ``SwiftUI/View/safari(url:onDismiss:)``

### SafarView Custom Activities

Expand Down
58 changes: 39 additions & 19 deletions Sources/SafariView/Modifiers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ public extension View {
/// - Parameter entersReaderIfAvailable: Whether or not the safari view should automatically enter reader mode if available.
/// - Returns: The modified view
func safariEntersReaderIfAvailable(_ entersReaderIfAvailable: Bool = true) -> some View {
let modifier = SafariViewEntersReaderIfAvailableModifier(entersReaderIfAvailable: entersReaderIfAvailable)
return ModifiedContent(content: self, modifier: modifier)
ModifiedContent(
content: self,
modifier: SafariViewEntersReaderIfAvailableModifier(entersReaderIfAvailable: entersReaderIfAvailable)
)
}

/// Set the bar collapsing behavior of safari views within this view
Expand All @@ -46,8 +48,10 @@ public extension View {
/// - Parameter barCollapsingEnabled: Whether or not bar collpasing should be enabled.
/// - Returns: The modified view
func safariBarCollapsingEnabled(_ barCollapsingEnabled: Bool = true) -> some View {
let modifier = SafariViewBarCollapsingEnabledModifier(barCollapsingEnabled: barCollapsingEnabled)
return ModifiedContent(content: self, modifier: modifier)
ModifiedContent(
content: self,
modifier: SafariViewBarCollapsingEnabledModifier(barCollapsingEnabled: barCollapsingEnabled)
)
}

/// Set the bar tint color of safari views within this view
Expand All @@ -57,8 +61,10 @@ public extension View {
/// - Parameter color: The color to use, or `nil` for the system default
/// - Returns: The modified view
func safariBarTintColor(_ color: Color?) -> some View {
let modifier = SafariViewBarTintColorModifier(safariViewBarTintColor: color)
return ModifiedContent(content: self, modifier: modifier)
ModifiedContent(
content: self,
modifier: SafariViewBarTintColorModifier(safariViewBarTintColor: color)
)
}

/// Set the control tint color of safari views within this view
Expand All @@ -68,8 +74,10 @@ public extension View {
/// - Parameter color: The color to use
/// - Returns: The modified view
func safariControlTintColor(_ color: Color) -> some View {
let modifier = SafariViewControlTintColorModifier(safariViewControlTintColor: color)
return ModifiedContent(content: self, modifier: modifier)
ModifiedContent(
content: self,
modifier: SafariViewControlTintColorModifier(safariViewControlTintColor: color)
)
}

/// Set the safari view's dismiss button style
Expand Down Expand Up @@ -107,8 +115,10 @@ public extension View {
/// - Parameter activities: The activities to include. You may use an array literal of `UIActivity` types.
/// - Returns: The modified content
func includedSafariActivities(_ activities: SafariView.IncludedActivities) -> some View {
let modifier = SafariViewIncludedActivitiesModifier(activities: activities)
return ModifiedContent(content: self, modifier: modifier)
ModifiedContent(
content: self,
modifier: SafariViewIncludedActivitiesModifier(activities: activities)
)
}

/// Conditionally include activities in the share sheet of safari views within this view.
Expand Down Expand Up @@ -138,9 +148,12 @@ public extension View {
/// - Parameter activities: Closure used to conditionally include activities
/// - Returns: The modified content
func includedSafariActivities(_ activities: @escaping (_ url: URL, _ pageTitle: String?) -> [UIActivity]) -> some View {
let activities = SafariView.IncludedActivities(activities)
let modifier = SafariViewIncludedActivitiesModifier(activities: activities)
return ModifiedContent(content: self, modifier: modifier)
ModifiedContent(
content: self,
modifier: SafariViewIncludedActivitiesModifier(
activities: .init(activities)
)
)
}

/// Exclude activity types from the share sheet of safari views within this view.
Expand All @@ -167,8 +180,10 @@ public extension View {
/// - Parameter activityTypes: The activity types to exclude. You may use an array literal of `UIActivity.ActivityType` values.
/// - Returns: The modified content
func excludedSafariActivityTypes(_ activityTypes: SafariView.ExcludedActivityTypes) -> some View {
let modifier = SafariViewExcludedActivityTypesModifier(activityTypes: activityTypes)
return ModifiedContent(content: self, modifier: modifier)
ModifiedContent(
content: self,
modifier: SafariViewExcludedActivityTypesModifier(activityTypes: activityTypes)
)
}

/// Conditionally exclude activity types from the share sheet of safari views within this view.
Expand Down Expand Up @@ -196,10 +211,15 @@ public extension View {
///
/// - Parameter activityTypes: Closure used to conditionally exclude activities
/// - Returns: The modified content
func excludedSafariActivityTypes(_ activityTypes: @escaping (_ url: URL, _ pageTitle: String?) -> [UIActivity.ActivityType]) -> some View {
let activityTypes = SafariView.ExcludedActivityTypes(activityTypes)
let modifier = SafariViewExcludedActivityTypesModifier(activityTypes: activityTypes)
return ModifiedContent(content: self, modifier: modifier)
func excludedSafariActivityTypes(
_ activityTypes: @escaping (_ url: URL, _ pageTitle: String?) -> [UIActivity.ActivityType]
) -> some View {
ModifiedContent(
content: self,
modifier: SafariViewExcludedActivityTypesModifier(
activityTypes: .init(activityTypes)
)
)
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,62 +86,6 @@ public extension View {
)
}

/// Presents a ``SafariView`` when a binding to a Boolean value that you provide is `true`.
///
/// Use this method when you want to present a ``SafariView`` to the user when a Boolean value you provide is true.
/// The example below displays a modal view of the mockup for a software license agreement when the user toggles the `isShowingSafari` variable by clicking or tapping on the “Show License Agreement” button:
///
/// ```swift
/// import Foundation
/// import SafariView
/// import SwiftUI
///
/// struct ShowLicenseAgreement: View {
///
/// let licenseAgreementURL: URL
///
/// @State private var isShowingSafari = false
///
/// var body: some View {
/// Button {
/// isShowingSafari.toggle()
/// } label: {
/// Text("Show License Agreement")
/// }
/// .safari(isPresented: $isShowingSafari,
/// url: licenseAgreementURL
/// onDismiss: didDismiss)
/// }
///
/// func didDismiss() {
/// // Handle the dismissing action.
/// }
///
/// }
/// ```
///
/// - Parameters:
/// - isPresented: A binding to a Boolean value that determines whether to present the ``SafariView`` that you create in the modifier’s content closure.
/// - url: The URL to load in the presented ``SafariView``
/// - onDismiss: The closure to execute when dismissing the ``SafariView``
/// - Returns: The modified view
func safari(
isPresented: Binding<Bool>,
url: URL,
onDismiss: (() -> Void)? = nil
) -> some View {
ModifiedContent(
content: self,
modifier: IsPresentedModifier(
isPresented: isPresented,
safariView: SafariView(
url: url
),
onDismiss: onDismiss
)
)
}

}

@available(iOS 14.0, macCatalyst 14.0, *)
Expand Down
118 changes: 118 additions & 0 deletions Sources/SafariView/Presentation/BoolURLPresentation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SafariUI
// BoolURLPresentation.swift
//
// MIT License
//
// Copyright (c) 2023 Varun Santhanam
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the Software), to deal
//
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation
import SwiftUI

@available(iOS 14.0, macCatalyst 14.0, *)
public extension View {

/// Presents a ``SafariView`` when a binding to a Boolean value that you provide is `true`.
///
/// Use this method when you want to present a ``SafariView`` to the user when a Boolean value you provide is true.
/// The example below displays a modal view of the mockup for a software license agreement when the user toggles the `isShowingSafari` variable by clicking or tapping on the “Show License Agreement” button:
///
/// ```swift
/// import Foundation
/// import SafariView
/// import SwiftUI
///
/// struct ShowLicenseAgreement: View {
///
/// let licenseAgreementURL: URL
///
/// @State private var isShowingSafari = false
///
/// var body: some View {
/// Button {
/// isShowingSafari.toggle()
/// } label: {
/// Text("Show License Agreement")
/// }
/// .safari(isPresented: $isShowingSafari,
/// url: licenseAgreementURL
/// onDismiss: didDismiss)
/// }
///
/// func didDismiss() {
/// // Handle the dismissing action.
/// }
///
/// }
/// ```
///
/// - Parameters:
/// - isPresented: A binding to a Boolean value that determines whether to present the ``SafariView`` that you create in the modifier’s content closure.
/// - url: The URL to load in the presented ``SafariView``
/// - onDismiss: The closure to execute when dismissing the ``SafariView``
/// - Returns: The modified view
func safari(
isPresented: Binding<Bool>,
url: URL,
onDismiss: (() -> Void)? = nil
) -> some View {
ModifiedContent(
content: self,
modifier: BoolURLPresentation(
isPresented: isPresented,
onDismiss: onDismiss,
url: url
)
)
}

}

@available(iOS 14.0, macCatalyst 14.0, *)
private struct BoolURLPresentation: ViewModifier {

init(
isPresented: Binding<Bool>,
onDismiss: (() -> Void)?,
url: URL
) {
_isPresented = isPresented
self.onDismiss = onDismiss
self.url = url
}

@MainActor
@ViewBuilder
func body(content: Content) -> some View {
content
.safari(
isPresented: $isPresented,
onDismiss: onDismiss
) {
SafariView(url: url)
}
}

@Binding
private var isPresented: Bool
private let onDismiss: (() -> Void)?
private let url: URL

}
File renamed without changes.
Loading

0 comments on commit 518296c

Please sign in to comment.