Lots more SwiftUI cleanup.

This commit is contained in:
Max Goedjen 2020-09-10 23:17:03 -07:00
parent c2fc71d299
commit 54d7fbe88d
No known key found for this signature in database
GPG Key ID: E58C21DD77B9B8E8
6 changed files with 82 additions and 86 deletions

View File

@ -21,14 +21,14 @@ struct AppDelegate: App {
@SceneBuilder var body: some Scene {
WindowGroup {
ContentView<Updater, AgentStatusChecker>()
ContentView<Updater, AgentStatusChecker>(runningSetup: $showingSetup)
.environmentObject(storeList)
.environmentObject(updater)
.environmentObject(agentStatusChecker)
.sheet(isPresented: $showingSetup) {
SetupView { completed in
self.showingSetup = false
self.hasRunSetup = completed
showingSetup = false
hasRunSetup = completed
}
}
.onAppear {
@ -51,7 +51,7 @@ struct AppDelegate: App {
}
CommandGroup(after: .help) {
Button("Setup Secret Agent") {
self.showingSetup = true
showingSetup = true
}
}
}

View File

@ -7,39 +7,40 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
@EnvironmentObject var storeList: SecretStoreList
@EnvironmentObject var updater: UpdaterType
@EnvironmentObject var agentStatusChecker: AgentStatusCheckerType
var runSetupBlock: (() -> Void)?
@State private var active: AnySecret.ID?
@State private var showingCreation = false
@State private var deletingSecret: AnySecret?
@State private var selectedUpdate: Release?
@Binding var runningSetup: Bool
var body: some View {
VStack {
if storeList.anyAvailable {
NavigationView {
List(selection: $active) {
ForEach(storeList.stores) { store in
if store.isAvailable {
Section(header: Text(store.name)) {
if store.secrets.isEmpty {
if store is AnySecretStoreModifiable {
NavigationLink(destination: EmptyStoreModifiableView(), tag: Constants.emptyStoreModifiableTag, selection: self.$active) {
Text("No Secrets")
NavigationView {
List(selection: $active) {
ForEach(storeList.stores) { store in
if store.isAvailable {
Section(header: Text(store.name)) {
if store.secrets.isEmpty {
if store is AnySecretStoreModifiable {
NavigationLink(destination: EmptyStoreModifiableView(), tag: Constants.emptyStoreModifiableTag, selection: $active) {
Text("No Secrets")
}
} else {
NavigationLink(destination: EmptyStoreView(), tag: Constants.emptyStoreTag, selection: $active) {
Text("No Secrets")
}
}
} else {
NavigationLink(destination: EmptyStoreView(), tag: Constants.emptyStoreTag, selection: self.$active) {
Text("No Secrets")
}
}
} else {
ForEach(store.secrets) { secret in
NavigationLink(destination: SecretDetailView(secret: secret), tag: secret.id, selection: self.$active) {
Text(secret.name)
}.contextMenu {
if store is AnySecretStoreModifiable {
Button(action: { self.delete(secret: secret) }) {
Text("Delete")
ForEach(store.secrets) { secret in
NavigationLink(destination: SecretDetailView(secret: secret), tag: secret.id, selection: $active) {
Text(secret.name)
}.contextMenu {
if store is AnySecretStoreModifiable {
Button(action: { delete(secret: secret) }) {
Text("Delete")
}
}
}
}
@ -47,42 +48,35 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
}
}
}
}.onAppear {
active = nextDefaultSecret
}
}.onAppear {
self.active = self.nextDefaultSecret
}
.frame(minWidth: 100, idealWidth: 240)
.sheet(item: $deletingSecret) { secret in
if self.storeList.modifiableStore != nil {
DeleteSecretView(secret: secret, store: self.storeList.modifiableStore!) { deleted in
self.deletingSecret = nil
if deleted {
self.active = self.nextDefaultSecret
.frame(minWidth: 100, idealWidth: 240)
.sheet(item: $deletingSecret) { secret in
if storeList.modifiableStore != nil {
DeleteSecretView(secret: secret, store: storeList.modifiableStore!) { deleted in
deletingSecret = nil
if deleted {
active = nextDefaultSecret
}
}
}
}
}
}
} else {
NoStoresView()
}
}
.sheet(isPresented: $showingCreation) {
CreateSecretView {
self.showingCreation = false
}
CreateSecretView(showing: $showingCreation)
}
.frame(minWidth: 640, minHeight: 320)
.toolbar {
// if updater.update != nil {
updateNotice()
// }
// if !agentStatusChecker.running {
// agentNotice()z
// }
updateNotice
agentNotice
ToolbarItem {
Button(action: {
self.showingCreation = true
showingCreation = true
}, label: {
Image(systemName: "plus")
})
@ -90,12 +84,9 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
}
}
func updateNotice() -> ToolbarItem<Void, AnyView> {
// let update = updater.update ?? Release(name: "", html_url: URL(string:"https://example.com")!, body: "")
var updateNotice: ToolbarItem<Void, AnyView> {
guard let update = updater.update else {
return ToolbarItem {
AnyView(Spacer())
}
return ToolbarItem { AnyView(Spacer()) }
}
let color: Color
let text: String
@ -108,7 +99,7 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
}
return ToolbarItem {
AnyView(Button(action: {
self.selectedUpdate = update
selectedUpdate = update
}, label: {
Text(text)
.font(.headline)
@ -122,20 +113,25 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
)
}
}
//
// func agentNotice() -> ToolbarItem<Void, AnyView> {
// ToolbarItem {
// Button(action: {
// self.runSetupBlock?()
// }, label: {
// Text("Agent is not running.")
// .font(.headline)
// .foregroundColor(.white)
// })
// .background(Color.orange)
// .cornerRadius(5)
// }
// }
var agentNotice: ToolbarItem<Void, AnyView> {
guard agentStatusChecker.running else {
return ToolbarItem { AnyView(Spacer()) }
}
return ToolbarItem {
AnyView(
Button(action: {
runningSetup = true
}, label: {
Text("Secret Agent Is Not Running")
.font(.headline)
.foregroundColor(.white)
})
.background(Color.orange)
.cornerRadius(5)
)
}
}
func delete<SecretType: Secret>(secret: SecretType) {
deletingSecret = AnySecret(secret)
@ -143,12 +139,12 @@ struct ContentView<UpdaterType: UpdaterProtocol, AgentStatusCheckerType: AgentSt
var nextDefaultSecret: AnyHashable? {
let fallback: AnyHashable
if self.storeList.modifiableStore?.isAvailable ?? false {
if storeList.modifiableStore?.isAvailable ?? false {
fallback = Constants.emptyStoreModifiableTag
} else {
fallback = Constants.emptyStoreTag
}
return self.storeList.stores.compactMap(\.secrets.first).first?.id ?? fallback
return storeList.stores.compactMap(\.secrets.first).first?.id ?? fallback
}
}

View File

@ -7,9 +7,8 @@ struct CreateSecretView: View {
@State var name = ""
@State var requiresAuthentication = true
var dismissalBlock: () -> ()
@Binding var showing: Bool
var body: some View {
VStack {
HStack {
@ -36,8 +35,10 @@ struct CreateSecretView: View {
}
HStack {
Spacer()
Button("Cancel", action: dismissalBlock)
.keyboardShortcut(.cancelAction)
Button("Cancel") {
showing = false
}
.keyboardShortcut(.cancelAction)
Button("Create", action: save)
.disabled(name.isEmpty)
.keyboardShortcut(.defaultAction)
@ -47,6 +48,6 @@ struct CreateSecretView: View {
func save() {
try! store.create(name: name, requiresAuthentication: requiresAuthentication)
dismissalBlock()
showing = false
}
}

View File

@ -38,7 +38,7 @@ struct DeleteSecretView<StoreType: SecretStoreModifiable>: View {
}
}
.onExitCommand {
self.dismissalBlock(false)
dismissalBlock(false)
}
}
HStack {
@ -47,7 +47,7 @@ struct DeleteSecretView<StoreType: SecretStoreModifiable>: View {
.disabled(confirm != secret.name)
.keyboardShortcut(.delete)
Button("Don't Delete") {
self.dismissalBlock(false)
dismissalBlock(false)
}
.keyboardShortcut(.cancelAction)
}
@ -58,6 +58,6 @@ struct DeleteSecretView<StoreType: SecretStoreModifiable>: View {
func delete() {
try! store.delete(secret: secret)
self.dismissalBlock(true)
dismissalBlock(true)
}
}

View File

@ -17,7 +17,7 @@ struct SecretDetailView<SecretType: Secret>: View {
.frame(minWidth: 150, maxWidth: .infinity)
.padding()
}.onDrag {
return NSItemProvider(item: NSData(data: self.keyWriter.openSSHFingerprint(secret: self.secret).data(using: .utf8)!), typeIdentifier: kUTTypeUTF8PlainText as String)
return NSItemProvider(item: NSData(data: keyWriter.openSSHFingerprint(secret: secret).data(using: .utf8)!), typeIdentifier: kUTTypeUTF8PlainText as String)
}
Spacer().frame(height: 10)
GroupBox(label: Text("Public Key")) {
@ -35,7 +35,7 @@ struct SecretDetailView<SecretType: Secret>: View {
.padding()
}
.onDrag {
return NSItemProvider(item: NSData(data: self.keyString.data(using: .utf8)!), typeIdentifier: kUTTypeUTF8PlainText as String)
return NSItemProvider(item: NSData(data: keyString.data(using: .utf8)!), typeIdentifier: kUTTypeUTF8PlainText as String)
}
Spacer()
}

View File

@ -11,17 +11,17 @@ struct SetupView: View {
index: 1,
nestedView: nil,
actionText: "Install") {
self.installLaunchAgent()
installLaunchAgent()
}
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,
nestedView: SetupStepCommandView(text: Constants.socketPrompt),
actionText: "Added") {
self.markAsDone()
markAsDone()
}
HStack {
Spacer()
Button(action: { self.completion?(true) }) {
Button(action: { completion?(true) }) {
Text("Finish")
}
.padding()
@ -69,7 +69,7 @@ struct SetupStepView<NestedViewType: View>: View {
}
.padding()
Button(action: {
self.completed = self.action()
completed = action()
}) {
Text(actionText)
}.disabled(completed)
@ -101,8 +101,7 @@ struct SetupStepCommandView: View {
.background(Color(white: 0, opacity: 0.10))
.cornerRadius(10)
.onDrag {
return NSItemProvider(item: NSData(data: self.text.data(using: .utf8)!), typeIdentifier: kUTTypeUTF8PlainText as String)
return NSItemProvider(item: NSData(data: text.data(using: .utf8)!), typeIdentifier: kUTTypeUTF8PlainText as String)
}
}