Mirror UX: no mirror indicator on explore/owner listings, push guidance shown for mirrors awaiting first sync, import page can't create mirrors #281
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub#281
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-ups to the mirror feature (Forgejo #240, now implemented): three gaps between what the mirror system does and what the UI communicates.
1. Explore/owner listings show no mirror indicator
Mirror repos are indistinguishable from normal repos anywhere in listing surfaces.
/exploreand/:ownerrender repo rows via<RepoRow>(web/src/pages/Repos.jsx:38-70— link +<StarCount>+<ActivityStamp>), which has no mirror awareness; the mirror badge exists only on the repo page itself (Repo.jsx:541, Forgejo #240 badge + next-sync).The data is already available per row-adjacent: the repo summary carries
mirror: {upstream_url, schedule, next_sync_at, last_synced_at, last_result}(verified live:GET /anon/walhub/api→ full mirror object). ButGET /api/v1/owners/{owner}/reposreturns names/shapes without mirror flags (see #247/#248's catalog work for the listing-shape precedent).Ask: a clear mirror indicator on listing rows — a mirror emoji or the established icon set's mirror glyph (note: a 4-byte emoji in the issue body breaks Forgejo's DB charset — use a 2-byte one like e.g.
#-prefixed mirror glyph or an inline SVG icon in the UI itself or an inline SVG icon in the UI itself) next to the repo name, withtitle/aria-label"mirror of " for hover/screen-reader. On/exploreand/:owner; also the search/user profile rows if shared.Implementation note: either extend the owner-repos listing payload with a
mirror: bool(rides the #247 catalog wire change — same file, same pattern), or have<RepoRow>fetch per-row (anti-pattern — the listing already exists; don't add N summary GETs). Prefer the payload extension.2. Mirror repos awaiting first sync show push guidance
While a mirror's first clone is running (or has not yet completed), an empty mirror repo renders
EmptyRepoGuide(web/src/pages/Tree.jsx:237) — which tells the user to push: "git push -u origin main… the first push lands directly" (web/src/components/EmptyRepoGuide.jsx:134-139). For a pull-only mirror this is doubly wrong: the push will be rejected (pull-only), and the correct action is wait for the scheduled sync / trigger a sync now.EmptyRepoGuidealready receivessummary(Tree.jsx:237), and the summary carries themirrorprojection (includinglast_synced_at/last_result— enough to distinguish "never synced, first clone pending" from a genuinely empty normal repo).Ask: when
summary.mirroris present, render a mirror-specific waiting state instead of the push guide: "This repository is a read-only mirror of <upstream_url>. First sync in progress — next scheduled sync <next_sync_at>." Plus a "Sync now" affordance if the manual-sync endpoint exists for non-admins (otherwise omit). Push guidance must never render for a mirror.3. Import page can't create mirrors
Mirror creation exists only on the New-repo page (
web/src/pages/New.jsx:27-56— mirror-from-URL mode →POST /api/v1/repos/mirrors). The import page (web/src/pages/Import.jsx) has zero mirror mentions — it drives the one-shot import flow (POST /api/v1/repos/imports) exclusively.Ask: add a mirror option to
/import— either a mode toggle (Import once / Mirror continuously) or a checkbox that switches the submit target fromrepos.imports.starttoPOST /api/v1/repos/mirrorswith a schedule preset. The form fields overlap almost entirely (source URL, owner, name, token),lib/mirror.jsalready exportsMIRROR_PRESETS/validateMirrorCreatefor reuse, and the backend endpoint exists (internal/mirror/http.go:91-93). This is UI wiring, not backend work.Copy note: whichever presentation, keep the semantic distinction honest — import = one-shot snapshot, mirror = recurring pull with push rejected.
Acceptance criteria
/exploreand/:ownerrows, with accessible labeling naming the upstream./importcan create a mirror (mode toggle or equivalent) using the shared mirror validation/presets; the created mirror appears with its indicator per criterion 1.Fix ready for review: PR #298 (fix/issue-281) — listing mirror badge (payload flag, no N+1), mirror waiting state instead of push guidance, /import mirror mode via the #240 create endpoint. All acceptance criteria covered; browser proof open per workspace rules.
Review of PR #298 (fix/issue-281, reviewed at
4d50484; fixup pushed as78ff2b1). No browser per review rules — tests + reasoning only.What I verified (scratch worktree /tmp/opencode/walhub-281; main untouched):
Small fixes pushed to origin/fix/issue-281 (
78ff2b1):Non-blocking observations (possible follow-ups, not merge gates):
Test results (all in scratch worktree):
MERGE RECOMMENDATION: ready to merge.
Fixed by PR #298 incl. review doc/a11y/copy fixups (listing cost acceptable, import mode verified; gates green), merged. Closing.