This commit is contained in:
Max Goedjen 2025-08-10 14:23:57 -07:00
parent bab76da2ab
commit 998f4b9bf4
No known key found for this signature in database
14 changed files with 99 additions and 81 deletions

View File

@ -65,7 +65,8 @@ let package = Package(
, ,
.target( .target(
name: "Brief", name: "Brief",
dependencies: [] dependencies: [],
swiftSettings: swiftSettings
), ),
.testTarget( .testTarget(
name: "BriefTests", name: "BriefTests",

View File

@ -2,7 +2,7 @@ import Foundation
import Observation import Observation
import Security import Security
import CryptoKit import CryptoKit
import LocalAuthentication @preconcurrency import LocalAuthentication
import SecretKit import SecretKit
import Synchronization import Synchronization

View File

@ -2,10 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.smartcard</key> <key>com.apple.security.smartcard</key>
<true/> <true/>
<key>keychain-access-groups</key> <key>keychain-access-groups</key>

View File

@ -359,8 +359,9 @@
50617D7723FCE48D0099B055 /* Project object */ = { 50617D7723FCE48D0099B055 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1220; LastSwiftUpdateCheck = 1220;
LastUpgradeCheck = 1320; LastUpgradeCheck = 2600;
ORGANIZATIONNAME = "Max Goedjen"; ORGANIZATIONNAME = "Max Goedjen";
TargetAttributes = { TargetAttributes = {
50617D7E23FCE48D0099B055 = { 50617D7E23FCE48D0099B055 = {
@ -491,6 +492,8 @@
baseConfigurationReference = 508A58AB241E121B0069DC07 /* Config.xcconfig */; baseConfigurationReference = 508A58AB241E121B0069DC07 /* Config.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@ -521,9 +524,11 @@
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
@ -544,6 +549,7 @@
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OTHER_SWIFT_FLAGS = ""; OTHER_SWIFT_FLAGS = "";
SDKROOT = macosx; SDKROOT = macosx;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
STRIP_INSTALLED_PRODUCT = NO; STRIP_INSTALLED_PRODUCT = NO;
STRIP_SWIFT_SYMBOLS = NO; STRIP_SWIFT_SYMBOLS = NO;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
@ -558,6 +564,8 @@
baseConfigurationReference = 508A58AB241E121B0069DC07 /* Config.xcconfig */; baseConfigurationReference = 508A58AB241E121B0069DC07 /* Config.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@ -588,9 +596,11 @@
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@ -604,6 +614,7 @@
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = ""; OTHER_SWIFT_FLAGS = "";
SDKROOT = macosx; SDKROOT = macosx;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
STRIP_INSTALLED_PRODUCT = NO; STRIP_INSTALLED_PRODUCT = NO;
STRIP_SWIFT_SYMBOLS = NO; STRIP_SWIFT_SYMBOLS = NO;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
@ -616,17 +627,20 @@
50617D9E23FCE48E0099B055 /* Debug */ = { 50617D9E23FCE48E0099B055 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Secretive/Secretive.entitlements; CODE_SIGN_ENTITLEMENTS = Secretive/Secretive.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\"";
DEVELOPMENT_TEAM = Z72PRUAWF6; DEVELOPMENT_TEAM = Z72PRUAWF6;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
ENABLE_USER_SELECTED_FILES = readwrite;
INFOPLIST_FILE = Secretive/Info.plist; INFOPLIST_FILE = Secretive/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -642,17 +656,20 @@
50617D9F23FCE48E0099B055 /* Release */ = { 50617D9F23FCE48E0099B055 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Secretive/Secretive.entitlements; CODE_SIGN_ENTITLEMENTS = Secretive/Secretive.entitlements;
CODE_SIGN_IDENTITY = "Developer ID Application"; CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\"";
DEVELOPMENT_TEAM = Z72PRUAWF6; DEVELOPMENT_TEAM = Z72PRUAWF6;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
ENABLE_USER_SELECTED_FILES = readwrite;
INFOPLIST_FILE = Secretive/Info.plist; INFOPLIST_FILE = Secretive/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -670,6 +687,8 @@
baseConfigurationReference = 508A58AB241E121B0069DC07 /* Config.xcconfig */; baseConfigurationReference = 508A58AB241E121B0069DC07 /* Config.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@ -700,9 +719,11 @@
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
@ -723,6 +744,7 @@
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OTHER_SWIFT_FLAGS = ""; OTHER_SWIFT_FLAGS = "";
SDKROOT = macosx; SDKROOT = macosx;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
STRIP_INSTALLED_PRODUCT = NO; STRIP_INSTALLED_PRODUCT = NO;
STRIP_SWIFT_SYMBOLS = NO; STRIP_SWIFT_SYMBOLS = NO;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
@ -735,14 +757,17 @@
508A5915241EF1A00069DC07 /* Test */ = { 508A5915241EF1A00069DC07 /* Test */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Secretive/Preview Content\"";
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = NO; ENABLE_HARDENED_RUNTIME = NO;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
ENABLE_USER_SELECTED_FILES = readwrite;
INFOPLIST_FILE = Secretive/Info.plist; INFOPLIST_FILE = Secretive/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -760,8 +785,11 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = SecretAgent/Info.plist; INFOPLIST_FILE = SecretAgent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
@ -781,9 +809,12 @@
CODE_SIGN_ENTITLEMENTS = SecretAgent/SecretAgent.entitlements; CODE_SIGN_ENTITLEMENTS = SecretAgent/SecretAgent.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
DEVELOPMENT_TEAM = Z72PRUAWF6; DEVELOPMENT_TEAM = Z72PRUAWF6;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = SecretAgent/Info.plist; INFOPLIST_FILE = SecretAgent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
@ -804,9 +835,12 @@
CODE_SIGN_IDENTITY = "Developer ID Application"; CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
DEVELOPMENT_TEAM = Z72PRUAWF6; DEVELOPMENT_TEAM = Z72PRUAWF6;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = SecretAgent/Info.plist; INFOPLIST_FILE = SecretAgent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1320" LastUpgradeVersion = "2600"
version = "1.7"> version = "1.7">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1320" LastUpgradeVersion = "2600"
version = "1.7"> version = "1.7">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -89,7 +89,7 @@
</BuildableProductRunnable> </BuildableProductRunnable>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release" buildConfiguration = "Debug"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"

View File

@ -2256,6 +2256,7 @@
} }
}, },
"empty_store_modifiable_title" : { "empty_store_modifiable_title" : {
"extractionState" : "stale",
"localizations" : { "localizations" : {
"ca" : { "ca" : {
"stringUnit" : { "stringUnit" : {

View File

@ -2,12 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.smartcard</key> <key>com.apple.security.smartcard</key>
<true/> <true/>
<key>keychain-access-groups</key> <key>keychain-access-groups</key>

View File

@ -10,7 +10,7 @@ struct ContentView: View {
@Binding var runningSetup: Bool @Binding var runningSetup: Bool
@Binding var hasRunSetup: Bool @Binding var hasRunSetup: Bool
@State var showingAgentInfo = false @State var showingAgentInfo = false
@State var activeSecret: AnySecret.ID? @State var activeSecret: AnySecret?
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
@Environment(\.secretStoreList) private var storeList: SecretStoreList @Environment(\.secretStoreList) private var storeList: SecretStoreList
@ -106,7 +106,7 @@ extension ContentView {
if let modifiable = storeList.modifiableStore { if let modifiable = storeList.modifiableStore {
CreateSecretView(store: modifiable, showing: $showingCreation) CreateSecretView(store: modifiable, showing: $showingCreation)
.onDisappear { .onDisappear {
guard let newest = modifiable.secrets.last?.id else { return } guard let newest = modifiable.secrets.last else { return }
activeSecret = newest activeSecret = newest
} }
} }

View File

@ -3,30 +3,16 @@ import SecretKit
struct EmptyStoreView: View { struct EmptyStoreView: View {
@State var store: AnySecretStore @State var store: AnySecretStore?
@Binding var activeSecret: AnySecret.ID?
var body: some View { var body: some View {
if store is AnySecretStoreModifiable { if store is AnySecretStoreModifiable {
NavigationLink(destination: EmptyStoreModifiableView(), tag: Constants.emptyStoreModifiableTag, selection: $activeSecret) { EmptyStoreModifiableView()
Text("empty_store_modifiable_title")
}
} else { } else {
NavigationLink(destination: EmptyStoreImmutableView(), tag: Constants.emptyStoreTag, selection: $activeSecret) { EmptyStoreImmutableView()
Text("empty_store_nonmodifiable_title")
} }
} }
} }
}
extension EmptyStoreView {
enum Constants {
static let emptyStoreModifiableTag = "emptyStoreModifiableTag"
static let emptyStoreTag = "emptyStoreTag"
}
}
struct EmptyStoreImmutableView: View { struct EmptyStoreImmutableView: View {

View File

@ -3,7 +3,7 @@ import SecretKit
struct SecretDetailView<SecretType: Secret>: View { struct SecretDetailView<SecretType: Secret>: View {
@State var secret: SecretType let secret: SecretType
private let keyWriter = OpenSSHKeyWriter() private let keyWriter = OpenSSHKeyWriter()
private let publicKeyFileStoreController = PublicKeyFileStoreController(homeDirectory: NSHomeDirectory().replacingOccurrences(of: Bundle.main.hostBundleID, with: Bundle.main.agentBundleID)) private let publicKeyFileStoreController = PublicKeyFileStoreController(homeDirectory: NSHomeDirectory().replacingOccurrences(of: Bundle.main.hostBundleID, with: Bundle.main.agentBundleID))
@ -47,12 +47,12 @@ struct SecretDetailView<SecretType: Secret>: View {
} }
//#if DEBUG #if DEBUG
//
//struct SecretDetailView_Previews: PreviewProvider { struct SecretDetailView_Previews: PreviewProvider {
// static var previews: some View { static var previews: some View {
// SecretDetailView(secret: Preview.Store(numberOfRandomSecrets: 1).secrets[0]) SecretDetailView(secret: Preview.Store(numberOfRandomSecrets: 1).secrets[0])
// } }
//} }
//
//#endif #endif

View File

@ -5,7 +5,6 @@ struct SecretListItemView: View {
@State var store: AnySecretStore @State var store: AnySecretStore
var secret: AnySecret var secret: AnySecret
@Binding var activeSecret: AnySecret.ID?
@State var isDeleting: Bool = false @State var isDeleting: Bool = false
@State var isRenaming: Bool = false @State var isRenaming: Bool = false
@ -13,13 +12,20 @@ struct SecretListItemView: View {
var deletedSecret: (AnySecret) -> Void var deletedSecret: (AnySecret) -> Void
var renamedSecret: (AnySecret) -> Void var renamedSecret: (AnySecret) -> Void
var body: some View { private var showingPopup: Binding<Bool> {
let showingPopupWrapped = Binding( Binding(
get: { isDeleting || isRenaming }, get: { isDeleting || isRenaming },
set: { if $0 == false { isDeleting = false; isRenaming = false } } set: {
if $0 == false {
isDeleting = false
isRenaming = false
}
}
) )
}
return NavigationLink(destination: SecretDetailView(secret: secret), tag: secret.id, selection: $activeSecret) { var body: some View {
NavigationLink(value: secret) {
if secret.requiresAuthentication { if secret.requiresAuthentication {
HStack { HStack {
Text(secret.name) Text(secret.name)
@ -40,7 +46,7 @@ struct SecretListItemView: View {
} }
} }
} }
.popover(isPresented: showingPopupWrapped) { .popover(isPresented: showingPopup) {
if let modifiable = store as? AnySecretStoreModifiable { if let modifiable = store as? AnySecretStoreModifiable {
if isDeleting { if isDeleting {
DeleteSecretView(store: modifiable, secret: secret) { deleted in DeleteSecretView(store: modifiable, secret: secret) { deleted in

View File

@ -55,7 +55,7 @@ struct StepView: View {
.foregroundColor(.green) .foregroundColor(.green)
.frame(width: max(0, ((width - (Constants.padding * 2)) / Double(numberOfSteps - 1)) * Double(currentStep) - (Constants.circleWidth / 2)), height: 5) .frame(width: max(0, ((width - (Constants.padding * 2)) / Double(numberOfSteps - 1)) * Double(currentStep) - (Constants.circleWidth / 2)), height: 5)
HStack { HStack {
ForEach(0..<numberOfSteps) { index in ForEach(Array(0..<numberOfSteps), id: \.self) { index in
ZStack { ZStack {
if currentStep > index { if currentStep > index {
Circle() Circle()

View File

@ -4,7 +4,7 @@ import SecretKit
struct StoreListView: View { struct StoreListView: View {
@Binding var activeSecret: AnySecret.ID? @Binding var activeSecret: AnySecret?
@Environment(SecretStoreList.self) private var storeList: SecretStoreList @Environment(SecretStoreList.self) private var storeList: SecretStoreList
@ -13,25 +13,24 @@ struct StoreListView: View {
} }
private func secretRenamed(secret: AnySecret) { private func secretRenamed(secret: AnySecret) {
activeSecret = secret.id activeSecret = secret
} }
var body: some View { var body: some View {
NavigationView { NavigationSplitView {
List(selection: $activeSecret) { List(selection: $activeSecret) {
ForEach(storeList.stores) { store in ForEach(storeList.stores) { store in
if store.isAvailable { if store.isAvailable {
Section(header: Text(store.name)) { Section(header: Text(store.name)) {
if store.secrets.isEmpty { if store.secrets.isEmpty {
EmptyStoreView(store: store, activeSecret: $activeSecret) EmptyStoreView(store: store)
} else { } else {
ForEach(store.secrets) { secret in ForEach(store.secrets) { secret in
SecretListItemView( SecretListItemView(
store: store, store: store,
secret: secret, secret: secret,
activeSecret: $activeSecret, deletedSecret: secretDeleted,
deletedSecret: self.secretDeleted, renamedSecret: secretRenamed
renamedSecret: self.secretRenamed
) )
} }
} }
@ -39,25 +38,26 @@ struct StoreListView: View {
} }
} }
} }
.listStyle(SidebarListStyle()) } detail: {
if let activeSecret {
SecretDetailView(secret: activeSecret)
} else {
EmptyStoreView(store: storeList.stores.first)
}
}
.navigationSplitViewStyle(.balanced)
.onAppear { .onAppear {
activeSecret = nextDefaultSecret activeSecret = nextDefaultSecret
} }
.frame(minWidth: 100, idealWidth: 240) .frame(minWidth: 100, idealWidth: 240)
}
} }
} }
extension StoreListView { extension StoreListView {
var nextDefaultSecret: AnyHashable? { private var nextDefaultSecret: AnySecret? {
let fallback: AnyHashable return storeList.stores.compactMap(\.secrets.first).first
if storeList.modifiableStore?.isAvailable ?? false {
fallback = EmptyStoreView.Constants.emptyStoreModifiableTag
} else {
fallback = EmptyStoreView.Constants.emptyStoreTag
}
return storeList.stores.compactMap(\.secrets.first).first?.id ?? fallback
} }
} }