diff --git a/Sources/Secretive.xcodeproj/project.pbxproj b/Sources/Secretive.xcodeproj/project.pbxproj index 58b67b3..88ed6a8 100644 --- a/Sources/Secretive.xcodeproj/project.pbxproj +++ b/Sources/Secretive.xcodeproj/project.pbxproj @@ -295,7 +295,7 @@ path = Helpers; sourceTree = ""; }; - 504788ED2E681EB200B4556F /* Styles */ = { + 504788ED2E681EB200B4556F /* Modifiers */ = { isa = PBXGroup; children = ( 50E4C4522E73C78900C73783 /* WindowBackgroundStyle.swift */, @@ -304,7 +304,7 @@ 504789222E697DD300B4556F /* BoxBackgroundStyle.swift */, 5065E312295517C500E16645 /* ToolbarButtonStyle.swift */, ); - path = Styles; + path = Modifiers; sourceTree = ""; }; 504788EE2E681EC300B4556F /* Secrets */ = { @@ -435,7 +435,7 @@ children = ( 504788EF2E681ED700B4556F /* Configuration */, 504788EE2E681EC300B4556F /* Secrets */, - 504788ED2E681EB200B4556F /* Styles */, + 504788ED2E681EB200B4556F /* Modifiers */, 504788F02E681F0100B4556F /* Views */, ); path = Views; diff --git a/Sources/Secretive/App.swift b/Sources/Secretive/App.swift index 64cc298..d88ce53 100644 --- a/Sources/Secretive/App.swift +++ b/Sources/Secretive/App.swift @@ -4,54 +4,17 @@ import SecureEnclaveSecretKit import SmartCardSecretKit import Brief -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() - let cryptoKit = SecureEnclave.Store() - let migrator = SecureEnclave.CryptoKitMigrator() - try? migrator.migrate(to: cryptoKit) - list.add(store: cryptoKit) - list.add(store: SmartCard.Store()) - return list - }() - - private static let _agentStatusChecker = AgentStatusChecker() - @Entry var agentStatusChecker: any AgentStatusCheckerProtocol = _agentStatusChecker - private static let _updater: any UpdaterProtocol = { - @AppStorage("defaultsHasRunSetup") var hasRunSetup = false - return Updater(checkOnLaunch: hasRunSetup) - }() - @Entry var updater: any UpdaterProtocol = _updater - - private static let _justUpdatedChecker = JustUpdatedChecker() - @Entry var justUpdatedChecker: any JustUpdatedCheckerProtocol = _justUpdatedChecker - - @MainActor var secretStoreList: SecretStoreList { - EnvironmentValues._secretStoreList - } -} - @main struct Secretive: App { @Environment(\.agentStatusChecker) var agentStatusChecker @Environment(\.justUpdatedChecker) var justUpdatedChecker @AppStorage("defaultsHasRunSetup") var hasRunSetup = false - @State private var showingSetup = false - @State private var showingIntegrations = false - @State private var showingCreation = false @SceneBuilder var body: some Scene { WindowGroup { - ContentView(showingCreation: $showingCreation, runningSetup: $showingSetup, hasRunSetup: $hasRunSetup) + ContentView() .environment(EnvironmentValues._secretStoreList) - .onAppear { - if !hasRunSetup { - showingSetup = true - } - } .onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in guard hasRunSetup else { return } agentStatusChecker.check() @@ -62,25 +25,41 @@ struct Secretive: App { forceLaunchAgent() } } - .sheet(isPresented: $showingIntegrations) { - IntegrationsView() - } } .commands { + AppCommands() + } + WindowGroup(id: String(describing: IntegrationsView.self)) { + IntegrationsView() + } + } + +} + +extension Secretive { + + struct AppCommands: Commands { + + @Environment(\.openWindow) var openWindow + @Environment(\.openURL) var openURL + @FocusedValue(\.showCreateSecret) var showCreateSecret + + var body: some Commands { CommandGroup(before: CommandGroupPlacement.appSettings) { Button(.integrationsMenuBarTitle, systemImage: "app.connected.to.app.below.fill") { - showingIntegrations = true + openWindow(id: String(describing: IntegrationsView.self)) } } CommandGroup(after: CommandGroupPlacement.newItem) { - Button(.appMenuNewSecretButton) { - showingCreation = true + Button(.appMenuNewSecretButton, systemImage: "plus") { + showCreateSecret?() } .keyboardShortcut(KeyboardShortcut(KeyEquivalent("N"), modifiers: [.command, .shift])) + .disabled(showCreateSecret?.isEnabled == false) } CommandGroup(replacing: .help) { Button(.appMenuHelpButton) { - NSWorkspace.shared.open(Constants.helpURL) + openURL(Constants.helpURL) } } SidebarCommands() @@ -113,8 +92,56 @@ extension Secretive { } - private enum Constants { static let helpURL = URL(string: "https://github.com/maxgoedjen/secretive/blob/main/FAQ.md")! } + +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() + let cryptoKit = SecureEnclave.Store() + let migrator = SecureEnclave.CryptoKitMigrator() + try? migrator.migrate(to: cryptoKit) + list.add(store: cryptoKit) + list.add(store: SmartCard.Store()) + return list + }() + + private static let _agentStatusChecker = AgentStatusChecker() + @Entry var agentStatusChecker: any AgentStatusCheckerProtocol = _agentStatusChecker + private static let _updater: any UpdaterProtocol = { + @AppStorage("defaultsHasRunSetup") var hasRunSetup = false + return Updater(checkOnLaunch: hasRunSetup) + }() + @Entry var updater: any UpdaterProtocol = _updater + + private static let _justUpdatedChecker = JustUpdatedChecker() + @Entry var justUpdatedChecker: any JustUpdatedCheckerProtocol = _justUpdatedChecker + + @MainActor var secretStoreList: SecretStoreList { + EnvironmentValues._secretStoreList + } +} + +extension FocusedValues { + @Entry var showCreateSecret: OpenSheet? +} + +final class OpenSheet { + + let closure: () -> Void + let isEnabled: Bool + + init(isEnabled: Bool = true, closure: @escaping () -> Void) { + self.isEnabled = isEnabled + self.closure = closure + } + + func callAsFunction() { + closure() + } + +} diff --git a/Sources/Secretive/Views/Styles/ActionButtonStyle.swift b/Sources/Secretive/Views/Modifiers/ActionButtonStyle.swift similarity index 100% rename from Sources/Secretive/Views/Styles/ActionButtonStyle.swift rename to Sources/Secretive/Views/Modifiers/ActionButtonStyle.swift diff --git a/Sources/Secretive/Views/Styles/BoxBackgroundStyle.swift b/Sources/Secretive/Views/Modifiers/BoxBackgroundStyle.swift similarity index 100% rename from Sources/Secretive/Views/Styles/BoxBackgroundStyle.swift rename to Sources/Secretive/Views/Modifiers/BoxBackgroundStyle.swift diff --git a/Sources/Secretive/Views/Styles/ErrorStyle.swift b/Sources/Secretive/Views/Modifiers/ErrorStyle.swift similarity index 100% rename from Sources/Secretive/Views/Styles/ErrorStyle.swift rename to Sources/Secretive/Views/Modifiers/ErrorStyle.swift diff --git a/Sources/Secretive/Views/Styles/ToolbarButtonStyle.swift b/Sources/Secretive/Views/Modifiers/ToolbarButtonStyle.swift similarity index 100% rename from Sources/Secretive/Views/Styles/ToolbarButtonStyle.swift rename to Sources/Secretive/Views/Modifiers/ToolbarButtonStyle.swift diff --git a/Sources/Secretive/Views/Styles/WindowBackgroundStyle.swift b/Sources/Secretive/Views/Modifiers/WindowBackgroundStyle.swift similarity index 100% rename from Sources/Secretive/Views/Styles/WindowBackgroundStyle.swift rename to Sources/Secretive/Views/Modifiers/WindowBackgroundStyle.swift diff --git a/Sources/Secretive/Views/Views/ContentView.swift b/Sources/Secretive/Views/Views/ContentView.swift index 117d0d8..822c318 100644 --- a/Sources/Secretive/Views/Views/ContentView.swift +++ b/Sources/Secretive/Views/Views/ContentView.swift @@ -6,9 +6,9 @@ import Brief struct ContentView: View { - @Binding var showingCreation: Bool - @Binding var runningSetup: Bool - @Binding var hasRunSetup: Bool + @AppStorage("defaultsHasRunSetup") var hasRunSetup = false + @State var showingCreation = false + @State var runningSetup = true @State var showingAgentInfo = false @State var activeSecret: AnySecret? @Environment(\.colorScheme) var colorScheme @@ -35,6 +35,23 @@ struct ContentView: View { toolbarItem(appPathNoticeView, id: "appPath") toolbarItem(newItemView, id: "new") } + .onAppear { + if !hasRunSetup { + runningSetup = true + } + } + .focusedSceneValue(\.showCreateSecret, .init(isEnabled: !runningSetup) { + showingCreation = true + }) + .sheet(isPresented: $showingCreation) { + if let modifiable = storeList.modifiableStore { + CreateSecretView(store: modifiable) { created in + if let created { + activeSecret = created + } + } + } + } .sheet(isPresented: $runningSetup) { SetupView(setupComplete: $hasRunSetup) } @@ -114,15 +131,6 @@ extension ContentView { showingCreation = true } .menuButton() - .sheet(isPresented: $showingCreation) { - if let modifiable = storeList.modifiableStore { - CreateSecretView(store: modifiable) { created in - if let created { - activeSecret = created - } - } - } - } } }