mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 10:36:35 +00:00
d3055702ef
Rolling back the .primaryAction placement (the pill shifted right and
lost its centered position in the toolbar). The "funny background with
shadow" visible in the toolbar is macOS's own .principal emphasis bezel
— not something Scarf draws, and not something we can cleanly hide
without disabling the toolbar surface itself. The native bezel is the
pill's frame; we just have to make the pill's interior read well inside
it.
Two changes to make the pill itself look like a toolbar tool inside
that bezel:
- Drop the colored dot, replace with a state-specific SF Symbol. The
icon's shape signals clickability (looks like a tool button), and its
color signals state (green/orange/yellow/red hierarchical). Less
"status chip", more "toolbar button with status".
- Icons per state:
- connected → checkmark.circle.fill (click to re-probe)
- degraded → stethoscope (click to run diagnostics, matches the
stethoscope on the Manage Servers row)
- idle → arrow.triangle.2.circlepath (checking/retry)
- error → exclamationmark.triangle.fill (click for stderr)
Horizontal padding = 4 so the icon-and-label sit balanced inside the
bezel rather than pushed up against its edges.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80 lines
3.8 KiB
Swift
80 lines
3.8 KiB
Swift
import SwiftUI
|
|
|
|
struct ContentView: View {
|
|
@Environment(AppCoordinator.self) private var coordinator
|
|
@Environment(\.serverContext) private var serverContext
|
|
/// Per-window connection status. Constructed from the window's
|
|
/// `serverContext` once; lifetime matches the window.
|
|
@State private var connectionStatus: ConnectionStatusViewModel
|
|
|
|
init() {
|
|
_connectionStatus = State(initialValue: ConnectionStatusViewModel(context: .local))
|
|
}
|
|
|
|
var body: some View {
|
|
NavigationSplitView {
|
|
SidebarView()
|
|
} detail: {
|
|
detailView
|
|
.toolbar {
|
|
ToolbarItem(placement: .navigation) {
|
|
ServerSwitcherToolbar()
|
|
}
|
|
if serverContext.isRemote {
|
|
// `.principal` centers the pill in the toolbar —
|
|
// the native emphasis bezel is the intended frame;
|
|
// the pill's own visual content (icon + label, no
|
|
// background) sits inside it in balance.
|
|
ToolbarItem(placement: .principal) {
|
|
ConnectionStatusPill(status: connectionStatus)
|
|
}
|
|
}
|
|
}
|
|
.onAppear {
|
|
// The actual context is injected via @Environment, which
|
|
// isn't available in `init`. Rebuild the monitor here
|
|
// the first time we know the real context. Safe to call
|
|
// repeatedly; `startMonitoring()` cancels + restarts.
|
|
if connectionStatus.context.id != serverContext.id {
|
|
connectionStatus = ConnectionStatusViewModel(context: serverContext)
|
|
}
|
|
connectionStatus.startMonitoring()
|
|
}
|
|
.onDisappear { connectionStatus.stopMonitoring() }
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var detailView: some View {
|
|
// Each routed view receives the window's `serverContext` in its
|
|
// init so its `@State` ViewModel is constructed bound to the right
|
|
// server. This is what makes multi-window work — without it,
|
|
// every window's VMs default-construct with `.local` even though
|
|
// the surrounding env has the right context.
|
|
switch coordinator.selectedSection {
|
|
case .dashboard: DashboardView(context: serverContext)
|
|
case .insights: InsightsView(context: serverContext)
|
|
case .sessions: SessionsView(context: serverContext)
|
|
case .activity: ActivityView(context: serverContext)
|
|
case .projects: ProjectsView(context: serverContext)
|
|
case .chat: ChatView()
|
|
case .memory: MemoryView(context: serverContext)
|
|
case .skills: SkillsView(context: serverContext)
|
|
case .platforms: PlatformsView(context: serverContext)
|
|
case .personalities: PersonalitiesView(context: serverContext)
|
|
case .quickCommands: QuickCommandsView(context: serverContext)
|
|
case .credentialPools: CredentialPoolsView(context: serverContext)
|
|
case .plugins: PluginsView(context: serverContext)
|
|
case .webhooks: WebhooksView(context: serverContext)
|
|
case .profiles: ProfilesView(context: serverContext)
|
|
case .tools: ToolsView(context: serverContext)
|
|
case .mcpServers: MCPServersView(context: serverContext)
|
|
case .gateway: GatewayView(context: serverContext)
|
|
case .cron: CronView(context: serverContext)
|
|
case .health: HealthView(context: serverContext)
|
|
case .logs: LogsView(context: serverContext)
|
|
case .settings: SettingsView(context: serverContext)
|
|
}
|
|
}
|
|
}
|