mirror of
https://github.com/maxgoedjen/secretive.git
synced 2026-03-11 03:57:23 +01:00
New setup (#657)
* WIP * WIP * WIP * Tweaks. * WIP * WIP * WIP * WIP * WIP * Cleanup * WIP * WIP * WIP * WIP * WIP * WIP * WIP * REmove setup menu item * WIP * . * . * . * Cleaup.
This commit is contained in:
151
Sources/Secretive/Views/Secrets/CreateSecretView.swift
Normal file
151
Sources/Secretive/Views/Secrets/CreateSecretView.swift
Normal file
@@ -0,0 +1,151 @@
|
||||
import SwiftUI
|
||||
import SecretKit
|
||||
|
||||
struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
|
||||
@State var store: StoreType
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
var createdSecret: (AnySecret?) -> Void
|
||||
|
||||
@State private var name = ""
|
||||
@State private var keyAttribution = ""
|
||||
@State private var authenticationRequirement: AuthenticationRequirement = .presenceRequired
|
||||
@State private var keyType: KeyType?
|
||||
@State var advanced = false
|
||||
@State var errorText: String?
|
||||
|
||||
private var authenticationOptions: [AuthenticationRequirement] {
|
||||
if advanced || authenticationRequirement == .biometryCurrent {
|
||||
[.presenceRequired, .notRequired, .biometryCurrent]
|
||||
} else {
|
||||
[.presenceRequired, .notRequired]
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .trailing) {
|
||||
Form {
|
||||
Section {
|
||||
TextField(String(localized: .createSecretNameLabel), text: $name, prompt: Text(.createSecretNamePlaceholder))
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
Picker(.createSecretRequireAuthenticationTitle, selection: $authenticationRequirement) {
|
||||
ForEach(authenticationOptions) { option in
|
||||
HStack {
|
||||
switch option {
|
||||
case .notRequired:
|
||||
Image(systemName: "bell")
|
||||
Text(.createSecretNotifyTitle)
|
||||
case .presenceRequired:
|
||||
Image(systemName: "lock")
|
||||
Text(.createSecretRequireAuthenticationTitle)
|
||||
case .biometryCurrent:
|
||||
Image(systemName: "lock.trianglebadge.exclamationmark.fill")
|
||||
Text(.createSecretRequireAuthenticationBiometricCurrentTitle)
|
||||
case .unknown:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
.tag(option)
|
||||
}
|
||||
}
|
||||
Group {
|
||||
switch authenticationRequirement {
|
||||
case .notRequired:
|
||||
Text(.createSecretNotifyDescription)
|
||||
case .presenceRequired:
|
||||
Text(.createSecretRequireAuthenticationDescription)
|
||||
case .biometryCurrent:
|
||||
Text(.createSecretRequireAuthenticationBiometricCurrentDescription)
|
||||
case .unknown:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
if authenticationRequirement == .biometryCurrent {
|
||||
Text(.createSecretBiometryCurrentWarning)
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 3)
|
||||
.background(.red.opacity(0.5), in: RoundedRectangle(cornerRadius: 5))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if advanced {
|
||||
Section {
|
||||
VStack {
|
||||
Picker(.createSecretKeyTypeLabel, selection: $keyType) {
|
||||
ForEach(store.supportedKeyTypes, id: \.self) { option in
|
||||
Text(String(describing: option))
|
||||
.tag(option)
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
if keyType?.algorithm == .mldsa {
|
||||
Text(.createSecretMldsaWarning)
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 3)
|
||||
.background(.red.opacity(0.5), in: RoundedRectangle(cornerRadius: 5))
|
||||
}
|
||||
}
|
||||
VStack(alignment: .leading) {
|
||||
TextField(.createSecretKeyAttributionLabel, text: $keyAttribution, prompt: Text(verbatim: "test@example.com"))
|
||||
Text(.createSecretKeyAttributionDescription)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
if let errorText {
|
||||
Section {
|
||||
} footer: {
|
||||
Text(verbatim: errorText)
|
||||
.errorStyle()
|
||||
}
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
Toggle(.createSecretAdvancedLabel, isOn: $advanced)
|
||||
.toggleStyle(.button)
|
||||
Spacer()
|
||||
Button(.createSecretCancelButton, role: .cancel) {
|
||||
dismiss()
|
||||
}
|
||||
Button(.createSecretCreateButton, action: save)
|
||||
.keyboardShortcut(.return)
|
||||
.primaryButton()
|
||||
.disabled(name.isEmpty)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.onAppear {
|
||||
keyType = store.supportedKeyTypes.first
|
||||
}
|
||||
.formStyle(.grouped)
|
||||
}
|
||||
|
||||
func save() {
|
||||
let attribution = keyAttribution.isEmpty ? nil : keyAttribution
|
||||
Task {
|
||||
do {
|
||||
let new = try await store.create(
|
||||
name: name,
|
||||
attributes: .init(
|
||||
keyType: keyType!,
|
||||
authentication: authenticationRequirement,
|
||||
publicKeyAttribution: attribution
|
||||
)
|
||||
)
|
||||
createdSecret(AnySecret(new))
|
||||
dismiss()
|
||||
} catch {
|
||||
errorText = error.localizedDescription
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#Preview {
|
||||
CreateSecretView(store: Preview.StoreModifiable()) { _ in }
|
||||
}
|
||||
Reference in New Issue
Block a user