mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-09-16 01:10:56 +00:00
WIP
This commit is contained in:
parent
cd76bb95ec
commit
fa658646d7
@ -1,7 +1,10 @@
|
||||
{
|
||||
"sourceLanguage" : "en",
|
||||
"strings" : {
|
||||
"Add Automatically" : {
|
||||
"" : {
|
||||
|
||||
},
|
||||
"Add This:" : {
|
||||
|
||||
},
|
||||
"agent_not_running_notice_detail_description" : {
|
||||
@ -1174,11 +1177,14 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Configuration File" : {
|
||||
|
||||
},
|
||||
"Configure" : {
|
||||
|
||||
},
|
||||
"Copy" : {
|
||||
"Configuring" : {
|
||||
|
||||
},
|
||||
"copyable_click_to_copy_button" : {
|
||||
@ -3858,6 +3864,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Secretive was unable to get SecretAgent to launch. Please try restarting your Mac, and if that doesn't work, file an issue on GitHub." : {
|
||||
|
||||
},
|
||||
"secure_enclave" : {
|
||||
"extractionState" : "manual",
|
||||
@ -5233,6 +5242,9 @@
|
||||
},
|
||||
"Start Agent" : {
|
||||
|
||||
},
|
||||
"Starting Agent" : {
|
||||
|
||||
},
|
||||
"unnamed_secret" : {
|
||||
"extractionState" : "manual",
|
||||
|
@ -53,6 +53,7 @@
|
||||
50BB046B2418AAAE00D6E079 /* EmptyStoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BB046A2418AAAE00D6E079 /* EmptyStoreView.swift */; };
|
||||
50BDCB722E63BAF20072D2E7 /* AgentStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BDCB712E63BAF20072D2E7 /* AgentStatusView.swift */; };
|
||||
50BDCB742E6436CA0072D2E7 /* ErrorStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BDCB732E6436C60072D2E7 /* ErrorStyle.swift */; };
|
||||
50BDCB762E6450950072D2E7 /* ConfigurationItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BDCB752E6450950072D2E7 /* ConfigurationItemView.swift */; };
|
||||
50C385A52407A76D00AF2719 /* SecretDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50C385A42407A76D00AF2719 /* SecretDetailView.swift */; };
|
||||
50CF4ABC2E601B0F005588DC /* ActionButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CF4ABB2E601B0F005588DC /* ActionButtonStyle.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
@ -144,6 +145,7 @@
|
||||
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>"; };
|
||||
50BDCB732E6436C60072D2E7 /* ErrorStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorStyle.swift; sourceTree = "<group>"; };
|
||||
50BDCB752E6450950072D2E7 /* ConfigurationItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationItemView.swift; sourceTree = "<group>"; };
|
||||
50C385A42407A76D00AF2719 /* SecretDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretDetailView.swift; sourceTree = "<group>"; };
|
||||
50CF4ABB2E601B0F005588DC /* ActionButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionButtonStyle.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@ -262,6 +264,7 @@
|
||||
50AE96FF2E5C1A420018C710 /* ConfigurationView.swift */,
|
||||
5066A6C72516FE6E004B5A36 /* CopyableView.swift */,
|
||||
50BDCB732E6436C60072D2E7 /* ErrorStyle.swift */,
|
||||
50BDCB752E6450950072D2E7 /* ConfigurationItemView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@ -460,6 +463,7 @@
|
||||
5066A6C82516FE6E004B5A36 /* CopyableView.swift in Sources */,
|
||||
50B8550D24138C4F009958AC /* DeleteSecretView.swift in Sources */,
|
||||
50BB046B2418AAAE00D6E079 /* EmptyStoreView.swift in Sources */,
|
||||
50BDCB762E6450950072D2E7 /* ConfigurationItemView.swift in Sources */,
|
||||
50617D8323FCE48E0099B055 /* App.swift in Sources */,
|
||||
506772C92425BB8500034DED /* NoStoresView.swift in Sources */,
|
||||
50153E22250DECA300525160 /* SecretListItemView.swift in Sources */,
|
||||
|
@ -23,6 +23,28 @@ extension View {
|
||||
|
||||
}
|
||||
|
||||
struct NormalButtonModifier: ViewModifier {
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
if #available(macOS 26.0, *) {
|
||||
content
|
||||
.glassEffect(.regular.tint(.white.opacity(0.1)), in: .circle)
|
||||
} else {
|
||||
content
|
||||
.buttonStyle(.borderless)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension View {
|
||||
|
||||
func normal() -> some View {
|
||||
modifier(NormalButtonModifier())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct DangerButtonModifier: ViewModifier {
|
||||
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
@ -21,22 +21,22 @@ struct AgentRunningView: View {
|
||||
Form {
|
||||
Section {
|
||||
if let process = agentStatusChecker.process {
|
||||
AgentInformationView(
|
||||
ConfigurationItemView(
|
||||
title: "Secret Agent Location",
|
||||
value: process.bundleURL!.path(),
|
||||
actions: [.revealInFinder],
|
||||
action: .revealInFinder(process.bundleURL!.path()),
|
||||
)
|
||||
AgentInformationView(
|
||||
ConfigurationItemView(
|
||||
title: "Socket Path",
|
||||
value: socketPath,
|
||||
actions: [.copy],
|
||||
action: .copy(socketPath),
|
||||
)
|
||||
AgentInformationView(
|
||||
ConfigurationItemView(
|
||||
title: "Version",
|
||||
value: Bundle(url: process.bundleURL!)!.infoDictionary!["CFBundleShortVersionString"] as! String
|
||||
)
|
||||
if let launchDate = process.launchDate {
|
||||
AgentInformationView(
|
||||
ConfigurationItemView(
|
||||
title: "Running Since",
|
||||
value: launchDate.formatted()
|
||||
)
|
||||
@ -144,50 +144,6 @@ struct AgentNotRunningView: View {
|
||||
|
||||
}
|
||||
|
||||
struct AgentInformationView: View {
|
||||
|
||||
enum Action {
|
||||
case copy
|
||||
case revealInFinder
|
||||
}
|
||||
|
||||
let title: LocalizedStringResource
|
||||
let value: String
|
||||
let actions: Set<Action>
|
||||
@State var tapping = false
|
||||
|
||||
init(title: LocalizedStringResource, value: String, actions: Set<Action> = []) {
|
||||
self.title = title
|
||||
self.value = value
|
||||
self.actions = actions
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Text(title)
|
||||
Spacer()
|
||||
if actions.contains(.revealInFinder) {
|
||||
Button("Reveal in Finder", systemImage: "folder") {
|
||||
NSWorkspace.shared.selectFile(value, inFileViewerRootedAtPath: value)
|
||||
}
|
||||
.labelStyle(.iconOnly)
|
||||
.buttonStyle(.borderless)
|
||||
}
|
||||
if actions.contains(.copy) {
|
||||
Button("Copy", systemImage: "document.on.document") {
|
||||
}
|
||||
.labelStyle(.iconOnly)
|
||||
.buttonStyle(.borderless)
|
||||
}
|
||||
}
|
||||
Text(value)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
AgentStatusView()
|
||||
.environment(\.agentStatusChecker, PreviewAgentStatusChecker(running: false))
|
||||
|
54
Sources/Secretive/Views/ConfigurationItemView.swift
Normal file
54
Sources/Secretive/Views/ConfigurationItemView.swift
Normal file
@ -0,0 +1,54 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ConfigurationItemView<Content: View>: View {
|
||||
|
||||
enum Action: Hashable {
|
||||
case copy(String)
|
||||
case revealInFinder(String)
|
||||
}
|
||||
|
||||
let title: LocalizedStringResource
|
||||
let content: Content
|
||||
let action: Action?
|
||||
|
||||
init(title: LocalizedStringResource, value: String, action: Action? = nil) where Content == Text {
|
||||
self.title = title
|
||||
self.content = Text(value)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
self.action = action
|
||||
}
|
||||
|
||||
init(title: LocalizedStringResource, action: Action? = nil, content: () -> Content) {
|
||||
self.title = title
|
||||
self.content = content()
|
||||
self.action = action
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Text(title)
|
||||
Spacer()
|
||||
switch action {
|
||||
case .copy(let string):
|
||||
Button("Reveal in Finder", systemImage: "folder") {
|
||||
NSWorkspace.shared.selectFile(string, inFileViewerRootedAtPath: string)
|
||||
}
|
||||
.labelStyle(.iconOnly)
|
||||
.buttonStyle(.borderless)
|
||||
case .revealInFinder(let string):
|
||||
Button("Reveal in Finder", systemImage: "folder") {
|
||||
NSWorkspace.shared.selectFile(string, inFileViewerRootedAtPath: string)
|
||||
}
|
||||
.labelStyle(.iconOnly)
|
||||
.buttonStyle(.borderless)
|
||||
case nil:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,52 +4,79 @@ struct ConfigurationView: View {
|
||||
|
||||
@Binding var visible: Bool
|
||||
|
||||
@State var running = true
|
||||
@State var sshConfig = false
|
||||
|
||||
@Environment(\.agentStatusChecker) var agentStatusChecker
|
||||
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 {
|
||||
VStack(spacing: 0) {
|
||||
NewStepView(
|
||||
title: "setup_agent_title",
|
||||
description: "setup_agent_description",
|
||||
systemImage: "network.badge.shield.half.filled",
|
||||
) {
|
||||
OnboardingButton("setup_agent_install_button", running) {
|
||||
Task {
|
||||
_ = await LaunchAgentController().forceLaunch()
|
||||
agentStatusChecker.check()
|
||||
running = agentStatusChecker.running
|
||||
Form {
|
||||
Section {
|
||||
Picker("Configuring", selection: $selectedShellInstruction) {
|
||||
ForEach(shellInstructions) { instruction in
|
||||
Text(instruction.shell)
|
||||
.tag(instruction)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
Divider()
|
||||
Divider()
|
||||
NewStepView(
|
||||
title: "setup_ssh_title",
|
||||
description: "setup_ssh_description",
|
||||
systemImage: "network.badge.shield.half.filled",
|
||||
) {
|
||||
HStack {
|
||||
OnboardingButton("setup_ssh_added_manually_button", false) {
|
||||
sshConfig = true
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
OnboardingButton("Add Automatically", false) {
|
||||
// let controller = ShellConfigurationController()
|
||||
// if controller.addToShell(shellInstructions: selectedShellInstruction) {
|
||||
// }
|
||||
sshConfig = true
|
||||
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")!)
|
||||
}
|
||||
}
|
||||
.background(.white.opacity(0.1), in: RoundedRectangle(cornerRadius: 10))
|
||||
.frame(minWidth: 500, idealWidth: 500, minHeight: 500, idealHeight: 500)
|
||||
.padding()
|
||||
.task {
|
||||
running = agentStatusChecker.running
|
||||
.formStyle(.grouped)
|
||||
.onAppear {
|
||||
selectedShellInstruction = shellInstructions.first
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ConfigurationView(visible: .constant(true)) {}
|
||||
.frame(width: 400, height: 300)
|
||||
}
|
||||
|
@ -103,11 +103,10 @@ extension ContentView {
|
||||
@ViewBuilder
|
||||
var newItemView: some View {
|
||||
if storeList.modifiableStore?.isAvailable ?? false {
|
||||
Button(action: {
|
||||
Button(.appMenuNewSecretButton, systemImage: "plus") {
|
||||
showingCreation = true
|
||||
}, label: {
|
||||
Image(systemName: "plus")
|
||||
})
|
||||
}
|
||||
.normal()
|
||||
.sheet(isPresented: $showingCreation) {
|
||||
if let modifiable = storeList.modifiableStore {
|
||||
CreateSecretView(store: modifiable, showing: $showingCreation) { created in
|
||||
|
@ -23,6 +23,12 @@ 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()
|
||||
@ -45,12 +51,6 @@ extension URL {
|
||||
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
struct SecretDetailView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SecretDetailView(secret: Preview.Store(numberOfRandomSecrets: 1).secrets[0])
|
||||
}
|
||||
#Preview {
|
||||
SecretDetailView(secret: Preview.Secret(name: "Demonstration Secret"))
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -133,62 +133,6 @@ struct NewStepView<Content: View>: View {
|
||||
|
||||
}
|
||||
|
||||
//struct SSHAgentSetupView: View {
|
||||
//
|
||||
// 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: "global",
|
||||
// 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 {
|
||||
// SetupStepView(title: "setup_ssh_title",
|
||||
// image: Image(systemName: "terminal"),
|
||||
// bodyText: "setup_ssh_description",
|
||||
// buttonTitle: "setup_ssh_added_manually_button",
|
||||
// buttonAction: buttonAction) {
|
||||
// Link("setup_third_party_faq_link", destination: URL(string: "https://github.com/maxgoedjen/secretive/blob/main/APP_CONFIG.md")!)
|
||||
// Picker(selection: $selectedShellInstruction, label: EmptyView()) {
|
||||
// ForEach(SSHAgentSetupView.controller.shellInstructions) { instruction in
|
||||
// Text(instruction.shell)
|
||||
// .tag(instruction)
|
||||
// .padding()
|
||||
// }
|
||||
// }.pickerStyle(SegmentedPickerStyle())
|
||||
// CopyableView(title: "setup_ssh_add_to_config_button_\(selectedShellInstruction.shellConfigPath)", image: Image(systemName: "greaterthan.square"), text: selectedShellInstruction.text)
|
||||
// Button("setup_ssh_add_for_me_button") {
|
||||
// let controller = ShellConfigurationController()
|
||||
// if controller.addToShell(shellInstructions: selectedShellInstruction) {
|
||||
// buttonAction()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
extension SetupView {
|
||||
|
||||
enum Constants {
|
||||
|
Loading…
Reference in New Issue
Block a user