Setup changes.

This commit is contained in:
Max Goedjen 2020-09-18 16:17:28 -07:00
parent 4c671472ae
commit bbd167ab04
No known key found for this signature in database
GPG Key ID: E58C21DD77B9B8E8
3 changed files with 67 additions and 39 deletions

View File

@ -17,29 +17,20 @@ struct Secretive: App {
@State private var showingSetup = false @State private var showingSetup = false
@State private var showingCreation = false @State private var showingCreation = false
@AppStorage("defaultsHasRunSetup") var hasRunSetup = false
@SceneBuilder var body: some Scene { @SceneBuilder var body: some Scene {
WindowGroup { WindowGroup {
ContentView<Updater, AgentStatusChecker>(showingCreation: $showingCreation, runningSetup: $showingSetup) ContentView<Updater, AgentStatusChecker>(showingCreation: $showingCreation, runningSetup: $showingSetup, hasRunSetup: $hasRunSetup)
.environmentObject(storeList) .environmentObject(storeList)
.environmentObject(Updater(checkOnLaunch: hasRunSetup)) .environmentObject(Updater(checkOnLaunch: hasRunSetup))
.environmentObject(agentStatusChecker) .environmentObject(agentStatusChecker)
.sheet(isPresented: $showingSetup) {
SetupView { completed in
showingSetup = false
hasRunSetup = completed
}
}
.onAppear { .onAppear {
if !hasRunSetup { if !hasRunSetup {
showingSetup = true showingSetup = true
} } else if agentStatusChecker.running && justUpdatedChecker.justUpdated {
if agentStatusChecker.running && justUpdatedChecker.justUpdated {
// Relaunch the agent, since it'll be running from earlier update still // Relaunch the agent, since it'll be running from earlier update still
_ = LaunchAgentController().install() _ = LaunchAgentController().install()
} }
} }
} }
.commands { .commands {
@ -55,7 +46,7 @@ struct Secretive: App {
} }
} }
CommandGroup(after: .help) { CommandGroup(after: .help) {
Button("Setup Secret Agent") { Button("Setup Secretive") {
showingSetup = true showingSetup = true
} }
} }

View File

@ -6,6 +6,7 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
@Binding var showingCreation: Bool @Binding var showingCreation: Bool
@Binding var runningSetup: Bool @Binding var runningSetup: Bool
@Binding var hasRunSetup: Bool
@EnvironmentObject private var storeList: SecretStoreList @EnvironmentObject private var storeList: SecretStoreList
@EnvironmentObject private var updater: UpdaterType @EnvironmentObject private var updater: UpdaterType
@ -29,7 +30,7 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
.frame(minWidth: 640, minHeight: 320) .frame(minWidth: 640, minHeight: 320)
.toolbar { .toolbar {
updateNotice updateNotice
agentNotice setupNotice
newItem newItem
} }
} }
@ -81,8 +82,8 @@ extension ContentView {
} }
} }
var agentNotice: ToolbarItem<Void, AnyView> { var setupNotice: ToolbarItem<Void, AnyView> {
guard !agentStatusChecker.running else { guard runningSetup || !hasRunSetup || !agentStatusChecker.running else {
return ToolbarItem { AnyView(Spacer()) } return ToolbarItem { AnyView(Spacer()) }
} }
return ToolbarItem { return ToolbarItem {
@ -90,12 +91,24 @@ extension ContentView {
Button(action: { Button(action: {
runningSetup = true runningSetup = true
}, label: { }, label: {
Text("Secret Agent Is Not Running") Group {
.font(.headline) if hasRunSetup && !agentStatusChecker.running {
.foregroundColor(.white) Text("Secret Agent Is Not Running")
} else {
Text("Setup Secretive")
}
}
.font(.headline)
.foregroundColor(.white)
}) })
.background(Color.orange) .background(Color.orange)
.cornerRadius(5) .cornerRadius(5)
.popover(isPresented: $runningSetup, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) {
SetupView { completed in
runningSetup = false
hasRunSetup = completed
}
}
) )
} }
} }

View File

@ -4,32 +4,37 @@ import SwiftUI
struct SetupView: View { struct SetupView: View {
var completion: ((Bool) -> Void)? var completion: ((Bool) -> Void)?
@State var completedSteps: Set<Step> = []
var body: some View { var body: some View {
Form { Form {
SetupStepView<Spacer>(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.", SetupStepView<Spacer>(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, nestedView: nil,
actionText: "Install") { 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.", 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.",
index: 2, stepID: .shellConfig,
nestedView: SetupStepCommandView(instructions: Constants.socketPrompts, selectedShellInstruction: Constants.socketPrompts.first!), nestedView: SetupStepCommandView(instructions: Constants.socketPrompts, selectedShellInstruction: Constants.socketPrompts.first!),
actionText: "Added") { actionText: "Added") {
markAsDone() markAsDone(.shellConfig)
} }
SetupStepView<Spacer>(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.", SetupStepView<Link>(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, stepID: .updateNotice,
nestedView: nil, nestedView: Link("Read more about this here.", destination: Constants.updaterFAQURL),
actionText: "Got it") { actionText: "Got it") {
markAsDone() markAsDone(.updateNotice)
} }
HStack { HStack {
Spacer() Spacer()
Button(action: { completion?(true) }) { Button("Finish") {
Text("Finish") completion?(completedAllSteps)
} }.disabled(!completedAllSteps)
.padding() .padding()
} }
}.frame(minWidth: 640, minHeight: 400) }.frame(minWidth: 640, minHeight: 400)
@ -40,7 +45,7 @@ struct SetupView: View {
struct SetupStepView<NestedViewType: View>: View { struct SetupStepView<NestedViewType: View>: View {
let text: String let text: String
let index: Int let stepID: Step
let nestedView: NestedViewType? let nestedView: NestedViewType?
@State var completed = false @State var completed = false
let actionText: String let actionText: String
@ -59,7 +64,7 @@ struct SetupStepView<NestedViewType: View>: View {
} else { } else {
Circle().foregroundColor(.blue) Circle().foregroundColor(.blue)
.frame(width: 30, height: 30) .frame(width: 30, height: 30)
Text(String(describing: index)) Text(String(describing: stepID.rawValue + 1))
.foregroundColor(.white) .foregroundColor(.white)
.bold() .bold()
} }
@ -74,11 +79,10 @@ struct SetupStepView<NestedViewType: View>: View {
} }
} }
.padding() .padding()
Button(action: { Button(actionText) {
completed = action() completed = action()
}) { }.frame(alignment: .trailing)
Text(actionText) .disabled(completed)
}.disabled(completed)
.padding() .padding()
} }
} }
@ -131,9 +135,14 @@ extension SetupView {
LaunchAgentController().install() LaunchAgentController().install()
} }
func markAsDone() -> Bool { func markAsDone(_ step: Step) -> Bool {
completedSteps.insert(step)
return true 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: "bash", text: "export SSH_AUTH_SOCK=\(socketPath)"),
ShellConfigInstruction(shell: "fish", text: "set -x 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 #if DEBUG
struct SetupView_Previews: PreviewProvider { struct SetupView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
SetupView() Group {
SetupView()
SetupView()
.frame(width: 1500, height: 400)
}
} }
} }