summaryrefslogtreecommitdiff
path: root/Hutch/Views/Auth/AuthView.swift
blob: 5a249ef320343ee72e1e5e81e868a12fc2059e4e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import SwiftUI

/// Token entry screen shown when the user is not authenticated.
struct TokenEntryView: View {
    private let createAccountURL = URL(string: "https://meta.sr.ht/register")!
    private let personalAccessTokensURL = URL(string: "https://meta.sr.ht/oauth/personal-access-tokens")!

    @Environment(AppState.self) private var appState
    @State private var token = ""
    @State private var isConnecting = false
    @State private var errorMessage: String?

    var body: some View {
        NavigationStack {
            Form {
                Section {
                    Text("Enter your SourceHut personal access token to connect.")
                } header: {
                    Text("Welcome to Hutch")
                } footer: {
                    Text("Hutch stores your SourceHut personal access token securely in the iOS keychain.")
                }

                Section {
                    SecureField("Personal Access Token", text: $token)
                        .textContentType(.password)
                        .autocorrectionDisabled()
                        .textInputAutocapitalization(.never)
                        .disabled(isConnecting)
                } header: {
                    Text("Token")
                }

                if let errorMessage {
                    Section {
                        Label {
                            Text(errorMessage)
                        } icon: {
                            Image(systemName: "exclamationmark.triangle.fill")
                                .foregroundStyle(.red)
                        }
                        .foregroundStyle(.red)
                    }
                }

                Section {
                    Button {
                        connect()
                    } label: {
                        HStack {
                            Text("Connect")
                            if isConnecting {
                                Spacer()
                                ProgressView()
                            }
                        }
                    }
                    .disabled(tokenTrimmed.isEmpty || isConnecting)
                }

                Section {
                    Link(destination: createAccountURL) {
                        Label("Create SourceHut account", systemImage: "person.badge.plus")
                    }

                    Link(destination: personalAccessTokensURL) {
                        Label("Create Personal Access Token", systemImage: "key")
                    }
                } header: {
                    Text("Need an account?")
                } footer: {
                    Text("These links open SourceHut in your browser. After signing up, create a Personal Access Token there and paste it here.")
                }
            }
            .navigationTitle("Hutch")
        }
    }

    private var tokenTrimmed: String {
        token.trimmingCharacters(in: .whitespacesAndNewlines)
    }

    private func connect() {
        errorMessage = nil
        isConnecting = true
        Task {
            do {
                try await appState.connect(with: tokenTrimmed)
            } catch {
                errorMessage = error.userFacingMessage
            }
            isConnecting = false
        }
    }
}