native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(repo-appearance): show repo icon and color dot in the sidebar

- RepoHeaderRow renders the user-pinned icon (when set) before the repo
name via the shared RepositoryIconImage. Tinting follows the icon's
own `isTintable` rule so PNG keeps its colors and SVG/SF Symbols pick
up the repo color.
- RepositorySectionView reads `@Shared(.repositoryAppearances)` once
per row and forwards the icon + tint to RepoHeaderRow. When a color
is set it draws a Finder-style 8pt color dot at the trailing edge —
in front of the hover-revealed action buttons so the tag stays
visible at rest and shifts only slightly when the row is hovered.
- No behavior change for repos with no appearance entry: the
conditional rendering keeps the row pixel-identical to the prior
text-only layout.

onevcat 434d9202 2ed1eb3f

+55 -3
+42 -3
supacode/Features/Repositories/Views/RepoHeaderRow.swift
··· 5 5 let name: String 6 6 let isRemoving: Bool 7 7 let tabCount: Int 8 + /// User-pinned icon, when set. Renders before the repo name. 9 + /// `nil` keeps the historical text-only layout intact. 10 + let icon: RepositoryIconSource? 11 + /// Resolved tint applied to tintable icons (SF Symbols / SVGs). 12 + /// PNGs and bundled assets ignore this and render their own colors. 13 + let iconTint: Color? 14 + /// Repo root URL — needed by `RepositoryIconImage` to resolve 15 + /// user-imported image filenames into absolute file URLs. 16 + let repositoryRootURL: URL? 8 17 var nameTooltip: String? 18 + 9 19 var body: some View { 10 20 HStack { 21 + if let icon, let repositoryRootURL { 22 + RepositoryIconImage( 23 + icon: icon, 24 + repositoryRootURL: repositoryRootURL, 25 + tintColor: iconTint, 26 + size: 14 27 + ) 28 + } 11 29 Text(name) 12 30 .foregroundStyle(.secondary) 13 31 .help(nameTooltip ?? "") ··· 44 62 45 63 #Preview("RepoHeaderRow") { 46 64 VStack(alignment: .leading, spacing: 12) { 47 - RepoHeaderRow(name: "supacode", isRemoving: false, tabCount: 3) 48 - RepoHeaderRow(name: "ghostty", isRemoving: false, tabCount: 0) 49 - RepoHeaderRow(name: "removing-repo", isRemoving: true, tabCount: 1) 65 + RepoHeaderRow( 66 + name: "supacode", 67 + isRemoving: false, 68 + tabCount: 3, 69 + icon: nil, 70 + iconTint: nil, 71 + repositoryRootURL: nil 72 + ) 73 + RepoHeaderRow( 74 + name: "ghostty", 75 + isRemoving: false, 76 + tabCount: 0, 77 + icon: .sfSymbol("folder.fill"), 78 + iconTint: .blue, 79 + repositoryRootURL: URL(fileURLWithPath: "/tmp/ghostty") 80 + ) 81 + RepoHeaderRow( 82 + name: "removing-repo", 83 + isRemoving: true, 84 + tabCount: 1, 85 + icon: .sfSymbol("hammer.fill"), 86 + iconTint: .orange, 87 + repositoryRootURL: URL(fileURLWithPath: "/tmp/removing") 88 + ) 50 89 } 51 90 .padding() 52 91 }
+13
supacode/Features/Repositories/Views/RepositorySectionView.swift
··· 1 1 import ComposableArchitecture 2 + import Sharing 2 3 import SwiftUI 3 4 4 5 struct RepositorySectionView: View { ··· 14 15 @Environment(\.colorScheme) private var colorScheme 15 16 @Environment(\.resolvedKeybindings) private var resolvedKeybindings 16 17 @State private var isHovering = false 18 + @Shared(.repositoryAppearances) private var repositoryAppearances 17 19 18 20 var body: some View { 19 21 let state = store.state ··· 34 36 } 35 37 let isDragging = isDragActive 36 38 39 + let appearance = repositoryAppearances[repository.id] ?? .empty 37 40 let header = HStack { 38 41 RepoHeaderRow( 39 42 name: repository.name, ··· 42 45 for: repository, 43 46 terminalManager: terminalManager 44 47 ), 48 + icon: appearance.icon, 49 + iconTint: appearance.color?.color, 50 + repositoryRootURL: repository.rootURL, 45 51 nameTooltip: repository.capabilities.supportsWorktrees 46 52 ? (isExpanded ? "Collapse" : "Expand") 47 53 : "Open terminal in folder" ··· 70 76 } 71 77 } 72 78 } 79 + } 80 + if let color = appearance.color { 81 + Circle() 82 + .fill(color.color) 83 + .frame(width: 8, height: 8) 84 + .help(color.displayName) 85 + .accessibilityLabel(Text("Repo color: \(color.displayName)")) 73 86 } 74 87 if isHovering && !isDragging { 75 88 Menu {