diff --git a/Secretive/App.swift b/Secretive/App.swift index 245eb29..d01593b 100644 --- a/Secretive/App.swift +++ b/Secretive/App.swift @@ -17,29 +17,20 @@ struct Secretive: App { @State private var showingSetup = false @State private var showingCreation = false - @AppStorage("defaultsHasRunSetup") var hasRunSetup = false @SceneBuilder var body: some Scene { WindowGroup { - ContentView(showingCreation: $showingCreation, runningSetup: $showingSetup) + ContentView(showingCreation: $showingCreation, runningSetup: $showingSetup, hasRunSetup: $hasRunSetup) .environmentObject(storeList) .environmentObject(Updater(checkOnLaunch: hasRunSetup)) .environmentObject(agentStatusChecker) - .sheet(isPresented: $showingSetup) { - SetupView { completed in - showingSetup = false - hasRunSetup = completed - } - } .onAppear { if !hasRunSetup { showingSetup = true - } - if agentStatusChecker.running && justUpdatedChecker.justUpdated { + } else if agentStatusChecker.running && justUpdatedChecker.justUpdated { // Relaunch the agent, since it'll be running from earlier update still _ = LaunchAgentController().install() } - } } .commands { @@ -55,7 +46,7 @@ struct Secretive: App { } } CommandGroup(after: .help) { - Button("Setup Secret Agent") { + Button("Setup Secretive") { showingSetup = true } } diff --git a/Secretive/Views/ContentView.swift b/Secretive/Views/ContentView.swift index f94c242..fa2902b 100644 --- a/Secretive/Views/ContentView.swift +++ b/Secretive/Views/ContentView.swift @@ -6,6 +6,7 @@ struct ContentView { - guard !agentStatusChecker.running else { + var setupNotice: ToolbarItem { + guard runningSetup || !hasRunSetup || !agentStatusChecker.running else { return ToolbarItem { AnyView(Spacer()) } } return ToolbarItem { @@ -90,12 +91,24 @@ extension ContentView { Button(action: { runningSetup = true }, label: { - Text("Secret Agent Is Not Running") - .font(.headline) - .foregroundColor(.white) + Group { + if hasRunSetup && !agentStatusChecker.running { + Text("Secret Agent Is Not Running") + } else { + Text("Setup Secretive") + } + } + .font(.headline) + .foregroundColor(.white) }) .background(Color.orange) .cornerRadius(5) + .popover(isPresented: $runningSetup, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) { + SetupView { completed in + runningSetup = false + hasRunSetup = completed + } + } ) } } diff --git a/Secretive/Views/SetupView.swift b/Secretive/Views/SetupView.swift index 8527d90..c561b5e 100644 --- a/Secretive/Views/SetupView.swift +++ b/Secretive/Views/SetupView.swift @@ -4,32 +4,37 @@ import SwiftUI struct SetupView: View { var completion: ((Bool) -> Void)? + @State var completedSteps: Set = [] var body: some View { Form { SetupStepView(text: "Secretive needs to install a helper app to sign requests when the main app isn't running. This app is called \"SecretAgent\" and you might see it in Activity Manager from time to time.", - index: 1, + stepID: .agent, nestedView: nil, actionText: "Install") { - installLaunchAgent() + let success = installLaunchAgent() + if success { + completedSteps.insert(.agent) + } + return success } - SetupStepView(text: "Add this line to your shell config (.bashrc or .zshrc) telling SSH to talk to SecretAgent when it wants to authenticate. Drag this into your config file.", - index: 2, + SetupStepView(text: "Add this line to your shell config telling SSH to talk to SecretAgent when it wants to authenticate. Drag this into your config file.", + stepID: .shellConfig, nestedView: SetupStepCommandView(instructions: Constants.socketPrompts, selectedShellInstruction: Constants.socketPrompts.first!), actionText: "Added") { - markAsDone() + markAsDone(.shellConfig) } - SetupStepView(text: "Secretive will periodically check with GitHub to see if there's a new release. If you see any network requests to GitHub, that's why.", - index: 3, - nestedView: nil, - actionText: "Got it") { - markAsDone() + SetupStepView(text: "Secretive will periodically check with GitHub to see if there's a new release. If you see any network requests to GitHub, that's why.", + stepID: .updateNotice, + nestedView: Link("Read more about this here.", destination: Constants.updaterFAQURL), + actionText: "Got it") { + markAsDone(.updateNotice) } HStack { Spacer() - Button(action: { completion?(true) }) { - Text("Finish") - } + Button("Finish") { + completion?(completedAllSteps) + }.disabled(!completedAllSteps) .padding() } }.frame(minWidth: 640, minHeight: 400) @@ -40,7 +45,7 @@ struct SetupView: View { struct SetupStepView: View { let text: String - let index: Int + let stepID: Step let nestedView: NestedViewType? @State var completed = false let actionText: String @@ -59,7 +64,7 @@ struct SetupStepView: View { } else { Circle().foregroundColor(.blue) .frame(width: 30, height: 30) - Text(String(describing: index)) + Text(String(describing: stepID.rawValue + 1)) .foregroundColor(.white) .bold() } @@ -74,11 +79,10 @@ struct SetupStepView: View { } } .padding() - Button(action: { + Button(actionText) { completed = action() - }) { - Text(actionText) - }.disabled(completed) + }.frame(alignment: .trailing) + .disabled(completed) .padding() } } @@ -131,9 +135,14 @@ extension SetupView { LaunchAgentController().install() } - func markAsDone() -> Bool { + func markAsDone(_ step: Step) -> Bool { + completedSteps.insert(step) return true } + + var completedAllSteps: Bool { + completedSteps == Set(Step.allCases) + } } @@ -146,6 +155,7 @@ extension SetupView { ShellConfigInstruction(shell: "bash", text: "export SSH_AUTH_SOCK=\(socketPath)"), ShellConfigInstruction(shell: "fish", text: "set -x SSH_AUTH_SOCK=\(socketPath)"), ] + static let updaterFAQURL = URL(string: "https://github.com/maxgoedjen/secretive/blob/main/FAQ.md#whats-this-network-request-to-github")! } } @@ -161,11 +171,25 @@ struct ShellConfigInstruction: Identifiable, Hashable { } +enum Step: Int, Identifiable, Hashable, CaseIterable { + + case agent, shellConfig, updateNotice + + var id: Int { + rawValue + } + +} + #if DEBUG struct SetupView_Previews: PreviewProvider { static var previews: some View { - SetupView() + Group { + SetupView() + SetupView() + .frame(width: 1500, height: 400) + } } }