Search code examples
swiftswiftuivisionos

How do I skip my login window if I already have a token?


I'm working on a visionOS app in Swift UI. Currently I have a login window that I want to keep small before opening to the much larger main app. I do this by having two WindowGroups and closing the current window in LoginView() after login is complete.

Issue is I want to skip the login WindowGroup if the user already has an auth token (I store it in keychain). Looking it up there doesn't seem to be any way of controlling which window gets picked on start in swiftUI other than initial order. I could check if the token already exists in LoginView and close the window right after opening but that seems like it could cause a poor user experience.

Any help would be appreciated.

import SwiftUI

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup (id: "Login"){
                LoginView().frame(
                    minWidth: 100, maxWidth: 400,
                    minHeight: 100, maxHeight: 400)
        }.windowResizability(.contentSize)
        WindowGroup (id: "Home"){
            HomeView()
        }
        .windowStyle(.plain)
    }
}


Solution

  • Ended up solving this by reworking how my windows happen.

    Instead of using two WindowGroups with separate windowing properties, use one and use a function to programmatically switch which view is in that group. By using .windowResizability(.contentSize) we can make it so that the window changes size according to view content. We then put frames inside on all of our top level views to choose what window size we want.

    @main
    struct MyApp: App {
        @State var loginComplete = false
        
        var body: some Scene {
                computedView()
            }
        func computedView() -> some Scene {
            WindowGroup {
                if authTokenExists() ||  loginComplete {
                    HomeView()
                } else {
                    LoginView(loginComplete: $loginComplete)
                }
            }
            .windowStyle(.plain)
            .windowResizability(.contentSize)
        }
        func authTokenExists() -> Bool {
            let query: [String: Any] = [
                kSecClass as String: kSecClassGenericPassword,
                kSecAttrService as String: "MyAppAuthToken", // Unique identifier for your app
                kSecReturnData as String: true,
                kSecMatchLimit as String: kSecMatchLimitOne
            ]
            
            var item: CFTypeRef?
            let status = SecItemCopyMatching(query as CFDictionary, &item)
            
            return status == errSecSuccess
    
        }
    }