Skip to content
Draft
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
15 changes: 15 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ custom_rules:
message: "Do not mutate store state directly in views. Send actions instead."
severity: error
included: "supacode/.*/Views/.*\\.swift"
interface_font_in_chrome:
name: "Interface Font In Chrome"
# `included` is the record of how far interface-text coverage reaches. It
# grows as directories are converted; it is never widened ahead of them,
# because a rule that fails on landing gets disabled rather than obeyed.
# Absence of any font modifier is invisible here — a view that inherits the
# system default matches nothing. Set a resolved default on the container
# for those, which this rule cannot check for you.
regex: "\\.font\\("
message: "Chrome text must honour the interface text settings. Use .interfaceFont(style) instead, or .fixedInterfaceFont(...) when the size is a layout constant."
severity: error
match_kinds:
- identifier
included: "supacode/(Features|App|Support)/.*\\.swift"
excluded: "supacode/Support/InterfaceTextMetrics.swift"
dictionary_unique_keys_with_values:
name: "Dictionary Unique Keys With Values"
regex: "\\bDictionary\\s*\\(\\s*uniqueKeysWithValues\\s*:"
Expand Down
2 changes: 1 addition & 1 deletion docs/components/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ and opens that section's root.

| Section | Controls |
|-----|----------|
| **General** | Appearance (system/light/dark), default app for opening worktrees, diff tool, confirm-before-quit, default view mode, window chrome tint, automatic repository icon detection, toolbar buttons (Run / Open-in-editor), dim unfocused splits, Active Agents panel auto-show & terminal titles. |
| **General** | Appearance (system/light/dark), minimum text size (System / 11–16 pt — a floor like Safari's "Never use font sizes smaller than": chrome text below the floor is lifted to it, covering the sidebar, Active Agents panel, toolbar, tab bar, and their popovers; terminal text is unaffected), default app for opening worktrees, diff tool, confirm-before-quit, default view mode, window chrome tint, automatic repository icon detection, toolbar buttons (Run / Open-in-editor), dim unfocused splits, Active Agents panel auto-show & terminal titles. |
| **Notifications** | In-app alerts, notification sound picker (Never / system sounds / Prowl Classic), macOS system notifications, move-notified-to-top, command-finished notification + threshold, Dock badge & bounce. → [notifications](notifications.md) |
| **Shortcuts** | Remap app keyboard shortcuts; view defaults; resolve conflicts. → [keyboard-shortcuts](../reference/keyboard-shortcuts.md) |
| **Worktree** | Worktree creation/deletion defaults: prompt on create, fetch before create, base directory, copy ignored/untracked files, automatic local-branch cleanup, merged-worktree action, archived auto-delete period. |
Expand Down
134 changes: 68 additions & 66 deletions docs/reference/settings-fields.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion supacode/App/AppLoadingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct AppLoadingView: View {
var body: some View {
VStack {
Text(Self.messages[messageIndex])
.font(.title3)
.interfaceFont(.title3)
.bold()
ProgressView()
.controlSize(.large)
Expand Down
8 changes: 6 additions & 2 deletions supacode/App/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,11 @@ struct ContentView: View {
)
return NavigationSplitView(columnVisibility: visibility) {
SidebarView(store: repositoriesStore, terminalManager: terminalManager)
.navigationSplitViewColumnWidth(min: 220, ideal: 260, max: 320)
.navigationSplitViewColumnWidth(
min: 220,
ideal: 260,
max: 320
)
} detail: {
WorktreeDetailView(store: store, terminalManager: terminalManager)
}
Expand Down Expand Up @@ -282,7 +286,7 @@ private struct RunScriptPromptView: View {
VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .leading, spacing: 4) {
Text("Run")
.font(.title3)
.interfaceFont(.title3)
Text("Enter a command to run in this worktree. It will be saved to repository settings.")
.foregroundStyle(.secondary)
}
Expand Down
7 changes: 7 additions & 0 deletions supacode/App/supacodeApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,13 @@ struct SupacodeApp: App {
.environment(ghosttyShortcuts)
.environment(commandKeyObserver)
.environment(\.resolvedKeybindings, store.resolvedKeybindings)
.environment(
\.interfaceText,
InterfaceTextResolution(
scale: store.settings.interfaceTextScale.factor,
minimumSize: store.settings.minimumTextSize.points ?? 0
)
)
.environment(askAgentHelp)
.sheet(
isPresented: Binding(
Expand Down
12 changes: 6 additions & 6 deletions supacode/Features/ActiveAgents/Views/ActiveAgentRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct ActiveAgentRow: View {
VStack(alignment: .leading, spacing: 2) {
title
Text(subtitle)
.font(.caption)
.interfaceFont(.caption)
.foregroundStyle(.secondary)
.lineLimit(1)
.truncationMode(.tail)
Expand All @@ -32,13 +32,13 @@ struct ActiveAgentRow: View {
private var title: some View {
HStack(alignment: .firstTextBaseline, spacing: 3) {
Text(entry.displayName)
.font(.body.weight(.medium))
.interfaceFont(.body, weight: .medium)
.foregroundStyle(.primary)
Text("·")
.font(.caption.weight(.semibold))
.interfaceFont(.caption, weight: .semibold)
.foregroundStyle(.tertiary)
Text(repositoryName)
.font(.callout.weight(.medium))
.interfaceFont(.callout, weight: .medium)
.foregroundStyle(repositoryColor?.color ?? .secondary)
}
.lineLimit(1)
Expand Down Expand Up @@ -73,7 +73,7 @@ struct ActiveAgentRow: View {

private var statusText: some View {
Text(entry.displayState.label)
.font(.caption2.weight(.semibold))
.interfaceFont(.caption2, weight: .semibold)
.lineLimit(1)
}
}
Expand Down Expand Up @@ -108,7 +108,7 @@ struct BaguaWorkingIndicator: View {

private func frameText(_ frame: String) -> some View {
Text(frame)
.font(.system(size: 17, weight: .bold, design: .monospaced))
.fixedInterfaceFont(.system(size: 17, weight: .bold, design: .monospaced))
.lineLimit(1)
.frame(width: 20, height: 18)
.accessibilityHidden(true)
Expand Down
4 changes: 2 additions & 2 deletions supacode/Features/ActiveAgents/Views/ActiveAgentsPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct ActiveAgentsPanel: View {
resizeHandle
HStack {
Text("Active Agents")
.font(.caption)
.interfaceFont(.caption)
.foregroundStyle(.secondary)
Spacer()
if let navigationShortcutHint, !store.entries.isEmpty {
Expand All @@ -40,7 +40,7 @@ struct ActiveAgentsPanel: View {
if store.entries.isEmpty {
Spacer(minLength: 0)
Text("New agents will appear here")
.font(.callout)
.interfaceFont(.callout)
.foregroundStyle(.secondary)
// Nudge up slightly off dead-center for better visual balance.
.offset(y: -8)
Expand Down
8 changes: 4 additions & 4 deletions supacode/Features/Canvas/Views/CanvasCardView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ struct CanvasCardView: View {
)
}
Text(repositoryName)
.font(.caption.bold())
.interfaceFont(.caption, weight: .bold)
.lineLimit(1)
HStack(spacing: 3) {
Text("/")
Expand All @@ -156,7 +156,7 @@ struct CanvasCardView: View {
}
Text(worktreeName)
}
.font(.caption)
.interfaceFont(.caption)
.foregroundStyle(.secondary)
.lineLimit(1)
Spacer()
Expand Down Expand Up @@ -203,7 +203,7 @@ struct CanvasCardView: View {
? "arrow.down.right.and.arrow.up.left"
: "arrow.up.left.and.arrow.down.right"
)
.font(.caption2.weight(.semibold))
.interfaceFont(.caption2, weight: .semibold)
.frame(width: 18, height: 18)
.contentShape(.rect)
}
Expand All @@ -216,7 +216,7 @@ struct CanvasCardView: View {
onClose()
} label: {
Image(systemName: "xmark")
.font(.caption2.weight(.semibold))
.interfaceFont(.caption2, weight: .semibold)
.frame(width: 18, height: 18)
.contentShape(.rect)
}
Expand Down
8 changes: 4 additions & 4 deletions supacode/Features/Canvas/Views/CanvasHelpButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct CanvasHelpButton: View {
togglePresentation()
} label: {
Image(systemName: "questionmark.circle")
.font(.body)
.interfaceFont(.body)
.accessibilityLabel("Canvas navigation help")
}
.buttonStyle(.bordered)
Expand Down Expand Up @@ -61,7 +61,7 @@ struct CanvasHelpButton: View {

return VStack(alignment: .leading, spacing: 14) {
Text("Canvas Navigation")
.font(.headline)
.interfaceFont(.headline)

VStack(alignment: .leading, spacing: 12) {
canvasHelpRow(
Expand Down Expand Up @@ -100,9 +100,9 @@ struct CanvasHelpButton: View {
.frame(width: 18)
.accessibilityHidden(true)
VStack(alignment: .leading, spacing: 2) {
Text(title).font(.callout).fontWeight(.medium)
Text(title).interfaceFont(.callout).fontWeight(.medium)
Text(detail)
.font(.caption)
.interfaceFont(.caption)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
Expand Down
2 changes: 1 addition & 1 deletion supacode/Features/Canvas/Views/CanvasSidebarButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct CanvasSidebarButton: View {
} label: {
HStack(spacing: 6) {
Label("Canvas", systemImage: "square.grid.2x2")
.font(.callout)
.interfaceFont(.callout)
.frame(maxWidth: .infinity, alignment: .leading)
if commandKeyObserver.isPressed,
let shortcut = AppShortcuts.display(for: AppShortcuts.CommandID.toggleCanvas, in: resolvedKeybindings)
Expand Down
10 changes: 5 additions & 5 deletions supacode/Features/Canvas/Views/CanvasView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ struct CanvasView: View {
"Broadcasting to \(selectionState.selectedTabIDs.count) cards",
systemImage: "dot.radiowaves.left.and.right"
)
.font(.callout)
.interfaceFont(.callout)
.padding(.horizontal, 10)
.padding(.vertical, 6)
.background(.bar, in: Capsule())
Expand All @@ -765,7 +765,7 @@ struct CanvasView: View {
selectAllCards()
} label: {
Image(systemName: "checkmark.rectangle.stack")
.font(.body)
.interfaceFont(.body)
.accessibilityLabel("Select All")
}
.buttonStyle(.bordered)
Expand All @@ -782,7 +782,7 @@ struct CanvasView: View {
arrangeCardsWithFit()
} label: {
Image(systemName: "rectangle.3.group")
.font(.body)
.interfaceFont(.body)
.accessibilityLabel("Arrange")
}
.buttonStyle(.bordered)
Expand All @@ -797,7 +797,7 @@ struct CanvasView: View {
organizeCardsWithFit()
} label: {
Image(systemName: "square.grid.2x2")
.font(.body)
.interfaceFont(.body)
.accessibilityLabel("Organize")
}
.buttonStyle(.bordered)
Expand All @@ -812,7 +812,7 @@ struct CanvasView: View {
tileCardsWithFit()
} label: {
Image(systemName: "rectangle.split.2x1")
.font(.body)
.interfaceFont(.body)
.accessibilityLabel("Tile")
}
.buttonStyle(.bordered)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ private struct CommandPaletteSectionHeader: View {

var body: some View {
Text(title.uppercased())
.font(.caption2.weight(.semibold))
.interfaceFont(.caption2, weight: .semibold)
.foregroundStyle(.secondary)
.padding(.horizontal, 6)
.padding(.bottom, 2)
Expand Down Expand Up @@ -671,7 +671,7 @@ private struct CommandPaletteRowView: View {
} else if let leadingIcon {
Image(systemName: leadingIcon)
.foregroundStyle(emphasis ? .primary : .secondary)
.font(.subheadline.weight(.medium))
.interfaceFont(.subheadline, weight: .medium)
.frame(width: 16, height: 16, alignment: .center)
.accessibilityHidden(true)
}
Expand All @@ -682,7 +682,7 @@ private struct CommandPaletteRowView: View {

if let subtitle = row.subtitle {
Text(subtitle)
.font(.caption)
.interfaceFont(.caption)
.foregroundStyle(.secondary)
}
}
Expand All @@ -691,7 +691,7 @@ private struct CommandPaletteRowView: View {

if let badge, !badge.isEmpty {
Text(badge)
.font(.caption2.weight(.medium))
.interfaceFont(.caption2, weight: .medium)
.padding(.horizontal, 7)
.padding(.vertical, 3)
.background(
Expand Down
4 changes: 2 additions & 2 deletions supacode/Features/Debug/Views/IconCatalogView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ import SwiftUI
.frame(width: 32, height: 32, alignment: .center)
VStack(alignment: .leading, spacing: 2) {
Text(token)
.font(.body.monospaced().weight(.semibold))
.interfaceFont(.body, weight: .semibold, design: .monospaced)
Text(detailLine)
.font(.caption.monospaced())
.interfaceFont(.caption, design: .monospaced)
.foregroundStyle(.secondary)
}
Spacer(minLength: 0)
Expand Down
8 changes: 4 additions & 4 deletions supacode/Features/DiffView/DiffWindowContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ struct DiffWindowContentView: View {
.foregroundStyle(.orange)
.accessibilityHidden(true)
Text(renderError.message)
.font(.caption)
.interfaceFont(.caption)
.multilineTextAlignment(.center)
}
.padding(12)
Expand Down Expand Up @@ -269,17 +269,17 @@ private struct FileRowView: View {
var body: some View {
HStack(spacing: 6) {
Text(file.statusSymbol)
.font(.caption)
.interfaceFont(.caption)
.monospaced()
.foregroundStyle(file.status.color)
.frame(width: 14, alignment: .center)
VStack(alignment: .leading, spacing: 1) {
Text(file.displayName)
.font(.body)
.interfaceFont(.body)
.lineLimit(1)
if !file.directoryPath.isEmpty {
Text(file.directoryPath)
.font(.caption)
.interfaceFont(.caption)
.foregroundStyle(.secondary)
.lineLimit(1)
.truncationMode(.head)
Expand Down
Loading
Loading