krz/rune
an ios client for njalla
clone: git clone https://gitbay.org/krz/rune.git
v1.0.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 @State private var selectedTab = 0
17
18 var body: some View {
19 TabView(selection: $selectedTab) {
20 DomainListView(viewModel: domainViewModel, client: settingsViewModel.client)
21 .tabItem {
22 Label("Domains", systemImage: "globe")
23 }
24 .tag(0)
25
26 TokenListView(viewModel: tokenViewModel, client: settingsViewModel.client) { deletedTokenKey in
27 do {
28 let didLogout = try settingsViewModel.logoutIfCurrentTokenDeleted(deletedTokenKey)
29 if didLogout {
30 selectedTab = 0
31 }
32 } catch {
33 settingsViewModel.errorMessage = error.localizedDescription
34 }
35 }
36 .tabItem {
37 Label("Tokens", systemImage: "key.horizontal")
38 }
39 .tag(1)
40
41 SettingsView(viewModel: settingsViewModel) {
42 domainViewModel.reset()
43 tokenViewModel.reset()
44 selectedTab = 0
45 }
46 .tabItem {
47 Label("Settings", systemImage: "gearshape")
48 }
49 .tag(2)
50 }
51 .task {
52 await settingsViewModel.bootstrap()
53 }
54 .task(id: settingsViewModel.isAuthenticated) {
55 guard let client = settingsViewModel.client else {
56 domainViewModel.reset()
57 tokenViewModel.reset()
58 selectedTab = 0
59 return
60 }
61
62 await domainViewModel.loadDomains(client: client)
63 await tokenViewModel.loadTokens(client: client)
64 }
65 .fullScreenCover(isPresented: onboardingBinding) {
66 OnboardingView(viewModel: settingsViewModel)
67 }
68 }
69
70 private var onboardingBinding: Binding<Bool> {
71 Binding(
72 get: { settingsViewModel.requiresOnboarding },
73 set: { _ in }
74 )
75 }
76}