krz/rune

an ios client for njalla

clone: git clone https://gitbay.org/krz/rune.git

v1.2.0: Rune/App/RuneApp.swift · raw

 1import SwiftUI
 2
 3@main
 4struct RuneApp: App {
 5    var body: some Scene {
 6        WindowGroup {
 7            RootView()
 8        }
 9    }
10}
11
12private struct RootView: View {
13    @StateObject private var settingsViewModel = SettingsViewModel()
14    @StateObject private var domainViewModel = DomainViewModel()
15    @StateObject private var tokenViewModel = TokenViewModel()
16    @StateObject private var walletViewModel = WalletViewModel()
17    @State private var selectedTab = 0
18
19    var body: some View {
20        TabView(selection: $selectedTab) {
21            DomainListView(viewModel: domainViewModel, client: settingsViewModel.client)
22                .tabItem {
23                    Label("Domains", systemImage: "globe")
24                }
25                .tag(0)
26
27            TokenListView(viewModel: tokenViewModel, client: settingsViewModel.client) { deletedTokenKey in
28                do {
29                    let didLogout = try settingsViewModel.logoutIfCurrentTokenDeleted(deletedTokenKey)
30                    if didLogout {
31                        selectedTab = 0
32                    }
33                } catch {
34                    settingsViewModel.errorMessage = error.localizedDescription
35                }
36            }
37                .tabItem {
38                    Label("Tokens", systemImage: "key.horizontal")
39                }
40                .tag(1)
41
42            SettingsView(viewModel: settingsViewModel, walletViewModel: walletViewModel) {
43                domainViewModel.reset()
44                tokenViewModel.reset()
45                walletViewModel.reset()
46                selectedTab = 0
47            }
48            .tabItem {
49                Label("Settings", systemImage: "gearshape")
50            }
51            .tag(2)
52        }
53        .task {
54            await settingsViewModel.bootstrap()
55            await syncAuthenticatedState()
56        }
57        .onChange(of: settingsViewModel.client) { _, _ in
58            Task {
59                await syncAuthenticatedState()
60            }
61        }
62        .fullScreenCover(isPresented: onboardingBinding) {
63            OnboardingView(viewModel: settingsViewModel)
64        }
65    }
66
67    private func syncAuthenticatedState() async {
68        guard let client = settingsViewModel.client else {
69            domainViewModel.reset()
70            tokenViewModel.reset()
71            walletViewModel.reset()
72            selectedTab = 0
73            return
74        }
75
76        await domainViewModel.loadDomains(client: client)
77        await tokenViewModel.loadTokens(client: client)
78    }
79
80    private var onboardingBinding: Binding<Bool> {
81        Binding(
82            get: { settingsViewModel.requiresOnboarding },
83            set: { _ in }
84        )
85    }
86}