diff --git a/Sources/SafariView/Environment.swift b/Sources/SafariView/EnvironmentValues.swift similarity index 73% rename from Sources/SafariView/Environment.swift rename to Sources/SafariView/EnvironmentValues.swift index 06296cf68..10335547f 100644 --- a/Sources/SafariView/Environment.swift +++ b/Sources/SafariView/EnvironmentValues.swift @@ -1,5 +1,5 @@ // SafariView -// Environment.swift +// EnvironmentValues.swift // // MIT License // @@ -27,12 +27,37 @@ import SwiftUI public extension EnvironmentValues { + /// The configuration used for ``SafariView`` + /// + /// You can retrieve this value for the currnet scope using the @Environment property wrapper + /// + /// ```swift + /// struct MyView: View { + /// + /// @Environment(\.safariViewConfiguration) + /// var safariViewConriguration + /// + /// } + /// ``` + /// + /// This property is equivelent to `SFSafariViewController`'s `.preferredControlTintColor` property var safariViewConfiguration: SafariView.Configuration { get { self[SafariViewConfigurationEnvironmentKey.self] } set { self[SafariViewConfigurationEnvironmentKey.self] = newValue } } - /// Apply a control tint color to the view + /// The control tint color used for ``SafariView`` + /// + /// You can retrieve this value for the currnet scope using the @Environment property wrapper + /// + /// ```swift + /// struct MyView: View { + /// + /// @Environment(\.safariViewControlTintColor) + /// var safariControlTintColor + /// + /// } + /// ``` /// /// This property is equivelent to `SFSafariViewController`'s `.preferredControlTintColor` property var safariViewControlTintColor: Color { @@ -40,7 +65,16 @@ public extension EnvironmentValues { set { self[SafariViewControlTintColorEnvironmentKey.self] = newValue } } - /// Apply an bar tint color to the view + /// The bar tint color used for ``SafariView`` + /// + /// You can retrieve this value for the currnet scope using the @Environment property wrapper + /// + /// ```swift + /// struct MyView: View { + /// @Environment(\.safariViewControlBarColor) + /// var safariBarTintColor + /// } + /// ``` /// /// This property is equivelent to `SFSafariViewController`'s `.preferredBarTintColor` property var safariViewBarTintColor: Color? { @@ -50,6 +84,17 @@ public extension EnvironmentValues { /// Set the safari view's dismiss button style /// + /// You can retrieve this value for the currnet scope using the @Environment property wrapper + /// + /// ```swift + /// struct MyView: View { + /// + /// @Environment(\.safariViewDismissButtonStyle) + /// var safariViewDismissButtonStyle + /// + /// } + /// ``` + /// /// This property is equivelent to `SFSafariViewController`'s `.dismissButtonStyle` property var safariViewDismissButtonStyle: SafariView.DismissButtonStyle { get { self[SafariViewDismissButtonStyleEnvironmentKey.self] } diff --git a/Sources/SafariView/ExcludedActivityTypes.swift b/Sources/SafariView/ExcludedActivityTypes.swift index 738d1a8f8..6a054a996 100644 --- a/Sources/SafariView/ExcludedActivityTypes.swift +++ b/Sources/SafariView/ExcludedActivityTypes.swift @@ -28,6 +28,7 @@ import UIKit public extension SafariView { + /// A struct used to exclude activity types from a SafariView struct ExcludedActivityTypes: ExpressibleByArrayLiteral { public init(_ excludedActivityTypes: @escaping (URL, String?) -> [UIActivity.ActivityType]) { @@ -40,12 +41,6 @@ public extension SafariView { // MARK: - API - public static let `default`: ExcludedActivityTypes = .init() - - public func callAsFunction(url: URL, pageTitle: String?) -> [UIActivity.ActivityType] { - excludedActivityTypes(url, pageTitle) - } - public static func + (lhs: ExcludedActivityTypes, rhs: ExcludedActivityTypes) -> ExcludedActivityTypes { .init { url, pageTitle in lhs(url: url, pageTitle: pageTitle) + rhs(url: url, pageTitle: pageTitle) @@ -60,11 +55,13 @@ public extension SafariView { self.init { _, _ in elements } } - // MARK: - Sequence + // MARK: - Private - public typealias Element = UIActivity.ActivityType + static let `default`: ExcludedActivityTypes = .init() - // MARK: - Private + func callAsFunction(url: URL, pageTitle: String?) -> [UIActivity.ActivityType] { + excludedActivityTypes(url, pageTitle) + } private let excludedActivityTypes: (URL, String?) -> [UIActivity.ActivityType] diff --git a/Sources/SafariView/IncludedActivities.swift b/Sources/SafariView/IncludedActivities.swift index e86eba823..a6f983eb5 100644 --- a/Sources/SafariView/IncludedActivities.swift +++ b/Sources/SafariView/IncludedActivities.swift @@ -36,14 +36,12 @@ public extension SafariView { self.includedActivities = includedActivities } - // MARK: - API - - public static let `default`: IncludedActivities = .init { _, _ in [] } - - public func callAsFunction(url: URL, pageTitle: String?) -> [UIActivity] { - includedActivities(url, pageTitle) + public init(_ includedActivities: [UIActivity]) { + self.includedActivities = { _, _ in includedActivities } } + // MARK: - API + public static func + (lhs: IncludedActivities, rhs: IncludedActivities) -> IncludedActivities { .init { url, pageTitle in lhs(url: url, pageTitle: pageTitle) + rhs(url: url, pageTitle: pageTitle) @@ -60,6 +58,12 @@ public extension SafariView { // MARK: - Private + static let `default`: IncludedActivities = .init() + + func callAsFunction(url: URL, pageTitle: String?) -> [UIActivity] { + includedActivities(url, pageTitle) + } + private let includedActivities: (_ url: URL, _ pageTitle: String?) -> [UIActivity] } diff --git a/Sources/SafariView/Modifiers.swift b/Sources/SafariView/Modifiers.swift index 3d8b79d07..d42f83e05 100644 --- a/Sources/SafariView/Modifiers.swift +++ b/Sources/SafariView/Modifiers.swift @@ -37,6 +37,19 @@ public extension View { /// Set the bar tint color of safari views within this view /// + /// Use this modifier to set the bar tint color of safari views within this view: + /// + /// ```swift + /// struct MyView: View { + /// var body: some View { + /// HStack { + /// SafariView(url: URL("https://www.apple.com")!) + /// } + /// .safariBarTintColor(Color.purple) + /// } + /// } + /// ``` + /// /// This modifier is the equivelent of the [`.preferredBarTintColor`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/2274394-preferredbartintcolor) property of a [`SFSafariViewController`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) /// - Parameter color: The color to use, or `nil` for the system default /// - Returns: The modified view diff --git a/Sources/SafariView/SafariView.docc/Environment.md b/Sources/SafariView/SafariView.docc/Environment.md new file mode 100644 index 000000000..d33f34bac --- /dev/null +++ b/Sources/SafariView/SafariView.docc/Environment.md @@ -0,0 +1,16 @@ +# ``SafariView/SwiftUI/EnvironmentValues`` + +Enviornment Values + +Some Documentation About Environment Values + +## Topics + +### Values + +- ``safariViewConfiguration`` +- ``safariViewBarTintColor`` +- ``safariViewControlTintColor`` +- ``safariViewDismissButtonStyle`` +- ``safariViewIncludedActivities`` +- ``safariViewExcludedActivityTypes`` diff --git a/Sources/SafariView/SafariView.docc/Modifiers.md b/Sources/SafariView/SafariView.docc/Modifiers.md new file mode 100644 index 000000000..0cc3d5170 --- /dev/null +++ b/Sources/SafariView/SafariView.docc/Modifiers.md @@ -0,0 +1,28 @@ +# ``SafariView/SwiftUI/View`` + +View modifiers used configure and present Safari Views. + +Some Content About View Modifiers + +## Topics + +### Configuration + +- ``safariConfiguration(_:)`` +- ``safariBarTintColor(_:)`` +- ``safariControlTintColor(_:)`` +- ``safariDismissButtonStyle(_:)`` + +### Presentation + +- ``safari(isPresented:onDismiss:safariView:)`` +- ``safari(url:onDismiss:safariView:)`` +- ``safari(item:onDismiss:safariView:)`` +- ``safari(item:id:onDismiss:safariView:)`` + +### Activities + +- ``includedSafariActivities(_:)-362lz`` +- ``includedSafariActivities(_:)-2u8l9`` +- ``excludedSafariActivityTypes(_:)-1v8zq`` +- ``excludedSafariActivityTypes(_:)-tvrg`` diff --git a/Sources/SafariView/SafariView.docc/SafariView.md b/Sources/SafariView/SafariView.docc/SafariView.md index f1ca1093a..97c940ee8 100644 --- a/Sources/SafariView/SafariView.docc/SafariView.md +++ b/Sources/SafariView/SafariView.docc/SafariView.md @@ -4,48 +4,30 @@ SafariServices in SwiftUI ## Overview -SafariView is a SwiftUI wrapper around [`SFSafariViewController`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) You can present a `SafariView` using our provided view modifiers: - -Using a `Binding`: - -```swift -extension View { - func safari( - isPresented: Binding, - onDismiss: (() -> Void)? = nil, - @ViewBuilder safariView: @escaping () -> SafariView - ) -> some View -} -``` - -Using a `Binding`: - -```swift -extension View { - func safari(url: Binding, - onDismiss: (() -> Void)? = nil, - safariView: @escaping (URL) -> SafariView) -> some View -} -``` - -Using a generic `Binding`: - -```swift -extension View { - func safari( - url: Binding, - onDismiss: (() -> Void)? = nil, - @ViewBuilder safariView: @escaping (URL) -> SafariView - ) -> some View -} -``` - -Alternatively, you can use sheet presentation or any other presentation mechanism of your choosing. - -The library contains a single `View`-conforming struct, also named `SafariView`, as well as several view modifiers used to control the appearance and behavior of a ``SafariView/SafariView`` +`SafariView` is a wrapper around [`SFSafariViewController`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) for use within SwiftUI applications. The view includes Safari features such as Reader, AutoFill, Fraudulent Website Detection, and content blocking. The user's activity and interaction with `SafariView` are not visible to your app, which cannot access AutoFill data, browsing history, or website data. You do not need to secure data between your app and Safari. If you would like to share data between your app and Safari, so it is easier for a user to log in only one time, use [`ASWebAuthenticationSession`](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) instead. + +- Important: In accordance with [App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/), this view must be used to visibly present information to users; the view may not be hidden or obscured by other views or layers. Additionally, an app may not use `SafariView` to track users without their knowledge and consent. + +UI features include the following: +- A read-only address field with a security indicator and a Reader button +- An Action button that invokes an activity view controller offering custom services from your app, and activities, such as messaging, from the system and other extensions +- A Done button, back and forward navigation buttons, and a button to open the page directly in Safari +- On devices that support 3D Touch, automatic Peek and Pop for links and detected data + +To learn about 3D Touch, see [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/) and [Adopting 3D Touch on iPhone](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/Adopting3DTouchOniPhone/index.html#//apple_ref/doc/uid/TP40016543). + +The library contains a single `View`-conforming struct, also named `SafariView`, as well as several view modifiers used to control the appearance, behavior and presentation of a ``SafariView/SafariView`` ## Topics ### Views -- ``SafariView/SafariView`` +- ``SafariView`` + +### Modifiers + +- ``SwiftUI/View`` + +### Environment + +- ``SwiftUI/EnvironmentValues`` diff --git a/Sources/SafariView/SafariView.docc/View.md b/Sources/SafariView/SafariView.docc/View.md index 73eb4c7cf..e4b444162 100644 --- a/Sources/SafariView/SafariView.docc/View.md +++ b/Sources/SafariView/SafariView.docc/View.md @@ -4,48 +4,6 @@ @DocumentationExtension(mergeBehavior: append) } -A `SafariView` is a wrapper around [`SFSafariViewController`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) for use within SwiftUI applications. The view includes Safari features such as Reader, AutoFill, Fraudulent Website Detection, and content blocking. The user's activity and interaction with `SafariView` are not visible to your app, which cannot access AutoFill data, browsing history, or website data. You do not need to secure data between your app and Safari. If you would like to share data between your app and Safari, so it is easier for a user to log in only one time, use [`ASWebAuthenticationSession`](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) instead. - -- Important: In accordance with [App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/), this view must be used to visibly present information to users; the view may not be hidden or obscured by other views or layers. Additionally, an app may not use `SafariView` to track users without their knowledge and consent. - -UI features include the following: -- A read-only address field with a security indicator and a Reader button -- An Action button that invokes an activity view controller offering custom services from your app, and activities, such as messaging, from the system and other extensions -- A Done button, back and forward navigation buttons, and a button to open the page directly in Safari -- On devices that support 3D Touch, automatic Peek and Pop for links and detected data - -To learn about 3D Touch, see [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/) and [Adopting 3D Touch on iPhone](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/Adopting3DTouchOniPhone/index.html#//apple_ref/doc/uid/TP40016543). - -You can present a `SafariView` using one of our provided view modifiers, like so: - -```swift -import Foundation -import SafariView -import SwiftUI - -struct ShowLicenseAgreement: View { - - let licenseAgreementURL: URL - - @State private var isShowingSafari = false - - var body: some View { - Button(action: { - isShowingSafari.toggle() - }) { - Text("Show License Agreement") - } - .safari(isPresented: $isShowingSafari, - onDismiss: didDismiss) { - SafariView(url: licenseAgreementURL) - } - } - -} -``` - -You can also use sheet presentation, or any other presentation mechanism of your choice. - ## Topics ### Creating a Safari View @@ -54,26 +12,16 @@ You can also use sheet presentation, or any other presentation mechanism of your ### Configuring the View - -- ``SwiftUI/View/safariConfiguration(_:)`` - ``Configuration`` - ``ActivityButton`` -- ``SwiftUI/View/safariBarTintColor(_:)`` -- ``SwiftUI/View/safariControlTintColor(_:)`` -- ``SwiftUI/View/safariDismissButtonStyle(_:)`` - ``DismissButtonStyle`` ### Custom Activities -- ``SwiftUI/View/includedSafariActivities(_:)-362lz`` -- ``SwiftUI/View/includedSafariActivities(_:)-2u8l9`` - ``IncludedActivities`` -- ``SwiftUI/View/excludedSafariActivityTypes(_:)-1v8zq`` -- ``SwiftUI/View/excludedSafariActivityTypes(_:)-tvrg`` - ``ExcludedActivityTypes`` ### Connection Prewarming - ``prewarmConnections(to:)`` - ``PrewarmingToken`` - diff --git a/Sources/SafariView/SafariView.swift b/Sources/SafariView/SafariView.swift index d423767d1..d37b032f9 100644 --- a/Sources/SafariView/SafariView.swift +++ b/Sources/SafariView/SafariView.swift @@ -53,15 +53,23 @@ public struct SafariView: View { // MARK: - API /// A convenience typealias for [`SFSafariViewController.DismissButtonStyle`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/dismissbuttonstyle) + /// + /// To change the configuration for the current scope, see the ``SwiftUI/View/safariConfiguration(_:)`` view modifier. public typealias DismissButtonStyle = SFSafariViewController.DismissButtonStyle /// A convenience typealias for [`SFSafariViewController.ActivityButton`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/activitybutton) + /// + /// To change the configuration for the current scope, see the ``SwiftUI/View/safariConfiguration(_:)`` view modifier. public typealias ActivityButton = SFSafariViewController.ActivityButton /// A convenience typealias for [`SFSafariViewController.PrewarmingToken`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller/prewarmingtoken) + /// + /// You can generate prewarming tokens for invalidation using the ``prewarmConnections(to:)`` static method. public typealias PrewarmingToken = SFSafariViewController.PrewarmingToken /// The configuration for a ``SafariView/SafariView`` + /// + /// To change the configuration for the current scope, see the ``SwiftUI/View/safariConfiguration(_:)`` view modifier. public struct Configuration { /// Create a configuration for a ``SafariView/SafariView``