Drop `*http.Request` from handlers that only needed it for the request
context or `URL.Query()`, and replace `params := c.Params()` indexing
with `c.Param(...)` lookups. Every handler in webapi_repo.go now takes
just `(c flamego.Context, user *database.User)`.
Apply review feedback on PR #8295. Flatten `repoHeaderCounts` into
`repoHeader` and rename fields to be more descriptive on the JSON wire
(`isViewerAdmin`, `issuesEnabled`, `pullRequestsEnabled`, `wikiEnabled`,
`watches`, `openPullRequests`, `isViewerWatching`, `hasViewerStarred`).
Apply the same naming to `repoActionResponse`. Rename `getRepoRaw` ->
`getRepoRawFile` with `{file}` param. Update the TS types and consumers
in `RepoHeader.tsx` to match.
Merge the author and parent/commit/buttons rows into a single
wrap-friendly flex line on desktop. Drop the committer line, since
showing it twice (author + committer) is rarely useful for the
common case where they match. Render each parent SHA as its own
clickable chip so multi-parent merge commits link to every parent.
Align View patch and Browse files to the left on mobile.
The commit diff page only ships the patch hunks, so unmodified context
between hunks is invisible. Add a per-file "Expand all lines" toggle so
the reader can pull in the full file when the surrounding code matters.
Backend:
- Migrate `repo.SingleDownload` to a new Flamego `getRepoRaw` handler.
Same URL shape (`/{owner}/{name}/raw/{ref}/{path}`) so external
consumers (`curl`, scripts) keep working. Bridged from the Macaron
router via `flamegoBridger` so the legacy path doesn't double-route
through `RepoRef` middleware. The ref segment accepts a branch, tag,
or commit SHA; commit SHAs match first (the common case from the
React diff page).
- Delete `repo.SingleDownload` and the legacy `m.Get("/raw/*", ...)`
Macaron handler. `repo.ServeBlob` stays because `internal/route/api/v1`
still uses it for the public REST API.
Frontend:
- Add an `UnfoldVertical` icon button to each file header. Click fetches
the pre + post file contents in parallel via the legacy raw URL,
calls `parseDiffFromFile` to upgrade the `FileDiffMetadata` to
`isPartial: false`, and stores the result keyed by item id.
- The `items` useMemo swaps in the upgraded `fileDiff` when present and
bumps the item `version` so Pierre's `CodeView` re-renders that file.
Set `expandUnchanged: true` globally so non-partial files immediately
render all context lines.
- Show a spinner during fetch, hide the button once expansion succeeds.
Skip the button for added/deleted files (no opposite side to expand).
- Added/deleted files preserve the old behaviour (no expansion).
Migrate the React commit diff page off of mocked repo metadata and onto
live web API endpoints, and take over the legacy `/owner/repo/commit/{sha}`
URL so the React page is the canonical commit view.
Backend:
- Split `webapi.go` into `webapi.go` (shared infra), `webapi_user.go`
(user handlers), and `webapi_repo.go` (repo handlers).
- Add `GET /api/web/{owner}/{name}/info` returning repo header data
(avatar, visibility, counts, mirror, viewer state). Mirrors legacy
`RepoAssignment` access logic: admin shortcut + partial-public masking.
- Add `GET /api/web/{owner}/{name}/commit/{sha}` returning commit
metadata only. Patch text lives on the existing `.diff` URL so it
avoids JSON-string escaping and caches independently.
- Migrate `repo.RawDiff` to Flamego `getRepoCommitRawDiff`. Now supports
`?whitespace=` for the React diff toggle. Public URL unchanged.
- Add `POST/DELETE /api/web/{owner}/{name}/watch` and `.../star` returning
the new viewer state + count so the client can update without refetch.
- Delete legacy `repo.Diff` and `repo.DiffJSON`. Add a SPA pass-through
Macaron route at `/owner/repo/commit/{sha}` with the legacy
`[a-f0-9]{7,40}` SHA regex.
Frontend:
- Install `@tanstack/react-query` and wire `QueryClientProvider` in
`router.tsx`. Pass `queryClient` through router context so loaders can
prefetch via `ensureQueryData`.
- Add `lib/queries/repo.ts` with `repoInfoQuery` + watch/star mutations.
- Move `CommitDiff.tsx` → `pages/repo/Commit.tsx` and `CommitDiff.search.ts`
→ `pages/repo/Commit.search.ts`. Rename `CommitDiff` → `RepoCommit`,
`CommitDiffPage` → `RepoCommitPage`, etc.
- Change route from `/$owner/$repo/_diff/$sha` to
`/$owner/$repo/commit/$sha`. Enforce SHA regex via TanStack `params.parse`
and convert API 404s to router `notFound()` so they render the NotFound
page instead of ServerError.
- Loader fetches metadata + raw diff in parallel (plus repo info via
Query cache), assembles them into `RepoCommitPage`.
- Replace `RepoHeader`'s `RepoHeaderRepo` interface with the live
`RepoInfo` type. Watch/Star buttons fire `useMutation` with optimistic
cache updates via `setQueryData`. Anonymous users see sign-in links.
- Swap the "Public"/"Private" pill for a Globe/Lock icon with tooltip.
- Add a collapsible desktop file tree. The toolbar's "Showing N changed
files" row owns a single toggle icon that opens the Sheet on mobile
and toggles the persistent sidebar on desktop. State persists to
localStorage.
- Hide the always-on "Verified" badge until commit signature
verification lands.
- DiffSearch: walk hunks by addition/deletionCount so matches on context
lines and pure-deletion hunks are no longer dropped.
- DiffSearch: nudge popup up to top-1 so it sits closer to the toolbar.
- RepoHeader: add per-repo avatar slot (mocked to favicon for now),
fold mobile tabs past the third into a hamburger overflow, swap
Issues icon from Clock to CircleDot, nudge avatar down 2px to
optically center the off-center favicon glyph.
- CommitDiff: render the authored timestamp as a relative string with
RFC1123 tooltip (matches Gogs's TimeSince template helper); helper
lives in web/src/lib/relative-time.ts.
- CommitDiff: inject GitHub-style yellow into Pierre's selected-line
background overrides so search matches read clearly in both themes.
- AGENTS.md: note that chrome-devtools MCP should run headless.
Adds the full commit diff experience around the @pierre/diffs CodeView
and @pierre/trees FileTree spike from the prior commit:
- RepoHeader, DiffToolbar, FileHeaderMenu, ResizableSidebar components
for the page chrome and per-file actions
- Sheet and Tooltip shadcn primitives
- CommitDiff.search.ts encodes diff toggles in the URL via TanStack
Router validation so the view is shareable
- Sticky workspace lock that pins the toolbar plus tree plus diff to
the viewport once the user scrolls past the commit metadata
- Whitespace mode wired through to git via the diff API's new
whitespace query (ignore-all, ignore-change)
- Per-file collapse, status filter, unified/split toggle, wrap, expand
all and collapse all
- New --color-success, --color-diff-added, --color-diff-removed
tokens documented in DESIGN.md, replacing ad-hoc Tailwind palette
references