mirror of
https://github.com/maxgoedjen/secretive.git
synced 2026-05-07 16:08:58 +02:00
* Sketching out. * WIP * WIP * Dump * Apply stash * Merge + WIP * UI * More WIP * Agent config * UI cleanup * Restore dirty files * XPC * Edit/delete * UI fixes * Cleanup * Change id for OpenSSHCertificate to hex of md5 * Fix runtime warning for confirmation dialog * Mark strings as reviewed * Cleanup * Fix agent tests
98 lines
3.6 KiB
Swift
98 lines
3.6 KiB
Swift
import SwiftUI
|
|
import SecretKit
|
|
import SSHProtocolKit
|
|
|
|
struct StoreListView: View {
|
|
|
|
enum StoreListSelection: Hashable {
|
|
case secret(AnySecret)
|
|
case certificate(OpenSSHCertificate)
|
|
}
|
|
|
|
@Binding var selection: StoreListSelection?
|
|
|
|
@Environment(\.secretStoreList) private var storeList
|
|
@Environment(\.certificateStore) private var certificateStore
|
|
|
|
private func secretDeleted(secret: AnySecret) {
|
|
selection = nextDefaultSecret.map(StoreListSelection.secret)
|
|
}
|
|
|
|
private func secretRenamed(secret: AnySecret) {
|
|
// Pull new version from store, so we get all updated attributes
|
|
selection = nil
|
|
selection = storeList.allSecrets.first(where: { $0.id == secret.id }).map(StoreListSelection.secret)
|
|
}
|
|
|
|
var body: some View {
|
|
NavigationSplitView {
|
|
List(selection: $selection) {
|
|
ForEach(storeList.stores) { store in
|
|
if store.isAvailable {
|
|
Section(header: Text(store.name)) {
|
|
ForEach(store.secrets) { secret in
|
|
SecretListItemView(
|
|
store: store,
|
|
secret: secret,
|
|
deletedSecret: secretDeleted,
|
|
renamedSecret: secretRenamed,
|
|
)
|
|
.tag(StoreListSelection.secret(secret))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if !certificateStore.certificates.isEmpty {
|
|
Section("Certificates") {
|
|
ForEach(certificateStore.certificates) { certificate in
|
|
CertificateListItemView(
|
|
certificate: certificate,
|
|
deletedCertificate: { _ in },
|
|
renamedCertificate: { _ in }
|
|
)
|
|
.tag(StoreListSelection.certificate(certificate))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} detail: {
|
|
switch selection {
|
|
case .secret(let secret):
|
|
SecretDetailView(secret: secret, certificates: certificateStore.certificates(for: secret)) {
|
|
selection = .certificate($0)
|
|
}
|
|
case .certificate(let certificate):
|
|
CertificateDetailView(certificate: certificate)
|
|
case nil:
|
|
if let nextDefaultSecret {
|
|
// This just means onAppear hasn't executed yet.
|
|
// Do this to avoid a blip.
|
|
SecretDetailView(secret: nextDefaultSecret, certificates: certificateStore.certificates(for: nextDefaultSecret)) {
|
|
selection = .certificate($0)
|
|
}
|
|
} else {
|
|
if let modifiable = storeList.modifiableStore, modifiable.isAvailable {
|
|
EmptyStoreView(store: modifiable)
|
|
} else {
|
|
EmptyStoreView(store: storeList.stores.first(where: \.isAvailable))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.navigationSplitViewStyle(.balanced)
|
|
.onAppear {
|
|
selection = nextDefaultSecret.map(StoreListSelection.secret)
|
|
}
|
|
.frame(minWidth: 100, idealWidth: 240)
|
|
|
|
}
|
|
}
|
|
|
|
extension StoreListView {
|
|
|
|
private var nextDefaultSecret: AnySecret? {
|
|
return storeList.allSecrets.first
|
|
}
|
|
|
|
}
|