mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-09-16 09:20:56 +00:00
WIP
This commit is contained in:
parent
ea96dd88eb
commit
f3ce6b9d0f
@ -1186,6 +1186,9 @@
|
||||
},
|
||||
"Configure" : {
|
||||
|
||||
},
|
||||
"Configure Integrations" : {
|
||||
|
||||
},
|
||||
"Configuring Tools for Secretive" : {
|
||||
|
||||
@ -3974,6 +3977,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Setup" : {
|
||||
|
||||
},
|
||||
"setup_agent_activity_monitor_description" : {
|
||||
"extractionState" : "manual",
|
||||
@ -5287,6 +5293,9 @@
|
||||
},
|
||||
"System" : {
|
||||
|
||||
},
|
||||
"Tell the tools you use how to talk to Secretive." : {
|
||||
|
||||
},
|
||||
"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." : {
|
||||
|
||||
|
@ -61,7 +61,6 @@ struct Secretive: App {
|
||||
}
|
||||
.sheet(isPresented: $showingIntegrations) {
|
||||
IntegrationsView()
|
||||
.frame(minHeight: 400)
|
||||
}
|
||||
}
|
||||
.commands {
|
||||
@ -81,6 +80,11 @@ struct Secretive: App {
|
||||
NSWorkspace.shared.open(Constants.helpURL)
|
||||
}
|
||||
}
|
||||
CommandGroup(after: .help) {
|
||||
Button("Setup") {
|
||||
showingSetup = true
|
||||
}
|
||||
}
|
||||
SidebarCommands()
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,11 @@ import SwiftUI
|
||||
struct PrimaryButtonModifier: ViewModifier {
|
||||
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@Environment(\.isEnabled) var isEnabled
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
// Tinted glass prominent is really hard to read on 26.0.
|
||||
if #available(macOS 26.0, *), colorScheme == .dark {
|
||||
if #available(macOS 26.0, *), colorScheme == .dark, isEnabled {
|
||||
content.buttonStyle(.glassProminent)
|
||||
} else {
|
||||
content.buttonStyle(.borderedProminent)
|
||||
@ -17,13 +18,13 @@ struct PrimaryButtonModifier: ViewModifier {
|
||||
|
||||
extension View {
|
||||
|
||||
func primary() -> some View {
|
||||
func primaryButton() -> some View {
|
||||
modifier(PrimaryButtonModifier())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct NormalButtonModifier: ViewModifier {
|
||||
struct MenuButtonModifier: ViewModifier {
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
if #available(macOS 26.0, *) {
|
||||
@ -39,7 +40,27 @@ struct NormalButtonModifier: ViewModifier {
|
||||
|
||||
extension View {
|
||||
|
||||
func normal() -> some View {
|
||||
func menuButton() -> some View {
|
||||
modifier(MenuButtonModifier())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct NormalButtonModifier: ViewModifier {
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
if #available(macOS 26.0, *) {
|
||||
content.buttonStyle(.glass)
|
||||
} else {
|
||||
content.buttonStyle(.bordered)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension View {
|
||||
|
||||
func normalButton() -> some View {
|
||||
modifier(NormalButtonModifier())
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ struct AgentNotRunningView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.primary()
|
||||
.primaryButton()
|
||||
} else {
|
||||
Text("Secretive was unable to get SecretAgent to launch. Please try restarting your Mac, and if that doesn't work, file an issue on GitHub.")
|
||||
.bold()
|
||||
|
@ -106,7 +106,7 @@ extension ContentView {
|
||||
Button(.appMenuNewSecretButton, systemImage: "plus") {
|
||||
showingCreation = true
|
||||
}
|
||||
.normal()
|
||||
.menuButton()
|
||||
.sheet(isPresented: $showingCreation) {
|
||||
if let modifiable = storeList.modifiableStore {
|
||||
CreateSecretView(store: modifiable) { created in
|
||||
|
@ -113,7 +113,7 @@ struct CreateSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
}
|
||||
Button(.createSecretCreateButton, action: save)
|
||||
.keyboardShortcut(.return)
|
||||
.primary()
|
||||
.primaryButton()
|
||||
.disabled(name.isEmpty)
|
||||
}
|
||||
.padding()
|
||||
|
@ -45,7 +45,7 @@ struct EditSecretView<StoreType: SecretStoreModifiable>: View {
|
||||
Button(.editSaveButton, action: rename)
|
||||
.disabled(name.isEmpty)
|
||||
.keyboardShortcut(.return)
|
||||
.primary()
|
||||
.primaryButton()
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
@ -21,19 +21,47 @@ struct IntegrationsView: View {
|
||||
}
|
||||
}
|
||||
} detail: {
|
||||
IntegrationsDetailView(selectedInstruction: $selectedInstruction)
|
||||
IntegrationsDetailView(selectedInstruction: $selectedInstruction)
|
||||
.fauxToolbar {
|
||||
Button("Done") {
|
||||
dismiss()
|
||||
}
|
||||
.normalButton()
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
selectedInstruction = instructions.gettingStarted
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
Button("Done") {
|
||||
dismiss()
|
||||
}
|
||||
.styled
|
||||
.frame(minHeight: 500)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension View {
|
||||
|
||||
func fauxToolbar<Content: View>(content: () -> Content) -> some View {
|
||||
modifier(FauxToolbarModifier(toolbarContent: content()))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct FauxToolbarModifier<ToolbarContent: View>: ViewModifier {
|
||||
|
||||
var toolbarContent: ToolbarContent
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
VStack(alignment: .leading) {
|
||||
content
|
||||
Divider()
|
||||
HStack {
|
||||
Spacer()
|
||||
toolbarContent
|
||||
.padding(.top, 8)
|
||||
.padding(.trailing, 16)
|
||||
.padding(.bottom, 16)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,20 +4,26 @@ struct SetupView: View {
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Binding var setupComplete: Bool
|
||||
|
||||
|
||||
@State var showingIntegrations = false
|
||||
@State var buttonWidth: CGFloat?
|
||||
|
||||
@State var installed = false
|
||||
@State var updates = false
|
||||
@State var sshConfig = false
|
||||
@State var integrations = false
|
||||
var allDone: Bool {
|
||||
installed && updates && integrations
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
VStack(spacing: 0) {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
StepView(
|
||||
title: "setup_agent_title",
|
||||
description: "setup_agent_description",
|
||||
systemImage: "lock.laptopcomputer",
|
||||
) {
|
||||
OnboardingButton("setup_agent_install_button", installed) {
|
||||
OnboardingButton("setup_agent_install_button", installed, width: buttonWidth) {
|
||||
Task {
|
||||
installed = await LaunchAgentController().install()
|
||||
}
|
||||
@ -29,78 +35,97 @@ struct SetupView: View {
|
||||
description: "setup_updates_description",
|
||||
systemImage: "network.badge.shield.half.filled",
|
||||
) {
|
||||
OnboardingButton("setup_updates_ok", updates) {
|
||||
Task {
|
||||
updates = true
|
||||
}
|
||||
OnboardingButton("setup_updates_ok", updates, width: buttonWidth) {
|
||||
updates = true
|
||||
}
|
||||
}
|
||||
Divider()
|
||||
StepView(
|
||||
title: "setup_ssh_title",
|
||||
description: "setup_ssh_description",
|
||||
systemImage: "network.badge.shield.half.filled",
|
||||
title: "Configure Integrations",
|
||||
description: "Tell the tools you use how to talk to Secretive.",
|
||||
systemImage: "firewall",
|
||||
) {
|
||||
HStack {
|
||||
OnboardingButton("Configure", false) {
|
||||
// sshConfig = true
|
||||
}
|
||||
OnboardingButton("Configure", integrations, width: buttonWidth) {
|
||||
showingIntegrations = true
|
||||
}
|
||||
}
|
||||
}
|
||||
.onPreferenceChange(OnboardingButton.WidthKey.self) { width in
|
||||
buttonWidth = width
|
||||
}
|
||||
.background(.white.opacity(0.1), in: RoundedRectangle(cornerRadius: 10))
|
||||
.frame(minWidth: 700, maxWidth: .infinity)
|
||||
HStack {
|
||||
Spacer()
|
||||
Button("Done") {}
|
||||
.styled
|
||||
Button("Done") {
|
||||
setupComplete = true
|
||||
dismiss()
|
||||
}
|
||||
.disabled(!allDone)
|
||||
.primaryButton()
|
||||
}
|
||||
}
|
||||
.interactiveDismissDisabled()
|
||||
.padding()
|
||||
.sheet(isPresented: $showingIntegrations, onDismiss: {
|
||||
integrations = true
|
||||
}, content: {
|
||||
IntegrationsView()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct OnboardingButton: View {
|
||||
|
||||
struct WidthKey: @MainActor PreferenceKey {
|
||||
@MainActor static var defaultValue: CGFloat? = nil
|
||||
static func reduce(value: inout CGFloat?, nextValue: () -> CGFloat?) {
|
||||
if let next = nextValue(), next > (value ?? -1) {
|
||||
value = next
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let label: LocalizedStringResource
|
||||
let complete: Bool
|
||||
let action: () -> Void
|
||||
|
||||
init(_ label: LocalizedStringResource, _ complete: Bool, action: @escaping () -> Void) {
|
||||
let width: CGFloat?
|
||||
@State var currentWidth: CGFloat?
|
||||
|
||||
init(_ label: LocalizedStringResource, _ complete: Bool, width: CGFloat? = nil, action: @escaping () -> Void) {
|
||||
self.label = label
|
||||
self.complete = complete
|
||||
self.action = action
|
||||
self.width = width
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Button(action: action) {
|
||||
HStack(spacing: 6) {
|
||||
Text(label)
|
||||
if complete {
|
||||
Text("Done")
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
} else {
|
||||
Text(label)
|
||||
}
|
||||
}
|
||||
.frame(width: width)
|
||||
.padding(.vertical, 2)
|
||||
.onGeometryChange(for: CGFloat.self) { proxy in
|
||||
proxy.size.width
|
||||
} action: { newValue in
|
||||
currentWidth = newValue
|
||||
}
|
||||
}
|
||||
.preference(key: WidthKey.self, value: currentWidth)
|
||||
.primaryButton()
|
||||
.disabled(complete)
|
||||
.styled
|
||||
.tint(complete ? .green : nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension View {
|
||||
|
||||
@ViewBuilder
|
||||
var styled: some View {
|
||||
if #available(macOS 26.0, *) {
|
||||
buttonStyle(.glassProminent)
|
||||
} else {
|
||||
buttonStyle(.borderedProminent)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct StepView<Content: View>: View {
|
||||
|
||||
let title: LocalizedStringResource
|
||||
@ -126,6 +151,7 @@ struct StepView<Content: View>: View {
|
||||
.bold()
|
||||
Text(description)
|
||||
}
|
||||
Spacer()
|
||||
actions
|
||||
}
|
||||
.padding(20)
|
||||
|
Loading…
Reference in New Issue
Block a user