mirror of
				https://github.com/maxgoedjen/secretive.git
				synced 2025-11-04 01:10:56 +00:00 
			
		
		
		
	Change how agent launch/relaunch is performed
This commit is contained in:
		
							parent
							
								
									84d5a56fb0
								
							
						
					
					
						commit
						f79aa9c347
					
				@ -32,7 +32,6 @@
 | 
			
		||||
		504788F62E68206F00B4556F /* GettingStartedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F52E68206F00B4556F /* GettingStartedView.swift */; };
 | 
			
		||||
		504789232E697DD300B4556F /* BoxBackgroundStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504789222E697DD300B4556F /* BoxBackgroundStyle.swift */; };
 | 
			
		||||
		50571E0324393C2600F76F6C /* JustUpdatedChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50571E0224393C2600F76F6C /* JustUpdatedChecker.swift */; };
 | 
			
		||||
		50571E0524393D1500F76F6C /* LaunchAgentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50571E0424393D1500F76F6C /* LaunchAgentController.swift */; };
 | 
			
		||||
		50617D8323FCE48E0099B055 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50617D8223FCE48E0099B055 /* App.swift */; };
 | 
			
		||||
		50617D8523FCE48E0099B055 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50617D8423FCE48E0099B055 /* ContentView.swift */; };
 | 
			
		||||
		50617D8A23FCE48E0099B055 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 50617D8923FCE48E0099B055 /* Preview Assets.xcassets */; };
 | 
			
		||||
@ -194,7 +193,6 @@
 | 
			
		||||
		504788F52E68206F00B4556F /* GettingStartedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GettingStartedView.swift; sourceTree = "<group>"; };
 | 
			
		||||
		504789222E697DD300B4556F /* BoxBackgroundStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxBackgroundStyle.swift; sourceTree = "<group>"; };
 | 
			
		||||
		50571E0224393C2600F76F6C /* JustUpdatedChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JustUpdatedChecker.swift; sourceTree = "<group>"; };
 | 
			
		||||
		50571E0424393D1500F76F6C /* LaunchAgentController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAgentController.swift; sourceTree = "<group>"; };
 | 
			
		||||
		5059933F2E7A3B5B0092CFFA /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Main.storyboard; sourceTree = "<group>"; };
 | 
			
		||||
		50617D7F23FCE48E0099B055 /* Secretive.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Secretive.app; sourceTree = BUILT_PRODUCTS_DIR; };
 | 
			
		||||
		50617D8223FCE48E0099B055 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
 | 
			
		||||
@ -448,7 +446,6 @@
 | 
			
		||||
				508A58B2241ED2180069DC07 /* AgentStatusChecker.swift */,
 | 
			
		||||
				5091D2BB25183B830049FD9B /* ApplicationDirectoryController.swift */,
 | 
			
		||||
				50571E0224393C2600F76F6C /* JustUpdatedChecker.swift */,
 | 
			
		||||
				50571E0424393D1500F76F6C /* LaunchAgentController.swift */,
 | 
			
		||||
			);
 | 
			
		||||
			path = Controllers;
 | 
			
		||||
			sourceTree = "<group>";
 | 
			
		||||
@ -707,7 +704,6 @@
 | 
			
		||||
				5099A02423FD2AAA0062B6F2 /* CreateSecretView.swift in Sources */,
 | 
			
		||||
				50AE97002E5C1A420018C710 /* IntegrationsView.swift in Sources */,
 | 
			
		||||
				50153E20250AFCB200525160 /* UpdateView.swift in Sources */,
 | 
			
		||||
				50571E0524393D1500F76F6C /* LaunchAgentController.swift in Sources */,
 | 
			
		||||
				5066A6C82516FE6E004B5A36 /* CopyableView.swift in Sources */,
 | 
			
		||||
				50B8550D24138C4F009958AC /* DeleteSecretView.swift in Sources */,
 | 
			
		||||
				50BB046B2418AAAE00D6E079 /* EmptyStoreView.swift in Sources */,
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@ import Brief
 | 
			
		||||
@main
 | 
			
		||||
struct Secretive: App {
 | 
			
		||||
    
 | 
			
		||||
    @Environment(\.agentStatusChecker) var agentStatusChecker
 | 
			
		||||
    @Environment(\.agentLaunchController) var agentLaunchController
 | 
			
		||||
    @Environment(\.justUpdatedChecker) var justUpdatedChecker
 | 
			
		||||
 | 
			
		||||
    @SceneBuilder var body: some Scene {
 | 
			
		||||
@ -15,14 +15,15 @@ struct Secretive: App {
 | 
			
		||||
            ContentView()
 | 
			
		||||
                .environment(EnvironmentValues._secretStoreList)
 | 
			
		||||
                .onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in
 | 
			
		||||
                    @AppStorage("defaultsHasRunSetup") var hasRunSetup = false
 | 
			
		||||
                    guard hasRunSetup else { return }
 | 
			
		||||
                    agentStatusChecker.check()
 | 
			
		||||
                    if agentStatusChecker.running && justUpdatedChecker.justUpdatedBuild {
 | 
			
		||||
                        // Relaunch the agent, since it'll be running from earlier update still
 | 
			
		||||
                        reinstallAgent()
 | 
			
		||||
                    } else if !agentStatusChecker.running && !agentStatusChecker.developmentBuild {
 | 
			
		||||
                        forceLaunchAgent()
 | 
			
		||||
                    Task {
 | 
			
		||||
                        @AppStorage("defaultsHasRunSetup") var hasRunSetup = false
 | 
			
		||||
                        guard hasRunSetup else { return }
 | 
			
		||||
                        agentLaunchController.check()
 | 
			
		||||
                        guard !agentLaunchController.developmentBuild else { return }
 | 
			
		||||
                        if justUpdatedChecker.justUpdatedBuild || !agentLaunchController.running {
 | 
			
		||||
                            // Relaunch the agent, since it'll be running from earlier update still
 | 
			
		||||
                            try await agentLaunchController.forceLaunch()
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
@ -79,30 +80,6 @@ extension Secretive {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extension Secretive {
 | 
			
		||||
 | 
			
		||||
    private func reinstallAgent() {
 | 
			
		||||
        Task {
 | 
			
		||||
            _ = await LaunchAgentController().install()
 | 
			
		||||
            try? await Task.sleep(for: .seconds(1))
 | 
			
		||||
            agentStatusChecker.check()
 | 
			
		||||
            if !agentStatusChecker.running {
 | 
			
		||||
                forceLaunchAgent()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private func forceLaunchAgent() {
 | 
			
		||||
        // We've run setup, we didn't just update, launchd is just not doing it's thing.
 | 
			
		||||
        // Force a launch directly.
 | 
			
		||||
        Task {
 | 
			
		||||
            _ = await LaunchAgentController().forceLaunch()
 | 
			
		||||
            agentStatusChecker.check()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private enum Constants {
 | 
			
		||||
    static let helpURL = URL(string: "https://github.com/maxgoedjen/secretive/blob/main/FAQ.md")!
 | 
			
		||||
}
 | 
			
		||||
@ -121,8 +98,8 @@ extension EnvironmentValues {
 | 
			
		||||
        return list
 | 
			
		||||
    }()
 | 
			
		||||
 | 
			
		||||
    private static let _agentStatusChecker = AgentStatusChecker()
 | 
			
		||||
    @Entry var agentStatusChecker: any AgentStatusCheckerProtocol = _agentStatusChecker
 | 
			
		||||
    private static let _agentLaunchController = AgentLaunchController()
 | 
			
		||||
    @Entry var agentLaunchController: any AgentLaunchControllerProtocol = _agentLaunchController
 | 
			
		||||
    private static let _updater: any UpdaterProtocol = {
 | 
			
		||||
        @AppStorage("defaultsHasRunSetup") var hasRunSetup = false
 | 
			
		||||
        return Updater(checkOnLaunch: hasRunSetup)
 | 
			
		||||
 | 
			
		||||
@ -2,18 +2,25 @@ import Foundation
 | 
			
		||||
import AppKit
 | 
			
		||||
import SecretKit
 | 
			
		||||
import Observation
 | 
			
		||||
import OSLog
 | 
			
		||||
import ServiceManagement
 | 
			
		||||
 | 
			
		||||
@MainActor protocol AgentStatusCheckerProtocol: Observable, Sendable {
 | 
			
		||||
@MainActor protocol AgentLaunchControllerProtocol: Observable, Sendable {
 | 
			
		||||
    var running: Bool { get }
 | 
			
		||||
    var developmentBuild: Bool { get }
 | 
			
		||||
    var process: NSRunningApplication? { get }
 | 
			
		||||
    func check()
 | 
			
		||||
    func install() async throws
 | 
			
		||||
    func uninstall() async throws
 | 
			
		||||
    func forceLaunch() async throws
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Observable @MainActor final class AgentStatusChecker: AgentStatusCheckerProtocol {
 | 
			
		||||
@Observable @MainActor final class AgentLaunchController: AgentLaunchControllerProtocol {
 | 
			
		||||
 | 
			
		||||
    var running: Bool = false
 | 
			
		||||
    var process: NSRunningApplication? = nil
 | 
			
		||||
    private let logger = Logger(subsystem: "com.maxgoedjen.secretive", category: "LaunchAgentController")
 | 
			
		||||
    private let service = SMAppService.loginItem(identifier: Bundle.agentBundleID)
 | 
			
		||||
 | 
			
		||||
    nonisolated init() {
 | 
			
		||||
        Task { @MainActor in
 | 
			
		||||
@ -49,6 +56,47 @@ import Observation
 | 
			
		||||
        Bundle.main.bundleURL.isXcodeURL
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func install() async throws {
 | 
			
		||||
        logger.debug("Installing agent")
 | 
			
		||||
        try? await service.unregister()
 | 
			
		||||
        // This is definitely a bit of a "seems to work better" thing but:
 | 
			
		||||
        // Seems to more reliably hit if these are on separate runloops, otherwise it seems like it sometimes doesn't kill old
 | 
			
		||||
        // and start new?
 | 
			
		||||
        try await Task.sleep(for: .seconds(1))
 | 
			
		||||
        try service.register()
 | 
			
		||||
        try await Task.sleep(for: .seconds(1))
 | 
			
		||||
        check()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func uninstall() async throws {
 | 
			
		||||
        logger.debug("Uninstalling agent")
 | 
			
		||||
        try await Task.sleep(for: .seconds(1))
 | 
			
		||||
        try await service.unregister()
 | 
			
		||||
        try await Task.sleep(for: .seconds(1))
 | 
			
		||||
        check()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func forceLaunch() async throws {
 | 
			
		||||
        logger.debug("Agent is not running, attempting to force launch by reinstalling")
 | 
			
		||||
        try await install()
 | 
			
		||||
        if running {
 | 
			
		||||
            logger.debug("Agent successfully force launched by reinstalling")
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
        logger.debug("Agent is not running, attempting to force launch by launching directly")
 | 
			
		||||
        let url = Bundle.main.bundleURL.appendingPathComponent("Contents/Library/LoginItems/SecretAgent.app")
 | 
			
		||||
        let config = NSWorkspace.OpenConfiguration()
 | 
			
		||||
        config.activates = false
 | 
			
		||||
        do {
 | 
			
		||||
            try await NSWorkspace.shared.openApplication(at: url, configuration: config)
 | 
			
		||||
            logger.debug("Agent force launched")
 | 
			
		||||
            try await Task.sleep(for: .seconds(1))
 | 
			
		||||
        } catch {
 | 
			
		||||
            logger.error("Error force launching \(error.localizedDescription)")
 | 
			
		||||
        }
 | 
			
		||||
        check()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extension URL {
 | 
			
		||||
 | 
			
		||||
@ -1,65 +0,0 @@
 | 
			
		||||
import Foundation
 | 
			
		||||
import ServiceManagement
 | 
			
		||||
import AppKit
 | 
			
		||||
import OSLog
 | 
			
		||||
import SecretKit
 | 
			
		||||
 | 
			
		||||
struct LaunchAgentController {
 | 
			
		||||
    
 | 
			
		||||
    private let logger = Logger(subsystem: "com.maxgoedjen.secretive", category: "LaunchAgentController")
 | 
			
		||||
 | 
			
		||||
    func install() async -> Bool {
 | 
			
		||||
        logger.debug("Installing agent")
 | 
			
		||||
        _ = setEnabled(false)
 | 
			
		||||
        // This is definitely a bit of a "seems to work better" thing but:
 | 
			
		||||
        // Seems to more reliably hit if these are on separate runloops, otherwise it seems like it sometimes doesn't kill old
 | 
			
		||||
        // and start new?
 | 
			
		||||
        try? await Task.sleep(for: .seconds(1))
 | 
			
		||||
        let result = await MainActor.run {
 | 
			
		||||
            setEnabled(true)
 | 
			
		||||
        }
 | 
			
		||||
        try? await Task.sleep(for: .seconds(1))
 | 
			
		||||
        return result
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func uninstall() async -> Bool {
 | 
			
		||||
        logger.debug("Uninstalling agent")
 | 
			
		||||
        try? await Task.sleep(for: .seconds(1))
 | 
			
		||||
        let result = await MainActor.run {
 | 
			
		||||
            setEnabled(false)
 | 
			
		||||
        }
 | 
			
		||||
        try? await Task.sleep(for: .seconds(1))
 | 
			
		||||
        return result
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func forceLaunch() async -> Bool {
 | 
			
		||||
        logger.debug("Agent is not running, attempting to force launch")
 | 
			
		||||
        let url = Bundle.main.bundleURL.appendingPathComponent("Contents/Library/LoginItems/SecretAgent.app")
 | 
			
		||||
        let config = NSWorkspace.OpenConfiguration()
 | 
			
		||||
        config.activates = false
 | 
			
		||||
        do {
 | 
			
		||||
            try await NSWorkspace.shared.openApplication(at: url, configuration: config)
 | 
			
		||||
            logger.debug("Agent force launched")
 | 
			
		||||
            try? await Task.sleep(for: .seconds(1))
 | 
			
		||||
            return true
 | 
			
		||||
        } catch {
 | 
			
		||||
            logger.error("Error force launching \(error.localizedDescription)")
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private func setEnabled(_ enabled: Bool) -> Bool {
 | 
			
		||||
        let service = SMAppService.loginItem(identifier: Bundle.agentBundleID)
 | 
			
		||||
        do {
 | 
			
		||||
            if enabled {
 | 
			
		||||
                try service.register()
 | 
			
		||||
            } else {
 | 
			
		||||
                try service.unregister()
 | 
			
		||||
            }
 | 
			
		||||
            return true
 | 
			
		||||
        } catch {
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import Foundation
 | 
			
		||||
import AppKit
 | 
			
		||||
 | 
			
		||||
class PreviewAgentStatusChecker: AgentStatusCheckerProtocol {
 | 
			
		||||
class PreviewAgentLaunchController: AgentLaunchControllerProtocol {
 | 
			
		||||
 | 
			
		||||
    let running: Bool
 | 
			
		||||
    let process: NSRunningApplication?
 | 
			
		||||
@ -15,4 +15,13 @@ class PreviewAgentStatusChecker: AgentStatusCheckerProtocol {
 | 
			
		||||
    func check() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func install() async throws {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func uninstall() async throws {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    func forceLaunch() async throws {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@ import SwiftUI
 | 
			
		||||
struct SetupView: View {
 | 
			
		||||
 | 
			
		||||
    @Environment(\.dismiss) private var dismiss
 | 
			
		||||
    @Environment(\.agentLaunchController) private var agentLaunchController
 | 
			
		||||
    @Binding var setupComplete: Bool
 | 
			
		||||
 | 
			
		||||
    @State var showingIntegrations = false
 | 
			
		||||
@ -31,7 +32,7 @@ struct SetupView: View {
 | 
			
		||||
                    ) {
 | 
			
		||||
                        installed = true
 | 
			
		||||
                        Task {
 | 
			
		||||
                            await LaunchAgentController().install()
 | 
			
		||||
                            try? await agentLaunchController.install()
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -2,10 +2,10 @@ import SwiftUI
 | 
			
		||||
 | 
			
		||||
struct AgentStatusView: View {
 | 
			
		||||
 | 
			
		||||
    @Environment(\.agentStatusChecker) private var agentStatusChecker: any AgentStatusCheckerProtocol
 | 
			
		||||
    @Environment(\.agentLaunchController) private var agentLaunchController: any AgentLaunchControllerProtocol
 | 
			
		||||
 | 
			
		||||
    var body: some View {
 | 
			
		||||
        if agentStatusChecker.running {
 | 
			
		||||
        if agentLaunchController.running {
 | 
			
		||||
            AgentRunningView()
 | 
			
		||||
        } else {
 | 
			
		||||
            AgentNotRunningView()
 | 
			
		||||
@ -14,12 +14,12 @@ struct AgentStatusView: View {
 | 
			
		||||
}
 | 
			
		||||
struct AgentRunningView: View {
 | 
			
		||||
 | 
			
		||||
    @Environment(\.agentStatusChecker) private var agentStatusChecker: any AgentStatusCheckerProtocol
 | 
			
		||||
    @Environment(\.agentLaunchController) private var agentLaunchController: any AgentLaunchControllerProtocol
 | 
			
		||||
 | 
			
		||||
    var body: some View {
 | 
			
		||||
        Form {
 | 
			
		||||
            Section {
 | 
			
		||||
                if let process = agentStatusChecker.process {
 | 
			
		||||
                if let process = agentLaunchController.process {
 | 
			
		||||
                    ConfigurationItemView(
 | 
			
		||||
                        title: .agentDetailsLocationTitle,
 | 
			
		||||
                        value: process.bundleURL!.path(),
 | 
			
		||||
@ -53,19 +53,13 @@ struct AgentRunningView: View {
 | 
			
		||||
                        Menu(.agentDetailsRestartAgentButton) {
 | 
			
		||||
                            Button(.agentDetailsDisableAgentButton) {
 | 
			
		||||
                                Task {
 | 
			
		||||
                                    _ = await LaunchAgentController()
 | 
			
		||||
                                    try? await agentLaunchController
 | 
			
		||||
                                        .uninstall()
 | 
			
		||||
                                    agentStatusChecker.check()
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        } primaryAction: {
 | 
			
		||||
                            Task {
 | 
			
		||||
                                let controller = LaunchAgentController()
 | 
			
		||||
                                let installed = await controller.install()
 | 
			
		||||
                                if !installed {
 | 
			
		||||
                                    _ = await controller.forceLaunch()
 | 
			
		||||
                                }
 | 
			
		||||
                                agentStatusChecker.check()
 | 
			
		||||
                                try? await agentLaunchController.forceLaunch()
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
@ -82,7 +76,7 @@ struct AgentRunningView: View {
 | 
			
		||||
 | 
			
		||||
struct AgentNotRunningView: View {
 | 
			
		||||
 | 
			
		||||
    @Environment(\.agentStatusChecker) private var agentStatusChecker: any AgentStatusCheckerProtocol
 | 
			
		||||
    @Environment(\.agentLaunchController) private var agentLaunchController
 | 
			
		||||
    @State var triedRestart = false
 | 
			
		||||
    @State var loading = false
 | 
			
		||||
 | 
			
		||||
@ -103,15 +97,10 @@ struct AgentNotRunningView: View {
 | 
			
		||||
                                guard !loading else { return }
 | 
			
		||||
                                loading = true
 | 
			
		||||
                                Task {
 | 
			
		||||
                                    let controller = LaunchAgentController()
 | 
			
		||||
                                    let installed = await controller.install()
 | 
			
		||||
                                    if !installed {
 | 
			
		||||
                                        _ = await controller.forceLaunch()
 | 
			
		||||
                                    }
 | 
			
		||||
                                    agentStatusChecker.check()
 | 
			
		||||
                                    try await agentLaunchController.forceLaunch()
 | 
			
		||||
                                    loading = false
 | 
			
		||||
 | 
			
		||||
                                    if !agentStatusChecker.running {
 | 
			
		||||
                                    if !agentLaunchController.running {
 | 
			
		||||
                                        triedRestart = true
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
@ -145,9 +134,9 @@ struct AgentNotRunningView: View {
 | 
			
		||||
 | 
			
		||||
//#Preview {
 | 
			
		||||
//    AgentStatusView()
 | 
			
		||||
//        .environment(\.agentStatusChecker, PreviewAgentStatusChecker(running: false))
 | 
			
		||||
//        .environment(\.agentLaunchController, PreviewAgentLaunchController(running: false))
 | 
			
		||||
//}
 | 
			
		||||
//#Preview {
 | 
			
		||||
//    AgentStatusView()
 | 
			
		||||
//        .environment(\.agentStatusChecker, PreviewAgentStatusChecker(running: true, process: .current))
 | 
			
		||||
//        .environment(\.agentLaunchController, PreviewAgentLaunchController(running: true, process: .current))
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ struct ContentView: View {
 | 
			
		||||
    @Environment(\.openWindow) private var openWindow
 | 
			
		||||
    @Environment(\.secretStoreList) private var storeList
 | 
			
		||||
    @Environment(\.updater) private var updater
 | 
			
		||||
    @Environment(\.agentStatusChecker) private var agentStatusChecker
 | 
			
		||||
    @Environment(\.agentLaunchController) private var agentLaunchController
 | 
			
		||||
 | 
			
		||||
    @AppStorage("defaultsHasRunSetup") private var hasRunSetup = false
 | 
			
		||||
    @State private var showingCreation = false
 | 
			
		||||
@ -127,7 +127,7 @@ extension ContentView {
 | 
			
		||||
            showingAgentInfo = true
 | 
			
		||||
        }, label: {
 | 
			
		||||
            HStack {
 | 
			
		||||
                if agentStatusChecker.running {
 | 
			
		||||
                if agentLaunchController.running {
 | 
			
		||||
                    Text(.agentRunningNoticeTitle)
 | 
			
		||||
                        .font(.headline)
 | 
			
		||||
                        .foregroundColor(colorScheme == .light ? Color(white: 0.3) : .white)
 | 
			
		||||
@ -145,8 +145,8 @@ extension ContentView {
 | 
			
		||||
        })
 | 
			
		||||
        .buttonStyle(
 | 
			
		||||
            ToolbarStatusButtonStyle(
 | 
			
		||||
                lightColor: agentStatusChecker.running ? .black.opacity(0.05) : .red.opacity(0.75),
 | 
			
		||||
                darkColor: agentStatusChecker.running ? .white.opacity(0.05) : .red.opacity(0.5),
 | 
			
		||||
                lightColor: agentLaunchController.running ? .black.opacity(0.05) : .red.opacity(0.75),
 | 
			
		||||
                darkColor: agentLaunchController.running ? .white.opacity(0.05) : .red.opacity(0.5),
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        .popover(isPresented: $showingAgentInfo, attachmentAnchor: attachmentAnchor, arrowEdge: .bottom) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user