Skip to content

Commit 3a066e4

Browse files
committed
Using debounced field for token. Improved error messages.
1 parent 18cf104 commit 3a066e4

File tree

2 files changed

+23
-22
lines changed

2 files changed

+23
-22
lines changed

CCMenu/Source/Pipeline Window/GitLab Sheets/AddGitLabPipelineSheet.swift

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,42 @@ struct AddGitLabPipelineSheet: View {
1010
@Binding var config: PipelineSheetConfig
1111
@EnvironmentObject private var authenticator: GitLabAuthenticator
1212
@Environment(\.presentationMode) @Binding var presentation
13+
@StateObject private var token = DebouncedText()
1314
@StateObject private var owner = DebouncedText()
1415
@StateObject private var project = DebouncedText()
1516
@StateObject private var projectList = GitLabProjectList()
1617
@StateObject private var branch = DebouncedText()
1718
@StateObject private var branchList = GitLabBranchList()
1819
@StateObject private var builder = GitLabPipelineBuilder()
1920
@State private var selectedProjectId: Int? = nil
20-
@State private var tokenInput: String = ""
21-
@FocusState private var istokenFieldFocused: Bool
2221

2322
var body: some View {
2423
VStack {
2524
Text("Add GitLab pipeline")
2625
.font(.headline)
2726
.padding(.bottom)
28-
Text("Enter a GitLab user or group name to fetch projects. If there are many projects only the most recently updated will be shown. You can type any valid name, even if it's not shown.\n\nCreate a personal access token with `read_api` scope to access private projects.")
27+
Text("Enter a GitLab user or group name to fetch projects. If there are many projects only the most recently updated will be shown. You can still type any valid name.\n\nCreate a personal access token with `read_api` scope to access private projects. The token you set here will be used for all GitHub pipelines.")
2928
.fixedSize(horizontal: false, vertical: true)
3029
.padding(.bottom)
3130
Form {
3231
HStack {
33-
SecureField("Authentication:", text: $tokenInput, prompt: Text("personal access token"))
32+
SecureField("Authentication:", text: $token.input, prompt: Text("personal access token"))
3433
.accessibilityIdentifier("Token field")
35-
.focused($istokenFieldFocused)
36-
.onChange(of: istokenFieldFocused) { _, newValue in
37-
if newValue == false {
34+
.onReceive(token.$text) { t in
35+
if t == token.input { // TODO: Is there a better way to avoid initial flickering?
3836
Task {
39-
await authenticator.setToken(tokenInput)
37+
await authenticator.setToken(t)
38+
if !owner.text.isEmpty {
39+
// TODO: Is there a better way to update project for new token?
40+
await projectList.updateProjects(name: owner.text, token: authenticator.token)
41+
}
4042
}
4143
}
4244
}
43-
Button(authenticator.token == nil ? "Create token" : "Manage tokens") {
45+
.onSubmit {
46+
token.takeInput()
47+
}
48+
Button("Manage tokens") {
4449
authenticator.openTokenSettingsOnWebsite()
4550
}
4651
}
@@ -51,7 +56,7 @@ struct AddGitLabPipelineSheet: View {
5156
.font(.callout)
5257
.padding(.vertical, 4)
5358
.padding(.horizontal, 8)
54-
.overlay(RoundedRectangle(cornerRadius: 4).stroke(Color.secondary, lineWidth: 0.5))
59+
.overlay(RoundedRectangle(cornerRadius: 2).stroke(Color.secondary, lineWidth: 0.5))
5560
}
5661
}
5762

@@ -170,7 +175,7 @@ struct AddGitLabPipelineSheet: View {
170175
.padding()
171176
.onAppear() {
172177
authenticator.fetchTokenFromKeychain()
173-
tokenInput = authenticator.token ?? ""
178+
token.input = authenticator.token ?? ""
174179
}
175180
.onDisappear() {
176181
authenticator.storeTokenInKeychain()

CCMenu/Source/Pipeline Window/GitLab Sheets/GitLabAuthenticator.swift

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@ class GitLabAuthenticator: ObservableObject {
2020
} else {
2121
token = trimmed
2222
let request = GitLabAPI.requestForTokenInfo(token: trimmed)
23-
guard let pat = await fetchTokenInfo(request: request) else {
24-
tokenDescription = "n/a"
25-
return
26-
}
23+
let pat = await fetchTokenInfo(request: request)
2724
updateTokenDescription(pat: pat)
2825
}
2926
}
@@ -47,7 +44,11 @@ class GitLabAuthenticator: ObservableObject {
4744
}
4845
}
4946

50-
private func updateTokenDescription(pat: GitLabPersonalAccessToken) {
47+
private func updateTokenDescription(pat: GitLabPersonalAccessToken?) {
48+
guard let pat else {
49+
tokenDescription = "\u{26A0}\u{FE0F} token is not valid"
50+
return
51+
}
5152
tokenDescription = String(format:"**%@**", pat.name)
5253
var errors: [String] = []
5354
if !pat.active {
@@ -58,7 +59,7 @@ class GitLabAuthenticator: ObservableObject {
5859
}
5960
if !errors.isEmpty {
6061
let errorText = errors.joined(separator: ", ")
61-
tokenDescription.append(String(format: "\n%@", errorText))
62+
tokenDescription.append(String(format: "\n\u{26A0}\u{FE0F} %@", errorText))
6263
} else if let expiryDate = pat.expiresAtDate {
6364
let formatter = RelativeDateTimeFormatter()
6465
let expiryText = formatter.localizedString(for: expiryDate, relativeTo: Date())
@@ -70,11 +71,6 @@ class GitLabAuthenticator: ObservableObject {
7071
func fetchTokenFromKeychain() {
7172
do {
7273
token = try Keychain.standard.getToken(forService: "GitLab")
73-
if let token {
74-
Task {
75-
await setToken(token)
76-
}
77-
}
7874
} catch {
7975
token = nil
8076
let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "application")

0 commit comments

Comments
 (0)