native macOS codings agent orchestrator prowl.onev.cat
Something went wrong. Try again.
4.1 kB · 142 lines
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143import SwiftUI
struct RepoHeaderRow: View { private static let debugHeaderLayers = false let name: String /// User-defined display title resolved by the parent reducer. When /// non-nil, takes precedence over `name` for display. var customTitle: String? let isRemoving: Bool /// User-pinned icon, when set. Renders before the repo name. /// `nil` keeps the historical text-only layout intact. let icon: RepositoryIconSource? /// Resolved tint applied to tintable icons (SF Symbols / SVGs). /// PNGs and bundled assets ignore this and render their own colors. let iconTint: Color? /// Repo root URL — needed by `RepositoryIconImage` to resolve /// user-imported image filenames into absolute file URLs. let repositoryRootURL: URL? var nameTooltip: String?
var body: some View { HStack { if let icon, let repositoryRootURL { RepositoryIconImage( icon: icon, repositoryRootURL: repositoryRootURL, tintColor: iconTint, size: 14 ) } RepoDisplayName( fallbackName: name, customTitle: customTitle, tooltip: nameTooltip ) .foregroundStyle(.secondary) if isRemoving { Text("Removing...") .font(.caption) .foregroundStyle(.tertiary) } } .background { if Self.debugHeaderLayers { Rectangle() .fill(.cyan.opacity(0.18)) .overlay { Rectangle() .stroke(.cyan, lineWidth: 1) } } } }}
/// Leaf view that renders the open-tab count badge for a repository.////// Lives in its own `View` so the read of `terminalManager` (an/// `@Observable` whose `states` dictionary churns whenever terminal/// activity happens) is isolated to this subtree. Without this split,/// `RepositorySectionView.body` would subscribe to every change in/// `terminalManager.states` on every re-evaluation — which under heavy/// terminal activity caused tens of thousands of body invocations per/// second across the sidebar.struct RepoHeaderTabCountBadge: View { let repository: Repository let terminalManager: WorktreeTerminalManager
var body: some View { TabCountBadge( count: RepositorySectionView.openTabCount( for: repository, terminalManager: terminalManager ) ) }}
/// Leaf view that renders the open-tab count badge for a single worktree/// row. Isolated for the same reason as `RepoHeaderTabCountBadge`: only/// this subtree subscribes to terminal state churn.struct WorktreeTabCountBadge: View { let worktreeID: Worktree.ID let terminalManager: WorktreeTerminalManager
var body: some View { TabCountBadge( count: terminalManager.stateIfExists(for: worktreeID)?.tabManager.tabs.count ?? 0 ) }}
/// Capsule open-tab count badge shared by the repository header and/// worktree rows. Hidden at count 0.struct TabCountBadge: View { let count: Int
var body: some View { if count > 0 { Text("\(count)") .font(.caption2) .monospacedDigit() .foregroundStyle(.secondary) .padding(.horizontal, 5) .padding(.vertical, 1) .background(.quaternary, in: .capsule) // Keep natural size when the row is width-starved; the sibling // name text (higher layout priority) truncates instead. .fixedSize() .help("\(count) active \(count == 1 ? "tab" : "tabs")") } }}
// MARK: - Previews
#Preview("RepoHeaderRow") { VStack(alignment: .leading, spacing: 12) { RepoHeaderRow( name: "supacode", isRemoving: false, icon: nil, iconTint: nil, repositoryRootURL: nil ) RepoHeaderRow( name: "ghostty", isRemoving: false, icon: .sfSymbol("folder.fill"), iconTint: .blue, repositoryRootURL: URL(fileURLWithPath: "/tmp/ghostty") ) RepoHeaderRow( name: "removing-repo", isRemoving: true, icon: .sfSymbol("hammer.fill"), iconTint: .orange, repositoryRootURL: URL(fileURLWithPath: "/tmp/removing") ) } .padding()}