All Projects → stleamist → Bettersafariview

stleamist / Bettersafariview

Licence: mit
A better way to present a SFSafariViewController or start a ASWebAuthenticationSession in SwiftUI.

Programming Languages

swift
15916 projects

Labels

Projects that are alternatives of or similar to Bettersafariview

Octotree
Browser extension that enhances GitHub code review and exploration. You can download Octotree for your browser from our website.
Stars: ✭ 21,726 (+20591.43%)
Mutual labels:  safari
Adguardforios
The most advanced ad blocker for iOS
Stars: ✭ 812 (+673.33%)
Mutual labels:  safari
Automator
Various Automator and AppleScript workflow and scripts for simplifying life
Stars: ✭ 68 (-35.24%)
Mutual labels:  safari
React Native Safari View
A React Native wrapper for Safari View Controller.
Stars: ✭ 475 (+352.38%)
Mutual labels:  safari
Etaoin
Pure Clojure Webdriver protocol implementation
Stars: ✭ 599 (+470.48%)
Mutual labels:  safari
Rainbowsafari
🌈 Hide sticky headers and color the menu bar on Safari for Yosemite
Stars: ✭ 54 (-48.57%)
Mutual labels:  safari
Uicollectionview Layouts Kit
📐 A set of custom layouts for UICollectionView with examples [Swift 5.3, iOS 12].
Stars: ✭ 410 (+290.48%)
Mutual labels:  safari
Known Css Properties
List of standard and browser specific CSS properties.
Stars: ✭ 89 (-15.24%)
Mutual labels:  safari
React Native Inappbrowser
📱InAppBrowser for React Native (Android & iOS) 🤘
Stars: ✭ 624 (+494.29%)
Mutual labels:  safari
Pass For Macos
macOS wrapper for pass, the standard UNIX password manager
Stars: ✭ 62 (-40.95%)
Mutual labels:  safari
Safariautologintest
A demo showing how you can auto-login users to an iOS app using SafariViewController (on iOS 9) and SFAuthenticationSession (on iOS 11)
Stars: ✭ 480 (+357.14%)
Mutual labels:  safari
Safari2aria
safari extension for use aria2 to replace safari default download
Stars: ✭ 563 (+436.19%)
Mutual labels:  safari
Applescripts
My collection of AppleScripts created/acquired over the years. This repo is designed to provide useful AppleScripts for others and as a general resource for AppleScript education.
Stars: ✭ 56 (-46.67%)
Mutual labels:  safari
Browsertime
Your browser, your page, your scripts!
Stars: ✭ 474 (+351.43%)
Mutual labels:  safari
Freedom
The Freedom to Open URLs in Third-Party Browsers on iOS with Custom UIActivity Subclasses.
Stars: ✭ 85 (-19.05%)
Mutual labels:  safari
Pwa Bugs
🚔 List of PWA Bugs and workarounds
Stars: ✭ 444 (+322.86%)
Mutual labels:  safari
Select Like A Boss For Safari
Extension for Safari that allows you to select text inside links.
Stars: ✭ 30 (-71.43%)
Mutual labels:  safari
Pushy
A Java library for sending APNs (iOS/macOS/Safari) push notifications
Stars: ✭ 1,353 (+1188.57%)
Mutual labels:  safari
Histools
A collection of tools for generating data visualizations from browser history data
Stars: ✭ 87 (-17.14%)
Mutual labels:  safari
Ublock
uBlock: a fast, lightweight, and lean blocker for Chrome, Firefox, and Safari.
Stars: ✭ 8,075 (+7590.48%)
Mutual labels:  safari

version Swift: 5.1+ iOS: 13.0+ macOS: 10.15+ watchOS: 6.2+
Build on Xcode SwiftPM: compatible license contact: @stleamist

BetterSafariView

A better way to present a SFSafariViewController or start a ASWebAuthenticationSession in SwiftUI.

Contents

Motivation

SwiftUI is a strong, intuitive way to build user interfaces, but was released with some part of existing elements missing. One example of those missing elements is the SFSafariViewController.

Fortunately, Apple provides a way to wrap UIKit elements into SwiftUI views. A common approach to place the SFSafariViewController inside SwiftUI is to create a simple view representing a SFSafariViewController, then present it with a sheet(isPresented:onDismiss:content:) modifier or a NavigationLink button (See RootView.swift in the demo project).

However, there’s a problem in this approach: it can’t present the SFSafariViewController with its default presentation style — a push transition covers full screen. A sheet modifier can present the view only in a modal sheet, and a navigation link shows the two navigation bars at the top so we have to deal with them. This comes down to the conclusion that there’s no option to present it the right way except for using present(_:animated:completion:) method of a UIViewController instance, but it is prohibited and not a good design to access the UIHostingController directly from the SwiftUI view.

BetterSafariView clearly achieves this goal by hosting a simple UIViewController to present a SFSafariViewController as a view’s background. In this way, a ASWebAuthenticationSession is also able to be started without any issue in SwiftUI.

Requirements

  • Xcode 11.0+
  • Swift 5.1+

SafariView

  • iOS 13.0+
  • Mac Catalyst 13.0+

WebAuthenticationSession

  • iOS 13.0+
  • Mac Catalyst 13.0+
  • macOS 10.15+
  • watchOS 6.2+

Usage

With the following modifiers, you can use it in a similar way to present a sheet.

SafariView

Example

import SwiftUI
import BetterSafariView

struct ContentView: View {
    
    @State private var presentingSafariView = false
    
    var body: some View {
        Button(action: {
            self.presentingSafariView = true
        }) {
            Text("Present SafariView")
        }
        .safariView(isPresented: $presentingSafariView) {
            SafariView(
                url: URL(string: "https://github.com/")!,
                configuration: SafariView.Configuration(
                    entersReaderIfAvailable: false,
                    barCollapsingEnabled: true
                )
            )
            .preferredBarAccentColor(.clear)
            .preferredControlAccentColor(.accentColor)
            .dismissButtonStyle(.done)
        }
    }
}

View Modifiers

safariView(isPresented:onDismiss:content:)
/// Presents a Safari view when a given condition is true.
func safariView(
    isPresented: Binding<Bool>,
    onDismiss: (() -> Void)? = nil,
    content: @escaping () -> SafariView
) -> some View
safariView(item:onDismiss:content:)
/// Presents a Safari view using the given item as a data source for the `SafariView` to present.
func safariView<Item: Identifiable>(
    item: Binding<Item?>,
    onDismiss: (() -> Void)? = nil,
    content: @escaping (Item) -> SafariView
) -> some View

SafariView Initializers

init(url:)
/// Creates a Safari view that loads the specified URL.
init(url: URL)
init(url:configuration:)
/// Creates and configures a Safari view that loads the specified URL.
init(url: URL, configuration: SafariView.Configuration)

SafariView Modifiers

preferredBarAccentColor(_:)
/// Sets the accent color for the background of the navigation bar and the toolbar.
func preferredBarAccentColor(_ color: Color?) -> SafariView
preferredControlAccentColor(_:)
/// Sets the accent color for the control buttons on the navigation bar and the toolbar.
func preferredControlAccentColor(_ color: Color?) -> SafariView
dismissButtonStyle(_:)
/// Sets the style of dismiss button to use in the navigation bar to close `SafariView`.
func dismissButtonStyle(_ style: SafariView.DismissButtonStyle) -> SafariView

WebAuthenticationSession

Example

import SwiftUI
import BetterSafariView

struct ContentView: View {
    
    @State private var startingWebAuthenticationSession = false
    
    var body: some View {
        Button(action: {
            self.startingWebAuthenticationSession = true
        }) {
            Text("Start WebAuthenticationSession")
        }
        .webAuthenticationSession(isPresented: $startingWebAuthenticationSession) {
            WebAuthenticationSession(
                url: URL(string: "https://github.com/login/oauth/authorize")!,
                callbackURLScheme: "github"
            ) { callbackURL, error in
                print(callbackURL, error)
            }
            .prefersEphemeralWebBrowserSession(false)
        }
    }
}

View Modifiers

webAuthenticationSession(isPresented:content:)
/// Starts a web authentication session when a given condition is true.
func webAuthenticationSession(
    isPresented: Binding<Bool>,
    content: @escaping () -> WebAuthenticationSession
) -> some View
webAuthenticationSession(item:content:)
/// Starts a web authentication session using the given item as a data source for the `WebAuthenticationSession` to start.
func webAuthenticationSession<Item: Identifiable>(
    item: Binding<Item?>,
    content: @escaping (Item) -> WebAuthenticationSession
) -> some View

WebAuthenticationSession Initializers

init(url:callbackURLScheme:completionHandler:)
/// Creates a web authentication session instance.
init(
    url: URL,
    callbackURLScheme: String?,
    completionHandler: @escaping (URL?, Error?) -> Void
)
init(url:callbackURLScheme:onCompletion:)
/// Creates a web authentication session instance.
init(
    url: URL,
    callbackURLScheme: String?,
    onCompletion: @escaping (Result<URL, Error>) -> Void
)

WebAuthenticationSession Modifier

prefersEphemeralWebBrowserSession(_:)
/// Configures whether the session should ask the browser for a private authentication session.
func prefersEphemeralWebBrowserSession(_ prefersEphemeralWebBrowserSession: Bool) -> WebAuthenticationSession

Known Issues

  • In .webAuthenticationSession(item:content:) modifier, the functionality that replaces a session on the item's identity change is not implemented, as there is no non-hacky way to be notified when the session's dismissal animation is completed.

Installation

Swift Package Manager

Add the following line to the dependencies in your Package.swift file:

.package(url: "https://github.com/stleamist/BetterSafariView.git", .upToNextMajor(from: "2.3.1"))

Next, add BetterSafariView as a dependency for your targets:

.target(name: "MyTarget", dependencies: ["BetterSafariView"])

Your completed description may look like this:

// swift-tools-version:5.1

import PackageDescription

let package = Package(
    name: "MyPackage",
    dependencies: [
        .package(url: "https://github.com/stleamist/BetterSafariView.git", .upToNextMajor(from: "2.3.1"))
    ],
    targets: [
        .target(name: "MyTarget", dependencies: ["BetterSafariView"])
    ]
)

Xcode

Select File > Swift Packages > Add Package Dependency, then enter the following URL:

https://github.com/stleamist/BetterSafariView.git

For more details, see Adding Package Dependencies to Your App.

Demo

You can see how it works on each platform and compare it with the other naive implementations in the demo project. Check out the demo app by opening BetterSafariView.xcworkspace.

NOTE: This demo project is available for iOS 14.0+, macOS 11.0+, and watchOS 7.0+, while the package is compatible with iOS 13.0+, macOS 10.15+, and watchOS 6.2+.

License

BetterSafariView is released under the MIT license. See LICENSE for details.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].