mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-04-10 17:47:19 +00:00
Lots more SwiftUI cleanup.
This commit is contained in:
parent
c2fc71d299
commit
54d7fbe88d
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user