77 lines
3.4 KiB
Swift
77 lines
3.4 KiB
Swift
// SPDX-FileCopyrightText: 2026 Kaede Akino
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
import SwiftUI
|
|
import TermindApplication
|
|
import TermindDomain
|
|
import TermindPresentation
|
|
|
|
struct KeyExportDetailView: View {
|
|
let keyID: SSHKeyRef.ID
|
|
@Environment(AppModel.self) private var app
|
|
@Environment(WindowModel.self) private var window
|
|
@State private var model: KeyExportModel?
|
|
|
|
var body: some View {
|
|
VaultDetailScaffold(
|
|
title: AppStrings.Keychain.exportToHost, symbol: "square.and.arrow.up", close: window.closeVaultWork
|
|
) {
|
|
if let model {
|
|
if model.journey.isPresented {
|
|
journey(model)
|
|
} else {
|
|
KeyExportForm(model: model)
|
|
}
|
|
} else {
|
|
ContentUnavailableView(AppStrings.Keychain.keyUnavailable.swiftUIKey, systemImage: "key.slash")
|
|
}
|
|
} footer: {
|
|
HStack {
|
|
if model?.phase == .exporting {
|
|
ProgressView().controlSize(.small)
|
|
Text(AppStrings.KeyExport.exporting).font(.caption)
|
|
}
|
|
Spacer()
|
|
Button(
|
|
model?.didExport == true ? AppStrings.Common.done.swiftUIKey : AppStrings.Common.cancel.swiftUIKey,
|
|
action: window.closeVaultWork)
|
|
if let model, case .failed = model.phase, model.journey.isPresented {
|
|
Button(AppStrings.Common.edit.swiftUIKey) { model.editOptions() }
|
|
}
|
|
if let model, !model.didExport, !model.journey.isPresented {
|
|
Button(AppStrings.KeyExport.exportAndAttach.swiftUIKey) { model.start() }
|
|
.buttonStyle(.borderedProminent).keyboardShortcut(.defaultAction)
|
|
.disabled(!model.canStart)
|
|
}
|
|
}.padding(Metrics.Space.l)
|
|
}
|
|
.task(id: keyID) {
|
|
model?.cancel()
|
|
model = app.hostLibrary.key(keyID).map {
|
|
KeyExportModel(key: $0, library: app.hostLibrary, services: app.connections.keyExportServices())
|
|
}
|
|
}
|
|
.onDisappear { model?.cancel() }
|
|
}
|
|
|
|
private func journey(_ model: KeyExportModel) -> some View {
|
|
let promptID = model.authenticationPrompt?.id
|
|
let operationID = model.operationID
|
|
return ConnectionJourneyView(
|
|
journey: model.journey, authenticationPrompt: model.authenticationPrompt,
|
|
hostKey: model.connection.pendingHostKey,
|
|
submitAuthentication: { identity, username, password, passphrase, key, save in
|
|
guard let promptID else { return }
|
|
model.submitAuthentication(
|
|
promptID: promptID, identityID: identity, username: username, password: password,
|
|
passphrase: passphrase, keyID: key, save: save)
|
|
},
|
|
continueHostKey: { model.acceptHostKey($0, operationID: operationID, remember: false) },
|
|
trustHostKey: { model.acceptHostKey($0, operationID: operationID, remember: true) },
|
|
denyHostKey: window.closeVaultWork, retry: model.retry, cancel: window.closeVaultWork,
|
|
securityKeySigning: model.connection.securityKeySigning,
|
|
keyboardAuthentication: model.connection.keyboardAuthentication,
|
|
cancelKeyboardAuthentication: window.closeVaultWork, isEmbedded: true)
|
|
}
|
|
}
|