mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-09-16 01:10:56 +00:00
WIP
This commit is contained in:
parent
fa658646d7
commit
9299bf343f
@ -787,6 +787,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Apps" : {
|
||||
|
||||
},
|
||||
"auth_context_persist_for_duration" : {
|
||||
"comment" : "When the user clicks the notification to leave a secret unlocked, they are shown a prompt to approve the action. This is the description, showing which secret will used. The first placeholder is the name of the secret. The second placeholder is a localized description of the time period it will remain unlocked for (eg: \"five minutes\")",
|
||||
@ -1184,7 +1187,7 @@
|
||||
"Configure" : {
|
||||
|
||||
},
|
||||
"Configuring" : {
|
||||
"Copy" : {
|
||||
|
||||
},
|
||||
"copyable_click_to_copy_button" : {
|
||||
@ -3039,6 +3042,15 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Getting Started" : {
|
||||
|
||||
},
|
||||
"Integrations" : {
|
||||
|
||||
},
|
||||
"Integrations..." : {
|
||||
|
||||
},
|
||||
"no_secure_storage_description" : {
|
||||
"extractionState" : "manual",
|
||||
@ -3270,6 +3282,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"other" : {
|
||||
|
||||
},
|
||||
"Other" : {
|
||||
|
||||
},
|
||||
"persist_authentication_accept_button" : {
|
||||
"comment" : "When the user authorizes an action using a secret that requires unlock, they're shown a notification offering to leave the secret unlocked for a set period of time. This is the title for the notification.",
|
||||
@ -5009,6 +5027,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Shell" : {
|
||||
|
||||
},
|
||||
"signed_notification_description" : {
|
||||
"comment" : "When the user performs an action using a secret, they're shown a notification describing what happened. This is the description, showing which secret was used. The placeholder is the name of the secret.",
|
||||
@ -5245,6 +5266,18 @@
|
||||
},
|
||||
"Starting Agent" : {
|
||||
|
||||
},
|
||||
"System" : {
|
||||
|
||||
},
|
||||
"TBD" : {
|
||||
|
||||
},
|
||||
"There's a community-maintained list of instructions for apps on GitHub. If the app you're looking for isn't supported, create an issue and the community may be able to help." : {
|
||||
|
||||
},
|
||||
"There's a community-maintained list of shell instructions on GitHub. If the shell you're looking for isn't supported, create an issue and the community may be able to help." : {
|
||||
|
||||
},
|
||||
"unnamed_secret" : {
|
||||
"extractionState" : "manual",
|
||||
@ -6194,6 +6227,12 @@
|
||||
},
|
||||
"Version" : {
|
||||
|
||||
},
|
||||
"View Documentation on Web" : {
|
||||
|
||||
},
|
||||
"View on GitHub" : {
|
||||
|
||||
}
|
||||
},
|
||||
"version" : "1.0"
|
||||
|
@ -48,7 +48,7 @@
|
||||
5099A02423FD2AAA0062B6F2 /* CreateSecretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5099A02323FD2AAA0062B6F2 /* CreateSecretView.swift */; };
|
||||
50A3B79424026B7600D209EA /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 50A3B79324026B7600D209EA /* Preview Assets.xcassets */; };
|
||||
50A3B79724026B7600D209EA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 50A3B79524026B7600D209EA /* Main.storyboard */; };
|
||||
50AE97002E5C1A420018C710 /* ConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50AE96FF2E5C1A420018C710 /* ConfigurationView.swift */; };
|
||||
50AE97002E5C1A420018C710 /* IntegrationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50AE96FF2E5C1A420018C710 /* IntegrationsView.swift */; };
|
||||
50B8550D24138C4F009958AC /* DeleteSecretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B8550C24138C4F009958AC /* DeleteSecretView.swift */; };
|
||||
50BB046B2418AAAE00D6E079 /* EmptyStoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BB046A2418AAAE00D6E079 /* EmptyStoreView.swift */; };
|
||||
50BDCB722E63BAF20072D2E7 /* AgentStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BDCB712E63BAF20072D2E7 /* AgentStatusView.swift */; };
|
||||
@ -140,7 +140,7 @@
|
||||
50A3B79624026B7600D209EA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
50A3B79824026B7600D209EA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
50A3B79924026B7600D209EA /* SecretAgent.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SecretAgent.entitlements; sourceTree = "<group>"; };
|
||||
50AE96FF2E5C1A420018C710 /* ConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationView.swift; sourceTree = "<group>"; };
|
||||
50AE96FF2E5C1A420018C710 /* IntegrationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationsView.swift; sourceTree = "<group>"; };
|
||||
50B8550C24138C4F009958AC /* DeleteSecretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteSecretView.swift; sourceTree = "<group>"; };
|
||||
50BB046A2418AAAE00D6E079 /* EmptyStoreView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyStoreView.swift; sourceTree = "<group>"; };
|
||||
50BDCB712E63BAF20072D2E7 /* AgentStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AgentStatusView.swift; sourceTree = "<group>"; };
|
||||
@ -261,7 +261,7 @@
|
||||
50153E1F250AFCB200525160 /* UpdateView.swift */,
|
||||
5066A6C12516F303004B5A36 /* SetupView.swift */,
|
||||
50BDCB712E63BAF20072D2E7 /* AgentStatusView.swift */,
|
||||
50AE96FF2E5C1A420018C710 /* ConfigurationView.swift */,
|
||||
50AE96FF2E5C1A420018C710 /* IntegrationsView.swift */,
|
||||
5066A6C72516FE6E004B5A36 /* CopyableView.swift */,
|
||||
50BDCB732E6436C60072D2E7 /* ErrorStyle.swift */,
|
||||
50BDCB752E6450950072D2E7 /* ConfigurationItemView.swift */,
|
||||
@ -457,7 +457,7 @@
|
||||
508A58B3241ED2180069DC07 /* AgentStatusChecker.swift in Sources */,
|
||||
50C385A52407A76D00AF2719 /* SecretDetailView.swift in Sources */,
|
||||
5099A02423FD2AAA0062B6F2 /* CreateSecretView.swift in Sources */,
|
||||
50AE97002E5C1A420018C710 /* ConfigurationView.swift in Sources */,
|
||||
50AE97002E5C1A420018C710 /* IntegrationsView.swift in Sources */,
|
||||
50153E20250AFCB200525160 /* UpdateView.swift in Sources */,
|
||||
50571E0524393D1500F76F6C /* LaunchAgentController.swift in Sources */,
|
||||
5066A6C82516FE6E004B5A36 /* CopyableView.swift in Sources */,
|
||||
@ -659,10 +659,18 @@
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_ENHANCED_SECURITY = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
|
||||
ENABLE_POINTER_AUTHENTICATION = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_USER_SELECTED_FILES = readwrite;
|
||||
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
|
||||
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CAMERA = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_LOCATION = NO;
|
||||
ENABLE_RESOURCE_ACCESS_PRINTING = NO;
|
||||
ENABLE_RESOURCE_ACCESS_USB = NO;
|
||||
INFOPLIST_FILE = Secretive/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -691,10 +699,18 @@
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_ENHANCED_SECURITY = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
|
||||
ENABLE_POINTER_AUTHENTICATION = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_USER_SELECTED_FILES = readwrite;
|
||||
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
|
||||
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CAMERA = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_LOCATION = NO;
|
||||
ENABLE_RESOURCE_ACCESS_PRINTING = NO;
|
||||
ENABLE_RESOURCE_ACCESS_USB = NO;
|
||||
INFOPLIST_FILE = Secretive/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -795,10 +811,18 @@
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_ENHANCED_SECURITY = YES;
|
||||
ENABLE_HARDENED_RUNTIME = NO;
|
||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
|
||||
ENABLE_POINTER_AUTHENTICATION = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_USER_SELECTED_FILES = readwrite;
|
||||
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
|
||||
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CAMERA = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_LOCATION = NO;
|
||||
ENABLE_RESOURCE_ACCESS_PRINTING = NO;
|
||||
ENABLE_RESOURCE_ACCESS_USB = NO;
|
||||
INFOPLIST_FILE = Secretive/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -821,8 +845,17 @@
|
||||
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
|
||||
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CAMERA = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_LOCATION = NO;
|
||||
ENABLE_RESOURCE_ACCESS_PRINTING = NO;
|
||||
ENABLE_RESOURCE_ACCESS_USB = NO;
|
||||
INFOPLIST_FILE = SecretAgent/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -847,8 +880,17 @@
|
||||
DEVELOPMENT_TEAM = Z72PRUAWF6;
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
|
||||
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CAMERA = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_LOCATION = NO;
|
||||
ENABLE_RESOURCE_ACCESS_PRINTING = NO;
|
||||
ENABLE_RESOURCE_ACCESS_USB = NO;
|
||||
INFOPLIST_FILE = SecretAgent/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -874,8 +916,17 @@
|
||||
DEVELOPMENT_TEAM = Z72PRUAWF6;
|
||||
ENABLE_APP_SANDBOX = YES;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
|
||||
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CAMERA = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_LOCATION = NO;
|
||||
ENABLE_RESOURCE_ACCESS_PRINTING = NO;
|
||||
ENABLE_RESOURCE_ACCESS_USB = NO;
|
||||
INFOPLIST_FILE = SecretAgent/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -37,6 +37,7 @@ struct Secretive: App {
|
||||
@Environment(\.agentStatusChecker) var agentStatusChecker
|
||||
@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 {
|
||||
@ -58,8 +59,17 @@ struct Secretive: App {
|
||||
forceLaunchAgent()
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingIntegrations) {
|
||||
IntegrationsView()
|
||||
.frame(minHeight: 400)
|
||||
}
|
||||
}
|
||||
.commands {
|
||||
CommandGroup(before: CommandGroupPlacement.appSettings) {
|
||||
Button("Integrations...", systemImage: "app.connected.to.app.below.fill") {
|
||||
showingIntegrations = true
|
||||
}
|
||||
}
|
||||
CommandGroup(after: CommandGroupPlacement.newItem) {
|
||||
Button(.appMenuNewSecretButton) {
|
||||
showingCreation = true
|
||||
@ -71,11 +81,6 @@ struct Secretive: App {
|
||||
NSWorkspace.shared.open(Constants.helpURL)
|
||||
}
|
||||
}
|
||||
CommandGroup(before: .help) {
|
||||
Button(.appMenuSetupButton) {
|
||||
showingSetup = true
|
||||
}
|
||||
}
|
||||
SidebarCommands()
|
||||
}
|
||||
}
|
||||
|
@ -32,14 +32,19 @@ struct ConfigurationItemView<Content: View>: View {
|
||||
Spacer()
|
||||
switch action {
|
||||
case .copy(let string):
|
||||
Button("Reveal in Finder", systemImage: "folder") {
|
||||
NSWorkspace.shared.selectFile(string, inFileViewerRootedAtPath: string)
|
||||
Button("Copy", systemImage: "document.on.document") {
|
||||
NSPasteboard.general.declareTypes([.string], owner: nil)
|
||||
NSPasteboard.general.setString(string, forType: .string)
|
||||
}
|
||||
.labelStyle(.iconOnly)
|
||||
.buttonStyle(.borderless)
|
||||
case .revealInFinder(let string):
|
||||
case .revealInFinder(let rawPath):
|
||||
Button("Reveal in Finder", systemImage: "folder") {
|
||||
NSWorkspace.shared.selectFile(string, inFileViewerRootedAtPath: string)
|
||||
// All foundation-based normalization methods replace this with the container directly.
|
||||
let processedPath = rawPath.replacingOccurrences(of: "~", with: "/Users/\(NSUserName())")
|
||||
let url = URL(filePath: processedPath)
|
||||
let folder = url.deletingLastPathComponent().path()
|
||||
NSWorkspace.shared.selectFile(processedPath, inFileViewerRootedAtPath: folder)
|
||||
}
|
||||
.labelStyle(.iconOnly)
|
||||
.buttonStyle(.borderless)
|
||||
|
@ -1,82 +0,0 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ConfigurationView: View {
|
||||
|
||||
@Binding var visible: Bool
|
||||
|
||||
|
||||
let buttonAction: () -> Void
|
||||
|
||||
@State private var selectedShellInstruction: ShellConfigInstruction?
|
||||
|
||||
private let socketPath = (NSHomeDirectory().replacingOccurrences(of: Bundle.hostBundleID, with: Bundle.agentBundleID) as NSString).appendingPathComponent("socket.ssh") as String
|
||||
|
||||
private var shellInstructions: [ShellConfigInstruction] {
|
||||
[
|
||||
ShellConfigInstruction(shell: "SSH",
|
||||
shellConfigDirectory: "~/.ssh/",
|
||||
shellConfigFilename: "config",
|
||||
text: "Host *\n\tIdentityAgent \(socketPath)"),
|
||||
ShellConfigInstruction(shell: "zsh",
|
||||
shellConfigDirectory: "~/",
|
||||
shellConfigFilename: ".zshrc",
|
||||
text: "export SSH_AUTH_SOCK=\(socketPath)"),
|
||||
ShellConfigInstruction(shell: "bash",
|
||||
shellConfigDirectory: "~/",
|
||||
shellConfigFilename: ".bashrc",
|
||||
text: "export SSH_AUTH_SOCK=\(socketPath)"),
|
||||
ShellConfigInstruction(shell: "fish",
|
||||
shellConfigDirectory: "~/.config/fish",
|
||||
shellConfigFilename: "config.fish",
|
||||
text: "set -x SSH_AUTH_SOCK \(socketPath)"),
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section {
|
||||
Picker("Configuring", selection: $selectedShellInstruction) {
|
||||
ForEach(shellInstructions) { instruction in
|
||||
Text(instruction.shell)
|
||||
.tag(instruction)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
if let selectedShellInstruction {
|
||||
ConfigurationItemView(title: "Configuration File", value: selectedShellInstruction.shellConfigPath, action: .revealInFinder(selectedShellInstruction.shellConfigPath))
|
||||
ConfigurationItemView(title: "Add This:", action: .copy(selectedShellInstruction.text)) {
|
||||
HStack {
|
||||
Text(selectedShellInstruction.text)
|
||||
.padding(8)
|
||||
.font(.system(.subheadline, design: .monospaced))
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.fill(.black.opacity(0.05))
|
||||
.stroke(.separator, lineWidth: 1)
|
||||
}
|
||||
|
||||
}
|
||||
Button("setup_ssh_add_for_me_button") {
|
||||
}
|
||||
}
|
||||
} footer: {
|
||||
Link("setup_third_party_faq_link", destination: URL(string: "https://github.com/maxgoedjen/secretive/blob/main/APP_CONFIG.md")!)
|
||||
}
|
||||
}
|
||||
.formStyle(.grouped)
|
||||
.onAppear {
|
||||
selectedShellInstruction = shellInstructions.first
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ConfigurationView(visible: .constant(true)) {}
|
||||
.frame(width: 400, height: 300)
|
||||
}
|
@ -36,7 +36,7 @@ struct ContentView: View {
|
||||
toolbarItem(newItemView, id: "new")
|
||||
}
|
||||
.sheet(isPresented: $runningSetup) {
|
||||
SetupView(visible: $runningSetup, setupComplete: $hasRunSetup)
|
||||
SetupView(setupComplete: $hasRunSetup)
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ extension ContentView {
|
||||
.normal()
|
||||
.sheet(isPresented: $showingCreation) {
|
||||
if let modifiable = storeList.modifiableStore {
|
||||
CreateSecretView(store: modifiable, showing: $showingCreation) { created in
|
||||
CreateSecretView(store: modifiable) { created in
|
||||
if let created {
|
||||
activeSecret = created
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import SecretKit
|
||||
struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
|
||||
@State var store: StoreType
|
||||
@Binding var showing: Bool
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
var createdSecret: (AnySecret?) -> Void
|
||||
|
||||
@State private var name = ""
|
||||
@ -109,7 +109,7 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
.toggleStyle(.button)
|
||||
Spacer()
|
||||
Button(.createSecretCancelButton, role: .cancel) {
|
||||
showing = false
|
||||
dismiss()
|
||||
}
|
||||
Button(.createSecretCreateButton, action: save)
|
||||
.keyboardShortcut(.return)
|
||||
@ -137,7 +137,7 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
)
|
||||
)
|
||||
createdSecret(AnySecret(new))
|
||||
showing = false
|
||||
dismiss()
|
||||
} catch {
|
||||
errorText = error.localizedDescription
|
||||
}
|
||||
@ -147,5 +147,5 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
}
|
||||
|
||||
#Preview {
|
||||
CreateSecretView(store: Preview.StoreModifiable(), showing: .constant(true)) { _ in }
|
||||
CreateSecretView(store: Preview.StoreModifiable()) { _ in }
|
||||
}
|
||||
|
192
Sources/Secretive/Views/IntegrationsView.swift
Normal file
192
Sources/Secretive/Views/IntegrationsView.swift
Normal file
@ -0,0 +1,192 @@
|
||||
import SwiftUI
|
||||
|
||||
struct IntegrationsView: View {
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@State private var selectedInstruction: ConfigurationFileInstructions?
|
||||
|
||||
private let socketPath = (NSHomeDirectory().replacingOccurrences(of: Bundle.hostBundleID, with: Bundle.agentBundleID) as NSString).appendingPathComponent("socket.ssh") as String
|
||||
|
||||
private var instructions: [ConfigurationGroup] {
|
||||
[
|
||||
ConfigurationGroup(name:"Integrations", instructions: [
|
||||
ConfigurationFileInstructions("Getting Started", id: .gettingStarted),
|
||||
]),
|
||||
ConfigurationGroup(name: "System", instructions: [
|
||||
ConfigurationFileInstructions(
|
||||
tool: "ssh",
|
||||
configPath: "~/.ssh/config",
|
||||
configText: "Host *\n\tIdentityAgent \(socketPath)",
|
||||
website: URL(string: "https://man.openbsd.org/ssh_config.5")!,
|
||||
),
|
||||
ConfigurationFileInstructions(
|
||||
tool: "git",
|
||||
configPath: "~/.gitconfig",
|
||||
configText: "PLACEHOLDER",
|
||||
website: URL(string: "https://git-scm.com/docs/git-config")!
|
||||
)
|
||||
]),
|
||||
ConfigurationGroup(name: "Shell", instructions: [
|
||||
ConfigurationFileInstructions(
|
||||
tool: "zsh",
|
||||
configPath: "~/.zshrc",
|
||||
configText: "export SSH_AUTH_SOCK=\(socketPath)"
|
||||
),
|
||||
ConfigurationFileInstructions(
|
||||
tool: "bash",
|
||||
configPath: "~/.bashrc",
|
||||
configText: "export SSH_AUTH_SOCK=\(socketPath)"
|
||||
),
|
||||
ConfigurationFileInstructions(
|
||||
tool: "fish",
|
||||
configPath: "~/.config/fish/config.fish",
|
||||
configText: "set -x SSH_AUTH_SOCK \(socketPath)"
|
||||
),
|
||||
ConfigurationFileInstructions("other", id: .otherShell),
|
||||
]),
|
||||
ConfigurationGroup(name:"Apps", instructions: [
|
||||
ConfigurationFileInstructions("Other", id: .otherApp),
|
||||
]),
|
||||
]
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationSplitView {
|
||||
List(selection: $selectedInstruction) {
|
||||
ForEach(instructions) { group in
|
||||
Section(group.name) {
|
||||
ForEach(group.instructions) { instruction in
|
||||
Text(instruction.tool)
|
||||
.padding(.vertical, 8)
|
||||
.tag(instruction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} detail: {
|
||||
if let selectedInstruction {
|
||||
Form {
|
||||
switch selectedInstruction.id {
|
||||
case .gettingStarted:
|
||||
Text("TBD")
|
||||
case .tool:
|
||||
Section(selectedInstruction.tool) {
|
||||
ConfigurationItemView(title: "Configuration File", value: selectedInstruction.configPath, action: .revealInFinder( selectedInstruction.configPath))
|
||||
ConfigurationItemView(title: "Add This:", action: .copy(selectedInstruction.configText)) {
|
||||
HStack {
|
||||
Text(selectedInstruction.configText)
|
||||
.padding(8)
|
||||
.font(.system(.subheadline, design: .monospaced))
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.fill(.black.opacity(0.05))
|
||||
.stroke(.separator, lineWidth: 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
if let url = selectedInstruction.website {
|
||||
Section {
|
||||
Link(destination: url) {
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("View Documentation on Web")
|
||||
.font(.headline)
|
||||
Text(url.absoluteString)
|
||||
.font(.caption2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case .otherShell:
|
||||
Section {
|
||||
Link("View on GitHub", destination: URL(string: "https://github.com/maxgoedjen/secretive-config-instructions/tree/main/shells")!)
|
||||
} header: {
|
||||
Text("There's a community-maintained list of shell instructions on GitHub. If the shell you're looking for isn't supported, create an issue and the community may be able to help.")
|
||||
.font(.body)
|
||||
}
|
||||
case .otherApp:
|
||||
Section {
|
||||
Link("View on GitHub", destination: URL(string: "https://github.com/maxgoedjen/secretive-config-instructions/tree/main/apps")!)
|
||||
} header: {
|
||||
Text("There's a community-maintained list of instructions for apps on GitHub. If the app you're looking for isn't supported, create an issue and the community may be able to help.")
|
||||
.font(.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
.formStyle(.grouped)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
selectedInstruction = instructions.first?.instructions.first
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
Button("Done") {
|
||||
dismiss()
|
||||
}
|
||||
.styled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct ConfigurationGroup: Identifiable {
|
||||
let id = UUID()
|
||||
var name: LocalizedStringResource
|
||||
var instructions: [ConfigurationFileInstructions] = []
|
||||
}
|
||||
|
||||
struct ConfigurationFileInstructions: Identifiable, Hashable {
|
||||
|
||||
var id: ID
|
||||
var tool: String
|
||||
var configPath: String
|
||||
var configText: String
|
||||
var website: URL?
|
||||
|
||||
init(tool: String, configPath: String, configText: String, website: URL? = nil) {
|
||||
self.id = .tool(tool)
|
||||
self.tool = tool
|
||||
self.configPath = configPath
|
||||
self.configText = configText
|
||||
self.website = website
|
||||
}
|
||||
|
||||
init(_ name: LocalizedStringResource, id: ID) {
|
||||
self.id = id
|
||||
tool = String(localized: name)
|
||||
configPath = ""
|
||||
configText = ""
|
||||
}
|
||||
|
||||
enum ID: Identifiable, Hashable {
|
||||
case gettingStarted
|
||||
case tool(String)
|
||||
case otherShell
|
||||
case otherApp
|
||||
|
||||
var id: String {
|
||||
switch self {
|
||||
case .gettingStarted:
|
||||
"getting_started"
|
||||
case .tool(let name):
|
||||
name
|
||||
case .otherShell:
|
||||
"other_shell"
|
||||
case .otherApp:
|
||||
"other_app"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#Preview {
|
||||
IntegrationsView()
|
||||
.frame(height: 500)
|
||||
}
|
@ -23,12 +23,6 @@ struct SecretDetailView<SecretType: Secret>: View {
|
||||
.frame(height: 20)
|
||||
CopyableView(title: .secretDetailPublicKeyPathLabel, image: Image(systemName: "lock.doc"), text: publicKeyFileStoreController.publicKeyPath(for: secret))
|
||||
Spacer()
|
||||
} header: {
|
||||
Text(verbatim: secret.name)
|
||||
.font(.system(size: 16, weight: .bold, design: .default))
|
||||
.foregroundStyle(.secondary)
|
||||
.padding(.leading)
|
||||
.padding(.bottom)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
|
@ -2,7 +2,7 @@ import SwiftUI
|
||||
|
||||
struct SetupView: View {
|
||||
|
||||
@Binding var visible: Bool
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Binding var setupComplete: Bool
|
||||
|
||||
@State var installed = false
|
||||
@ -12,7 +12,7 @@ struct SetupView: View {
|
||||
var body: some View {
|
||||
VStack {
|
||||
VStack(spacing: 0) {
|
||||
NewStepView(
|
||||
StepView(
|
||||
title: "setup_agent_title",
|
||||
description: "setup_agent_description",
|
||||
systemImage: "lock.laptopcomputer",
|
||||
@ -24,7 +24,7 @@ struct SetupView: View {
|
||||
}
|
||||
}
|
||||
Divider()
|
||||
NewStepView(
|
||||
StepView(
|
||||
title: "setup_updates_title",
|
||||
description: "setup_updates_description",
|
||||
systemImage: "network.badge.shield.half.filled",
|
||||
@ -36,7 +36,7 @@ struct SetupView: View {
|
||||
}
|
||||
}
|
||||
Divider()
|
||||
NewStepView(
|
||||
StepView(
|
||||
title: "setup_ssh_title",
|
||||
description: "setup_ssh_description",
|
||||
systemImage: "network.badge.shield.half.filled",
|
||||
@ -101,7 +101,7 @@ extension View {
|
||||
|
||||
}
|
||||
|
||||
struct NewStepView<Content: View>: View {
|
||||
struct StepView<Content: View>: View {
|
||||
|
||||
let title: LocalizedStringResource
|
||||
let icon: Image
|
||||
@ -141,27 +141,7 @@ extension SetupView {
|
||||
|
||||
}
|
||||
|
||||
struct ShellConfigInstruction: Identifiable, Hashable {
|
||||
|
||||
var shell: String
|
||||
var shellConfigDirectory: String
|
||||
var shellConfigFilename: String
|
||||
var text: String
|
||||
|
||||
var id: String {
|
||||
shell
|
||||
}
|
||||
|
||||
var shellConfigPath: String {
|
||||
return (shellConfigDirectory as NSString).appendingPathComponent(shellConfigFilename)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#Preview {
|
||||
SetupView(visible: .constant(true), setupComplete: .constant(false))
|
||||
SetupView(setupComplete: .constant(false))
|
||||
}
|
||||
|
||||
//#Preview {
|
||||
// SSHAgentSetupView(buttonAction: {})
|
||||
//}
|
||||
|
Loading…
Reference in New Issue
Block a user