krz/hutch

an ios client for sourcehut

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

v2.10.1: Hutch/Views/Auth/AuthView.swift · raw

 1import SwiftUI
 2
 3/// Token entry screen shown when the user is not authenticated.
 4struct TokenEntryView: View {
 5    private let createAccountURL = URL(string: "https://meta.sr.ht/register")!
 6    private let personalAccessTokensURL = URL(string: "https://meta.sr.ht/oauth/personal-access-tokens")!
 7
 8    @Environment(AppState.self) private var appState
 9    @State private var token = ""
10    @State private var isConnecting = false
11    @State private var errorMessage: String?
12
13    var body: some View {
14        NavigationStack {
15            Form {
16                Section {
17                    Text("Enter your SourceHut personal access token to connect.")
18                } header: {
19                    Text("Welcome to Hutch")
20                } footer: {
21                    Text("Hutch stores your SourceHut personal access token securely in the iOS keychain.")
22                }
23
24                Section {
25                    SecureField("Personal Access Token", text: $token)
26                        .textContentType(.password)
27                        .autocorrectionDisabled()
28                        .textInputAutocapitalization(.never)
29                        .disabled(isConnecting)
30                } header: {
31                    Text("Token")
32                }
33
34                if let errorMessage {
35                    Section {
36                        Label {
37                            Text(errorMessage)
38                        } icon: {
39                            Image(systemName: "exclamationmark.triangle.fill")
40                                .foregroundStyle(.red)
41                        }
42                        .foregroundStyle(.red)
43                    }
44                }
45
46                Section {
47                    Button {
48                        connect()
49                    } label: {
50                        HStack {
51                            Text("Connect")
52                            if isConnecting {
53                                Spacer()
54                                ProgressView()
55                            }
56                        }
57                    }
58                    .disabled(tokenTrimmed.isEmpty || isConnecting)
59                }
60
61                Section {
62                    Link(destination: createAccountURL) {
63                        Label("Create SourceHut account", systemImage: "person.badge.plus")
64                    }
65
66                    Link(destination: personalAccessTokensURL) {
67                        Label("Create Personal Access Token", systemImage: "key")
68                    }
69                } header: {
70                    Text("Need an account?")
71                } footer: {
72                    Text("These links open SourceHut in your browser. After signing up, create a Personal Access Token there and paste it here.")
73                }
74            }
75            .navigationTitle("Hutch")
76        }
77    }
78
79    private var tokenTrimmed: String {
80        token.trimmingCharacters(in: .whitespacesAndNewlines)
81    }
82
83    private func connect() {
84        errorMessage = nil
85        isConnecting = true
86        Task {
87            do {
88                try await appState.connect(with: tokenTrimmed)
89            } catch {
90                errorMessage = error.userFacingMessage
91            }
92            isConnecting = false
93        }
94    }
95}