krz/hutch

an ios client for sourcehut

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

v2.8.1: Hutch/Views/More/AccountSwitcherView.swift · raw

 1import SwiftUI
 2
 3struct AccountSwitcherView: View {
 4    @Environment(AppState.self) private var appState
 5    @Environment(\.dismiss) private var dismiss
 6
 7    @State private var showAddAccount = false
 8    @State private var isSwitching = false
 9    @State private var switchError: String?
10
11    var body: some View {
12        NavigationStack {
13            List {
14                Section {
15                    ForEach(appState.accounts) { account in
16                        Button {
17                            guard account.id != appState.activeAccountID else { return }
18                            switchTo(account)
19                        } label: {
20                            HStack {
21                                Text("~\(account.username)")
22                                    .foregroundStyle(.primary)
23                                Spacer()
24                                if account.id == appState.activeAccountID {
25                                    Image(systemName: "checkmark")
26                                        .foregroundStyle(.tint)
27                                }
28                            }
29                        }
30                        .disabled(isSwitching)
31                    }
32                    .onDelete { indexSet in
33                        for index in indexSet {
34                            let account = appState.accounts[index]
35                            Task { await appState.removeAccount(id: account.id) }
36                        }
37                    }
38                }
39
40                Section {
41                    Button {
42                        showAddAccount = true
43                    } label: {
44                        Label("Add Account", systemImage: "plus.circle")
45                    }
46                    .disabled(isSwitching)
47                }
48            }
49            .navigationTitle("Accounts")
50            .navigationBarTitleDisplayMode(.inline)
51            .toolbar {
52                ToolbarItem(placement: .confirmationAction) {
53                    Button("Done") { dismiss() }
54                }
55            }
56            .overlay {
57                if isSwitching {
58                    ZStack {
59                        Color.black.opacity(0.25).ignoresSafeArea()
60                        ProgressView("Switching…")
61                            .padding()
62                            .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 12))
63                    }
64                }
65            }
66            .alert("Switch Failed", isPresented: Binding(
67                get: { switchError != nil },
68                set: { if !$0 { switchError = nil } }
69            )) {
70                Button("OK") { switchError = nil }
71            } message: {
72                Text(switchError ?? "")
73            }
74            .sheet(isPresented: $showAddAccount) {
75                AddAccountView()
76            }
77        }
78    }
79
80    private func switchTo(_ account: AccountEntry) {
81        isSwitching = true
82        Task {
83            do {
84                try await appState.switchAccount(to: account.id)
85                dismiss()
86            } catch {
87                switchError = error.localizedDescription
88            }
89            isSwitching = false
90        }
91    }
92}