krz/hutch

an ios client for sourcehut

clone: git clone https://gitbay.org/krz/hutch.git

18a9f62c9acadced60657addb61c2d4d8c1aab17

verified · cmc

author: Christian Cleberg <hello@cleberg.net> · 2026-04-03T04:21:53Z

fix: remove stray files
 codex-fix-refs-type-conflict.md |  89 --------------
 codex-user-resource-browsing.md | 249 ----------------------------------------
 2 files changed, 338 deletions(-)

diff --git a/codex-fix-refs-type-conflict.md b/codex-fix-refs-type-conflict.md
deleted file mode 100644
index 4ff2eec..0000000
--- a/codex-fix-refs-type-conflict.md
+++ /dev/null
@@ -1,89 +0,0 @@
-# Fix: Conflicting `[Reference]` vs `[ReferenceDetail]` in RepositorySettingsView
-
-## Background
-
-`RepositoryDetailViewModel.branches` was recently changed from `[Reference]` to
-`[ReferenceDetail]` to support displaying commit dates in the Refs tab.
-`ReferenceDetail` has the same `name: String` and `target: String?` fields as
-`Reference`, plus an additional `date: Date?`.
-
-`RepositorySettingsView` and `RepositorySettingsViewModel` still declare their
-`branches` parameter as `[Reference]`, causing this compiler error:
-
-```
-RepositoryDetailView.swift:56:51
-Conflicting arguments to generic parameter 'T' ('[ReferenceDetail]' vs. '[Reference]')
-```
-
-The settings view model only uses `branches` for the HEAD branch picker
-(`selectedHeadReferenceForSave()` accesses `$0.name`). No mapping back to
-`Reference` is needed — just update the type throughout the settings layer.
-
----
-
-## Changes Required
-
-### 1. `Hutch/Views/Repositories/RepositorySettingsViewModel.swift`
-
-**Change the stored property type:**
-
-Find:
-```swift
-var branches: [Reference]
-```
-
-Replace with:
-```swift
-var branches: [ReferenceDetail]
-```
-
-**Change the `init` parameter type:**
-
-Find:
-```swift
-init(
-    repository: RepositorySummary,
-    branches: [Reference],
-    client: SRHTClient
-) {
-```
-
-Replace with:
-```swift
-init(
-    repository: RepositorySummary,
-    branches: [ReferenceDetail],
-    client: SRHTClient
-) {
-```
-
-### 2. `Hutch/Views/Repositories/RepositorySettingsView.swift`
-
-**Change the stored property type:**
-
-Find:
-```swift
-let branches: [Reference]
-```
-
-Replace with:
-```swift
-let branches: [ReferenceDetail]
-```
-
----
-
-## No Other Changes
-
-- Do not modify `Reference` or `ReferenceDetail` in `Git.swift`.
-- Do not modify `RepositoryDetailView.swift` — the call site is already correct.
-- Do not modify `ReferencesListView.swift` or `RepositoryDetailViewModel.swift`.
-- `selectedHeadReferenceForSave()` in the settings view model accesses only
-  `$0.name` on each branch, which exists on `ReferenceDetail` — no logic
-  changes are needed.
-
-## Verification
-
-Build the project. The compiler error at `RepositoryDetailView.swift:56` should
-be gone. Confirm the repository settings sheet still opens and the HEAD branch
-picker populates correctly.
diff --git a/codex-user-resource-browsing.md b/codex-user-resource-browsing.md
deleted file mode 100644
index c37be38..0000000
--- a/codex-user-resource-browsing.md
+++ /dev/null
@@ -1,249 +0,0 @@
-# feat: User resource browsing from profile
-
-## Goal
-
-Extend `UserProfileView` so that after looking up a user, their public
-repositories and trackers are shown as browsable sections below the existing
-profile metadata. This mirrors the sr.ht `~username` page.
-
----
-
-## Context
-
-**Entry point:** `Hutch/Views/Lookup/LookupView.swift`
-Looking up a user opens `UserProfileView` in a sheet. Currently the view only
-shows static metadata fields from the `User` model.
-
-**Owner identifier:** `user.canonicalName` (e.g. `~username`). Strip the leading
-`~` when passing to GraphQL `username` parameters — see the existing pattern in
-`AppState.resolveRepository(owner:name:)`.
-
-**Existing row views to reuse:**
-- `RepositoryRowView` in `Hutch/Views/Repositories/RepositoryRowView.swift`
-- Tracker row style from `TrackerListView` private `TrackerRowView`
-
-**API pattern for user-scoped queries** (from `AppState.swift`):
-```graphql
-query repoLookup($owner: String!, $name: String!) {
-    user(username: $owner) {
-        repository(name: $name) { ... }
-    }
-}
-```
-The same `user(username:)` root field supports `repositories` and `trackers`
-paginated collections on git.sr.ht and todo.sr.ht respectively.
-
----
-
-## New File: `Hutch/Views/Lookup/UserProfileViewModel.swift`
-
-Create an `@Observable @MainActor` view model following the same pattern as
-`RepositoryListViewModel` and `TrackerListViewModel`.
-
-```swift
-@Observable
-@MainActor
-final class UserProfileViewModel {
-    private(set) var repositories: [RepositorySummary] = []
-    private(set) var trackers: [TrackerSummary] = []
-    private(set) var isLoadingRepositories = false
-    private(set) var isLoadingTrackers = false
-    var repositoriesError: String?
-    var trackersError: String?
-
-    private let client: SRHTClient
-    let ownerUsername: String  // without leading ~
-
-    init(ownerUsername: String, client: SRHTClient) { ... }
-
-    func loadRepositories() async { ... }
-    func loadTrackers() async { ... }
-}
-```
-
-**GraphQL queries:**
-
-Repositories (execute against `.git` service):
-```graphql
-query userRepositories($owner: String!) {
-    user(username: $owner) {
-        repositories {
-            results {
-                id rid name description visibility updated
-                owner { canonicalName }
-                HEAD { name target }
-            }
-            cursor
-        }
-    }
-}
-```
-
-Trackers (execute against `.todo` service):
-```graphql
-query userTrackers($owner: String!) {
-    user(username: $owner) {
-        trackers {
-            results {
-                id rid name description visibility updated
-                owner { canonicalName }
-            }
-            cursor
-        }
-    }
-}
-```
-
-Decode using private response structs identical to those in
-`RepositoryListViewModel` and `TrackerListViewModel`. Map results to
-`RepositorySummary` and `TrackerSummary` exactly as those view models do.
-
----
-
-## Modified File: `Hutch/Views/Lookup/UserProfileView.swift`
-
-### View model instantiation
-
-Add `@State private var profileViewModel: UserProfileViewModel?` and initialise
-it in `.task` using `user.canonicalName` with the leading `~` stripped:
-
-```swift
-.task {
-    let owner = user.canonicalName.hasPrefix("~")
-        ? String(user.canonicalName.dropFirst())
-        : user.canonicalName
-    let vm = UserProfileViewModel(ownerUsername: owner, client: appState.client)
-    profileViewModel = vm
-    async let repos: () = vm.loadRepositories()
-    async let trackers: () = vm.loadTrackers()
-    _ = await (repos, trackers)
-}
-```
-
-Restore `@Environment(AppState.self) private var appState` (it was removed in a
-recent commit but is needed for `client` access).
-
-### Repositories section
-
-Add after the existing metadata sections:
-
-```swift
-Section {
-    if viewModel.isLoadingRepositories && viewModel.repositories.isEmpty {
-        ProgressView()
-    } else if viewModel.repositories.isEmpty {
-        Text("No public repositories.")
-            .foregroundStyle(.secondary)
-    } else {
-        ForEach(viewModel.repositories.prefix(4)) { repo in
-            NavigationLink {
-                RepositoryDetailView(repository: repo)
-            } label: {
-                RepositoryRowView(repository: repo, buildStatus: .none)
-            }
-        }
-        if viewModel.repositories.count > 4 {
-            NavigationLink("See All") {
-                UserRepositoriesView(viewModel: viewModel)
-            }
-        }
-    }
-} header: {
-    Text("Repositories")
-}
-```
-
-### Trackers section
-
-Immediately after the Repositories section:
-
-```swift
-Section {
-    if viewModel.isLoadingTrackers && viewModel.trackers.isEmpty {
-        ProgressView()
-    } else if viewModel.trackers.isEmpty {
-        Text("No public trackers.")
-            .foregroundStyle(.secondary)
-    } else {
-        ForEach(viewModel.trackers.prefix(4)) { tracker in
-            NavigationLink {
-                TicketListView(tracker: tracker)
-            } label: {
-                TrackerRowView(tracker: tracker)
-            }
-        }
-        if viewModel.trackers.count > 4 {
-            NavigationLink("See All") {
-                UserTrackersView(viewModel: viewModel)
-            }
-        }
-    }
-} header: {
-    Text("Trackers")
-}
-```
-
-`TrackerRowView` — use the same VStack layout as the private `TrackerRowView`
-in `TrackerListView.swift`. Define it as a private struct in
-`UserProfileView.swift` rather than duplicating from `TrackerListView`.
-
----
-
-## New File: `Hutch/Views/Lookup/UserRepositoriesView.swift`
-
-A simple full-list view for "See All" repositories:
-
-```swift
-struct UserRepositoriesView: View {
-    let viewModel: UserProfileViewModel
-
-    var body: some View {
-        List {
-            ForEach(viewModel.repositories) { repo in
-                NavigationLink {
-                    RepositoryDetailView(repository: repo)
-                } label: {
-                    RepositoryRowView(repository: repo, buildStatus: .none)
-                }
-            }
-        }
-        .listStyle(.plain)
-        .navigationTitle("Repositories")
-        .navigationBarTitleDisplayMode(.inline)
-        .overlay {
-            if viewModel.isLoadingRepositories && viewModel.repositories.isEmpty {
-                SRHTLoadingStateView(message: "Loading repositories…")
-            }
-        }
-        .refreshable {
-            await viewModel.loadRepositories()
-        }
-    }
-}
-```
-
-## New File: `Hutch/Views/Lookup/UserTrackersView.swift`
-
-Same pattern as `UserRepositoriesView` but for trackers, navigating to
-`TicketListView(tracker:)`.
-
----
-
-## Navigation context
-
-`UserProfileView` is always presented inside a `NavigationStack` via the sheet
-in `LookupView`. `NavigationLink` destinations push correctly within that stack.
-No changes to `LookupView` or `MoreRoute` are needed.
-
----
-
-## Verification
-
-1. Look up a user with public repositories and trackers. Confirm both sections
-   appear below the profile metadata.
-2. Tap a repository row — confirm `RepositoryDetailView` pushes correctly.
-3. Tap a tracker row — confirm `TicketListView` pushes correctly.
-4. For users with more than 4 items, confirm "See All" pushes the full list.
-5. Look up a user with no public resources — confirm the empty-state text
-   renders in each section rather than crashing.
-6. Build with no warnings.