fix(macos): streamline onboarding ui

main
Peter Steinberger 2025-12-20 15:20:31 +00:00
parent d306fcb8a2
commit e800e84a77
3 changed files with 45 additions and 13 deletions

View File

@ -261,11 +261,16 @@ struct GeneralSettings: View {
Button { Button {
Task { await self.installCLI() } Task { await self.installCLI() }
} label: { } label: {
if self.isInstallingCLI { let title = self.cliInstalled ? "Reinstall CLI helper" : "Install CLI helper"
ProgressView().controlSize(.small) ZStack {
} else { Text(title)
Text(self.cliInstalled ? "Reinstall CLI helper" : "Install CLI helper") .opacity(self.isInstallingCLI ? 0 : 1)
if self.isInstallingCLI {
ProgressView()
.controlSize(.small)
}
} }
.frame(minWidth: 150, minHeight: 24)
} }
.disabled(self.isInstallingCLI) .disabled(self.isInstallingCLI)

View File

@ -86,8 +86,8 @@ struct OnboardingView: View {
private static let clipboardPoll = Timer.publish(every: 0.4, on: .main, in: .common).autoconnect() private static let clipboardPoll = Timer.publish(every: 0.4, on: .main, in: .common).autoconnect()
private let permissionsPageIndex = 5 private let permissionsPageIndex = 5
private var pageOrder: [Int] { static func pageOrder(for mode: AppState.ConnectionMode) -> [Int] {
switch self.state.connectionMode { switch mode {
case .remote: case .remote:
// Remote setup doesn't need local gateway/CLI/workspace setup pages, // Remote setup doesn't need local gateway/CLI/workspace setup pages,
// and WhatsApp/Telegram setup is optional. // and WhatsApp/Telegram setup is optional.
@ -95,10 +95,14 @@ struct OnboardingView: View {
case .unconfigured: case .unconfigured:
[0, 1, 9] [0, 1, 9]
case .local: case .local:
[0, 1, 2, 3, 5, 6, 7, 8, 9] [0, 1, 2, 3, 5, 6, 8, 9]
} }
} }
private var pageOrder: [Int] {
Self.pageOrder(for: self.state.connectionMode)
}
private var pageCount: Int { self.pageOrder.count } private var pageCount: Int { self.pageOrder.count }
private var activePageIndex: Int { private var activePageIndex: Int {
self.activePageIndex(for: self.currentPage) self.activePageIndex(for: self.currentPage)
@ -175,6 +179,7 @@ struct OnboardingView: View {
await self.refreshPerms() await self.refreshPerms()
self.refreshCLIStatus() self.refreshCLIStatus()
self.loadWorkspaceDefaults() self.loadWorkspaceDefaults()
self.ensureDefaultWorkspace()
self.refreshAnthropicOAuthStatus() self.refreshAnthropicOAuthStatus()
self.loadIdentityDefaults() self.loadIdentityDefaults()
self.preferredGatewayID = BridgeDiscoveryPreferences.preferredStableID() self.preferredGatewayID = BridgeDiscoveryPreferences.preferredStableID()
@ -214,8 +219,6 @@ struct OnboardingView: View {
self.permissionsPage() self.permissionsPage()
case 6: case 6:
self.cliPage() self.cliPage()
case 7:
self.workspacePage()
case 8: case 8:
self.whatsappPage() self.whatsappPage()
case 9: case 9:
@ -849,11 +852,16 @@ struct OnboardingView: View {
Button { Button {
Task { await self.installCLI() } Task { await self.installCLI() }
} label: { } label: {
if self.installingCLI { let title = self.cliInstalled ? "Reinstall CLI" : "Install CLI"
ProgressView() ZStack {
} else { Text(title)
Text(self.cliInstalled ? "Reinstall CLI" : "Install CLI") .opacity(self.installingCLI ? 0 : 1)
if self.installingCLI {
ProgressView()
.controlSize(.small)
}
} }
.frame(minWidth: 120, minHeight: 28)
} }
.buttonStyle(.borderedProminent) .buttonStyle(.borderedProminent)
.disabled(self.installingCLI) .disabled(self.installingCLI)
@ -1364,6 +1372,20 @@ struct OnboardingView: View {
self.workspacePath = AgentWorkspace.displayPath(for: url) self.workspacePath = AgentWorkspace.displayPath(for: url)
} }
private func ensureDefaultWorkspace() {
guard self.state.connectionMode == .local else { return }
let configured = ClawdisConfigFile.inboundWorkspace()
let url = AgentWorkspace.resolveWorkspaceURL(from: configured)
do {
_ = try AgentWorkspace.bootstrap(workspaceURL: url)
if (configured ?? "").trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
ClawdisConfigFile.setInboundWorkspace(AgentWorkspace.displayPath(for: url))
}
} catch {
self.workspaceStatus = "Failed to create workspace: \(error.localizedDescription)"
}
}
private func loadIdentityDefaults() { private func loadIdentityDefaults() {
if let identity = ClawdisConfigFile.loadIdentity() { if let identity = ClawdisConfigFile.loadIdentity() {
self.identityName = identity.name self.identityName = identity.name

View File

@ -13,4 +13,9 @@ struct OnboardingViewSmokeTests {
discoveryModel: GatewayDiscoveryModel()) discoveryModel: GatewayDiscoveryModel())
_ = view.body _ = view.body
} }
@Test func pageOrderOmitsWorkspaceStep() {
let order = OnboardingView.pageOrder(for: .local)
#expect(!order.contains(7))
}
} }