Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions Sources/Clavis/Components/GlassComponents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ public struct LiquidGlassCapsuleControlModifier: ViewModifier {
public var isFocused: Bool = false
public var tint: Color? = nil
@Environment(\.accessibilityReduceTransparency) private var reduceTransparency
@Environment(\.colorSchemeContrast) private var contrast

@ViewBuilder
public func body(content: Content) -> some View {
Expand All @@ -141,21 +142,21 @@ public struct LiquidGlassCapsuleControlModifier: ViewModifier {
.overlay(
Capsule()
.stroke(
isFocused ? DesignTokens.accentBlue.opacity(0.8) : Color.clear,
lineWidth: isFocused ? 1.5 : 1
isFocused ? DesignTokens.accentBlue : contrast == .increased ? Color.primary : Color.clear,
lineWidth: isFocused || contrast == .increased ? 1.5 : 1
)
)
} else {
content
.background(
Capsule()
.fill(tint ?? Color(nsColor: .controlBackgroundColor).opacity(0.65))
.fill(tint ?? Color(nsColor: .controlBackgroundColor).opacity(reduceTransparency ? 1 : 0.65))
)
.overlay(
Capsule()
.stroke(
isFocused ? DesignTokens.accentBlue.opacity(0.75) : DesignTokens.cardBorder,
lineWidth: isFocused ? 1.5 : 1
isFocused ? DesignTokens.accentBlue : contrast == .increased ? Color.primary : DesignTokens.cardBorder,
lineWidth: isFocused || contrast == .increased ? 1.5 : 1
)
)
}
Expand Down Expand Up @@ -227,25 +228,30 @@ public struct LiquidGlassButtonStyleModifier: ViewModifier {
}

public struct AdaptiveGlassCapsuleModifier: ViewModifier {
@Environment(\.accessibilityReduceTransparency) private var reduceTransparency
@Environment(\.colorSchemeContrast) private var contrast
public init() {}

@ViewBuilder
public func body(content: Content) -> some View {
if #available(macOS 26.0, *) {
if #available(macOS 26.0, *), !reduceTransparency {
content
.glassEffect(.regular.interactive(), in: .capsule)
} else {
content
.background(
ZStack {
VisualEffectView(material: .sidebar, blendingMode: .withinWindow)
Color(nsColor: NSColor.controlBackgroundColor).opacity(0.5)
if !reduceTransparency {
VisualEffectView(material: .sidebar, blendingMode: .withinWindow)
}
Color(nsColor: NSColor.controlBackgroundColor).opacity(reduceTransparency ? 1 : 0.5)
}
.clipShape(Capsule())
)
.overlay(
Capsule()
.stroke(DesignTokens.cardBorder, lineWidth: 0.8)
.stroke(contrast == .increased ? Color.primary : DesignTokens.cardBorder,
lineWidth: contrast == .increased ? 1.5 : 0.8)
)
}
}
Expand Down
12 changes: 8 additions & 4 deletions Sources/Clavis/Views/KeyDetailInspectorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -482,10 +482,12 @@ public struct KeyDetailInspectorView: View {
}

private var activeSessionsSection: some View {
let sessions = appState.agentSessions.filter { $0.keyFingerprint == key.fingerprint }
let paused = appState.requestPolicy.isPaused
let available = appState.isSocketActive && appState.requestPolicy.state != .unknown
let sessions = paused ? [] : appState.agentSessions.filter { $0.keyFingerprint == key.fingerprint }
return Section("Active Sessions") {
VStack(spacing: 12) {
if let grace = activeGitGraceSession {
if !paused, let grace = activeGitGraceSession {
HStack {
Label("Git signing", systemImage: "signature")
Spacer()
Expand All @@ -504,8 +506,10 @@ public struct KeyDetailInspectorView: View {
Button("Revoke") { appState.endAgentSession(id: session.id) }
}
}
if sessions.isEmpty && activeGitGraceSession == nil {
Text("No active approvals. Clavis will ask on the next permitted request.")
if paused || (sessions.isEmpty && activeGitGraceSession == nil) {
Text(paused ? "Requests are paused. Approvals have been revoked."
: available ? "No active approvals. Clavis will ask on the next permitted request."
: "Session status is unavailable. Check the agent connection.")
.font(.callout).foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
}
Expand Down
61 changes: 0 additions & 61 deletions Sources/Clavis/Views/Sheets/KeyPurposePicker.swift

This file was deleted.

12 changes: 12 additions & 0 deletions Sources/Clavis/Views/Sheets/SettingsNavigation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct SettingsNavigation<General: View>: View {
let general: General
@AppStorage("clavis.settings.tab") private var selectedTab = SettingsTab.general.rawValue
@StateObject private var applications: ApplicationSettingsModel
@FocusState private var focusedTab: SettingsTab?

init(general: General, agent: any AgentControlling) {
self.general = general
Expand All @@ -36,6 +37,7 @@ struct SettingsNavigation<General: View>: View {
ForEach(SettingsTab.allCases, id: \.rawValue) { tab in
Button {
selectedTab = tab.rawValue
focusedTab = tab
} label: {
VStack(spacing: 3) {
Image(systemName: tab.symbol).font(.system(size: 14))
Expand All @@ -51,10 +53,20 @@ struct SettingsNavigation<General: View>: View {
.contentShape(Capsule())
}
.buttonStyle(.plain)
.focused($focusedTab, equals: tab)
.accessibilityIdentifier("settings-tab-\(tab.rawValue.lowercased())")
.accessibilityLabel("\(tab.rawValue) settings")
.accessibilityAddTraits(selectedTab == tab.rawValue ? [.isSelected] : [])
}
}
.onMoveCommand { direction in
guard focusedTab != nil else { return }
switch direction {
case .left: selectedTab = SettingsTab.general.rawValue; focusedTab = .general
case .right: selectedTab = SettingsTab.bots.rawValue; focusedTab = .bots
default: break
}
}
.padding(4)
.liquidGlassCapsuleControl()
.padding(.vertical, 12)
Expand Down
Loading
Loading