diff --git a/IceCubesApp/App/SafariRouter.swift b/IceCubesApp/App/SafariRouter.swift index b860a21b..9faef5c0 100644 --- a/IceCubesApp/App/SafariRouter.swift +++ b/IceCubesApp/App/SafariRouter.swift @@ -3,6 +3,7 @@ import Env import Observation import SafariServices import SwiftUI +import Models extension View { @MainActor func withSafariRouter() -> some View { @@ -26,7 +27,7 @@ private struct SafariRouter: ViewModifier { }) .onOpenURL { url in // Open external URL (from icecubesapp://) - let urlString = url.absoluteString.replacingOccurrences(of: "icecubesapp://", with: "https://") + let urlString = url.absoluteString.replacingOccurrences(of: AppInfo.scheme, with: "https://") guard let url = URL(string: urlString), url.host != nil else { return } _ = routerPath.handle(url: url) } diff --git a/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift b/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift index 346952a0..b9efcd08 100644 --- a/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift +++ b/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift @@ -1,4 +1,5 @@ import AppAccount +import AuthenticationServices import Combine import DesignSystem import Env @@ -27,7 +28,6 @@ struct AddAccountView: View { @State private var signInClient: Client? @State private var instances: [InstanceSocial] = [] @State private var instanceFetchError: LocalizedStringKey? - @State private var oauthURL: URL? private let instanceNamePublisher = PassthroughSubject() @@ -136,21 +136,6 @@ struct AddAccountView: View { break } } - .onOpenURL(perform: { url in - Task { - await continueSignIn(url: url) - } - }) - .onChange(of: oauthURL) { _, newValue in - if newValue == nil { - isSigninIn = false - } - } - #if !targetEnvironment(macCatalyst) - .sheet(item: $oauthURL, content: { url in - SafariView(url: url) - }) - #endif } } @@ -233,11 +218,19 @@ struct AddAccountView: View { do { signInClient = .init(server: sanitizedName) if let oauthURL = try await signInClient?.oauthURL() { -#if targetEnvironment(macCatalyst) - openURL(oauthURL) -#else - self.oauthURL = oauthURL -#endif + let session = ASWebAuthenticationSession(url: oauthURL, + callbackURLScheme: AppInfo.scheme.replacingOccurrences(of: "://", with: "")) + { callbackURL, error in + if let callbackURL { + Task { + await continueSignIn(url: callbackURL) + } + } else { + isSigninIn = false + } + } + session.presentationContextProvider = SceneDelegate.authViewController + session.start() } else { isSigninIn = false } @@ -252,7 +245,6 @@ struct AddAccountView: View { return } do { - oauthURL = nil let oauthToken = try await client.continueOauthFlow(url: url) let client = Client(server: client.server, oauthToken: oauthToken) let account: Account = try await client.get(endpoint: Accounts.verifyCredentials) @@ -266,7 +258,6 @@ struct AddAccountView: View { isSigninIn = false dismiss() } catch { - oauthURL = nil isSigninIn = false } } diff --git a/Packages/DesignSystem/Sources/DesignSystem/SceneDelegate.swift b/Packages/DesignSystem/Sources/DesignSystem/SceneDelegate.swift index 61419be5..c6c8b32a 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/SceneDelegate.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/SceneDelegate.swift @@ -1,4 +1,5 @@ import Combine +import AuthenticationServices import UIKit @Observable @@ -6,6 +7,9 @@ public class SceneDelegate: NSObject, UIWindowSceneDelegate, Sendable { public var window: UIWindow? public private(set) var windowWidth: CGFloat = UIScreen.main.bounds.size.width public private(set) var windowHeight: CGFloat = UIScreen.main.bounds.size.height + + public static var globalPresentationAnchor: ASPresentationAnchor? = nil + public static var authViewController = AuthViewController() public func scene(_ scene: UIScene, willConnectTo _: UISceneSession, @@ -13,6 +17,8 @@ public class SceneDelegate: NSObject, UIWindowSceneDelegate, Sendable { { guard let windowScene = scene as? UIWindowScene else { return } window = windowScene.keyWindow + + Self.globalPresentationAnchor = window #if targetEnvironment(macCatalyst) if let titlebar = windowScene.titlebar { @@ -54,3 +60,9 @@ public class SceneDelegate: NSObject, UIWindowSceneDelegate, Sendable { } } } + +public class AuthViewController: UIViewController, ASWebAuthenticationPresentationContextProviding { + public func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { + return SceneDelegate.globalPresentationAnchor ?? ASPresentationAnchor() + } +}