| @@ -68,6 +68,9 @@ private struct SecretSetSheet: View { |
| 68 | |
68 | |
| 69 | @State private var name = "" |
69 | @State private var name = "" |
| 70 | @State private var value = "" |
70 | @State private var value = "" |
| |
71 | @State private var multiLine = false |
| |
72 | /// Errors shown here are this sheet's own, not an earlier list action's. |
| |
73 | @State private var attempted = false |
| 71 | |
74 | |
| 72 | var body: some View { |
75 | var body: some View { |
| 73 | NavigationStack { |
76 | NavigationStack { |
| @@ -78,14 +81,26 @@ private struct SecretSetSheet: View { |
| 78 | .autocorrectionDisabled() |
81 | .autocorrectionDisabled() |
| 79 | .textInputAutocapitalization(.characters) |
82 | .textInputAutocapitalization(.characters) |
| 80 | .accessibilityIdentifier("secret-name") |
83 | .accessibilityIdentifier("secret-name") |
| 81 | SecureField("Value", text: $value) |
84 | if multiLine { |
| 82 | .autocorrectionDisabled() |
85 | TextEditor(text: $value) |
| 83 | .textInputAutocapitalization(.never) |
86 | .frame(minHeight: 120) |
| 84 | .accessibilityIdentifier("secret-value") |
87 | .font(.gbMono(.caption)) |
| |
88 | .autocorrectionDisabled() |
| |
89 | .textInputAutocapitalization(.never) |
| |
90 | .accessibilityIdentifier("secret-value-multiline") |
| |
91 | } else { |
| |
92 | SecureField("Value", text: $value) |
| |
93 | .autocorrectionDisabled() |
| |
94 | .textInputAutocapitalization(.never) |
| |
95 | .accessibilityIdentifier("secret-value") |
| |
96 | } |
| |
97 | Toggle("Multi-line value", isOn: $multiLine) |
| 85 | } footer: { |
98 | } footer: { |
| 86 | Text("Uppercase letters, digits and underscores. The value is sent once and cannot be read back.") |
99 | Text(multiLine |
| |
100 | ? "Shown while you type, for a value with line breaks such as a private key. It is sent once and cannot be read back." |
| |
101 | : "Uppercase letters, digits and underscores. The value is sent once and cannot be read back.") |
| 87 | } |
102 | } |
| 88 | if let error = model.actionError { |
103 | if attempted, let error = model.actionError { |
| 89 | Section { GBNotice(error, .gbWarn) } |
104 | Section { GBNotice(error, .gbWarn) } |
| 90 | } |
105 | } |
| 91 | } |
106 | } |
| @@ -101,6 +116,7 @@ private struct SecretSetSheet: View { |
| 101 | } else { |
116 | } else { |
| 102 | Button("Set") { |
117 | Button("Set") { |
| 103 | Task { |
118 | Task { |
| |
119 | attempted = true |
| 104 | guard await model.set(name: name, value: value) else { return } |
120 | guard await model.set(name: name, value: value) else { return } |
| 105 | // A secure field that still holds text as the sheet |
121 | // A secure field that still holds text as the sheet |
| 106 | // goes makes iOS offer to save it as a password. |
122 | // goes makes iOS offer to save it as a password. |
| @@ -222,6 +238,7 @@ private struct DeployKeyAddSheet: View { |
| 222 | @State private var text = "" |
238 | @State private var text = "" |
| 223 | @State private var canPush = false |
239 | @State private var canPush = false |
| 224 | @State private var ttl: String? |
240 | @State private var ttl: String? |
| |
241 | @State private var attempted = false |
| 225 | |
242 | |
| 226 | var body: some View { |
243 | var body: some View { |
| 227 | NavigationStack { |
244 | NavigationStack { |
| @@ -246,7 +263,7 @@ private struct DeployKeyAddSheet: View { |
| 246 | Text("In a year").tag(String?.some("365d")) |
263 | Text("In a year").tag(String?.some("365d")) |
| 247 | } |
264 | } |
| 248 | } |
265 | } |
| 249 | if let error = model.actionError { |
266 | if attempted, let error = model.actionError { |
| 250 | Section { GBNotice(error, .gbWarn) } |
267 | Section { GBNotice(error, .gbWarn) } |
| 251 | } |
268 | } |
| 252 | } |
269 | } |
| @@ -261,7 +278,10 @@ private struct DeployKeyAddSheet: View { |
| 261 | ProgressView() |
278 | ProgressView() |
| 262 | } else { |
279 | } else { |
| 263 | Button("Add") { |
280 | Button("Add") { |
| 264 | Task { if await model.add(publicKey: text, canPush: canPush, ttl: ttl) { onDone() } } |
281 | Task { |
| |
282 | attempted = true |
| |
283 | if await model.add(publicKey: text, canPush: canPush, ttl: ttl) { onDone() } |
| |
284 | } |
| 265 | } |
285 | } |
| 266 | .disabled(text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) |
286 | .disabled(text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) |
| 267 | .accessibilityIdentifier("deploy-key-submit") |
287 | .accessibilityIdentifier("deploy-key-submit") |