mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-08-31 01:20:57 +00:00
WIP
This commit is contained in:
parent
11c92327ac
commit
bff58b00ec
@ -2179,6 +2179,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Current Biometrics" : {
|
||||
|
||||
},
|
||||
"delete_confirmation_cancel_button" : {
|
||||
"extractionState" : "manual",
|
||||
@ -2949,6 +2952,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"If you change your biometric settings in _any way_, including adding a new fingerprint, this key will no longer be accessible." : {
|
||||
|
||||
},
|
||||
"Key Attribution" : {
|
||||
|
||||
@ -3555,6 +3561,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Require authentication with current set of biometrics." : {
|
||||
|
||||
},
|
||||
"secret_detail_md5_fingerprint_label" : {
|
||||
"extractionState" : "manual",
|
||||
@ -5350,6 +5359,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Test" : {
|
||||
|
||||
},
|
||||
"test@example.com" : {
|
||||
|
||||
|
@ -17,7 +17,7 @@ public struct Attributes: Sendable, Codable, Hashable {
|
||||
authentication: AuthenticationRequirement = .presenceRequired,
|
||||
publicKeyAttribution: String? = nil
|
||||
) {
|
||||
assert(authentication != .unknown, "Secrets cannot be created with an unknown authentication requirement.")
|
||||
// assert(authentication != .unknown, "Secrets cannot be created with an unknown authentication requirement.")
|
||||
self.keyType = keyType
|
||||
self.authentication = authentication
|
||||
self.publicKeyAttribution = publicKeyAttribution
|
||||
|
@ -13,6 +13,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
@MainActor private let storeList: SecretStoreList = {
|
||||
let list = SecretStoreList()
|
||||
// list.add(store: SecureEnclave.CryptoKitStore())
|
||||
list.add(store: SecureEnclave.Store())
|
||||
list.add(store: SmartCard.Store())
|
||||
return list
|
||||
|
@ -1,4 +1,3 @@
|
||||
import Cocoa
|
||||
import SwiftUI
|
||||
import SecretKit
|
||||
import SecureEnclaveSecretKit
|
||||
@ -10,6 +9,7 @@ extension EnvironmentValues {
|
||||
// This is injected through .environment modifier below instead of @Entry for performance reasons (basially, restrictions around init/mainactor causing delay in loading secrets/"empty screen" blip).
|
||||
@MainActor fileprivate static let _secretStoreList: SecretStoreList = {
|
||||
let list = SecretStoreList()
|
||||
list.add(store: SecureEnclave.Store())
|
||||
list.add(store: SecureEnclave.CryptoKitStore())
|
||||
list.add(store: SmartCard.Store())
|
||||
return list
|
||||
|
@ -30,7 +30,7 @@ struct ContentView: View {
|
||||
}
|
||||
.frame(minWidth: 640, minHeight: 320)
|
||||
.toolbar {
|
||||
// toolbarItem(updateNoticeView, id: "update")
|
||||
toolbarItem(updateNoticeView, id: "update")
|
||||
toolbarItem(runningOrRunSetupView, id: "setup")
|
||||
toolbarItem(appPathNoticeView, id: "appPath")
|
||||
toolbarItem(newItemView, id: "new")
|
||||
|
@ -8,7 +8,9 @@ struct CopyableView: View {
|
||||
var text: String
|
||||
|
||||
@State private var interactionState: InteractionState = .normal
|
||||
|
||||
@State private var expanded = false
|
||||
@State private var showExpand = false
|
||||
|
||||
var content: some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
@ -31,17 +33,50 @@ struct CopyableView: View {
|
||||
}
|
||||
.padding(EdgeInsets(top: 20, leading: 20, bottom: 10, trailing: 20))
|
||||
Divider()
|
||||
Text(text)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.foregroundColor(primaryTextColor)
|
||||
.padding(EdgeInsets(top: 10, leading: 20, bottom: 20, trailing: 20))
|
||||
.multilineTextAlignment(.leading)
|
||||
.font(.system(.body, design: .monospaced))
|
||||
textView
|
||||
.lineLimit(expanded ? nil : 5)
|
||||
.overlay {
|
||||
ViewThatFits {
|
||||
textView
|
||||
.hidden()
|
||||
.onAppear {
|
||||
showExpand = false
|
||||
}
|
||||
Spacer()
|
||||
.onAppear {
|
||||
showExpand = true
|
||||
}
|
||||
}
|
||||
}
|
||||
.overlay(alignment: .bottomTrailing) {
|
||||
if showExpand {
|
||||
if #available(macOS 26.0, *) {
|
||||
Button("Test", systemImage: "rectangle.expand.vertical") {
|
||||
expanded = true
|
||||
showExpand = false
|
||||
}
|
||||
.labelStyle(.iconOnly)
|
||||
.buttonBorderShape(.circle)
|
||||
.buttonStyle(.glass)
|
||||
.padding()
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
._background(interactionState: interactionState)
|
||||
.frame(minWidth: 150, maxWidth: .infinity)
|
||||
}
|
||||
|
||||
var textView: some View {
|
||||
Text(text)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.foregroundColor(primaryTextColor)
|
||||
.padding(EdgeInsets(top: 10, leading: 20, bottom: 20, trailing: 20))
|
||||
.multilineTextAlignment(.leading)
|
||||
.font(.system(.body, design: .monospaced))
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
content
|
||||
.onHover { hovering in
|
||||
@ -49,10 +84,10 @@ struct CopyableView: View {
|
||||
interactionState = hovering ? .hovering : .normal
|
||||
}
|
||||
}
|
||||
.onDrag({
|
||||
NSItemProvider(item: NSData(data: text.data(using: .utf8)!), typeIdentifier: UTType.utf8PlainText.identifier)
|
||||
}, preview: {
|
||||
content
|
||||
.draggable(text, preview: {
|
||||
content
|
||||
.lineLimit(3)
|
||||
.frame(maxWidth: 300)
|
||||
._background(interactionState: .dragging)
|
||||
})
|
||||
.onTapGesture {
|
||||
@ -170,7 +205,7 @@ struct CopyableView_Previews: PreviewProvider {
|
||||
Group {
|
||||
CopyableView(title: "secret_detail_sha256_fingerprint_label", image: Image(systemName: "figure.wave"), text: "Hello world.")
|
||||
.padding()
|
||||
CopyableView(title: "secret_detail_sha256_fingerprint_label", image: Image(systemName: "figure.wave"), text: "Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. ")
|
||||
CopyableView(title: "secret_detail_sha256_fingerprint_label", image: Image(systemName: "figure.wave"), text: "Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text. Long text.")
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,11 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
@State var advanced = false
|
||||
|
||||
private var authenticationOptions: [AuthenticationRequirement] {
|
||||
[.presenceRequired, .notRequired]
|
||||
if advanced || authenticationRequirement == .biometryCurrent {
|
||||
[.presenceRequired, .notRequired, .biometryCurrent]
|
||||
} else {
|
||||
[.presenceRequired, .notRequired]
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@ -21,11 +25,48 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
Form {
|
||||
Section {
|
||||
TextField(String(localized: .createSecretNameLabel), text: $name, prompt: Text(.createSecretNamePlaceholder))
|
||||
Picker(.createSecretRequireAuthenticationTitle, selection: $authenticationRequirement) {
|
||||
ForEach(authenticationOptions) { option in
|
||||
Text(String(describing: option))
|
||||
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("Current Biometrics")
|
||||
case .unknown:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
.tag(option)
|
||||
}
|
||||
}
|
||||
Group {
|
||||
switch authenticationRequirement {
|
||||
case .notRequired:
|
||||
Text(.createSecretNotifyDescription)
|
||||
case .presenceRequired:
|
||||
Text(.createSecretRequireAuthenticationDescription)
|
||||
case .biometryCurrent:
|
||||
Text("Require authentication with current set of biometrics.")
|
||||
case .unknown:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
if authenticationRequirement == .biometryCurrent {
|
||||
Text("If you change your biometric settings in _any way_, including adding a new fingerprint, this key will no longer be accessible.")
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 3)
|
||||
.background(.red.opacity(0.5), in: RoundedRectangle(cornerRadius: 5))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if advanced {
|
||||
@ -48,7 +89,8 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
VStack(alignment: .leading) {
|
||||
TextField("Key Attribution", text: $keyAttribution, prompt: Text("test@example.com"))
|
||||
Text("This shows at the end of your public key.")
|
||||
.font(.caption)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,8 @@ struct EditSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
VStack(alignment: .leading) {
|
||||
TextField("Key Attribution", text: $publicKeyAttribution, prompt: Text("test@example.com"))
|
||||
Text("This shows at the end of your public key.")
|
||||
.font(.caption)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ struct ToolbarButtonStyle: ButtonStyle {
|
||||
configuration
|
||||
.label
|
||||
.foregroundColor(.white)
|
||||
.padding(EdgeInsets(top: 6, leading: 8, bottom: 6, trailing: 8))
|
||||
.padding(.vertical, 6)
|
||||
.padding(.horizontal, 9)
|
||||
.glassEffect(.regular.tint(glassTint), in: .capsule)
|
||||
.onHover { hovering in
|
||||
self.hovering = hovering
|
||||
@ -41,6 +42,8 @@ struct ToolbarButtonStyle: ButtonStyle {
|
||||
.label
|
||||
.background(colorScheme == .light ? lightColor : darkColor)
|
||||
.foregroundColor(.white)
|
||||
.padding(.vertical, 6)
|
||||
.padding(.horizontal, 8)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 5))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 5)
|
||||
|
Loading…
Reference in New Issue
Block a user