Lists: repository link, private-repo tag, and Refresh from GitHub (#74) - #176
Merged
Merged
Conversation
Adds the strip that sits under a GitHub-backed list's name, as a self-contained
`GitHubListHeader` control — one line of hosting in `ListsView.xaml`, nothing
added to `ListsViewModel`.
- `owner/repo issues` as a link, opening that repository's issues page in the
OS browser.
- A `Private repo` tag on an explicit `githubRepoPrivate: true`, with copy that
keeps repository access and list visibility apart: they are set separately, so
someone invited to the list may still get a GitHub sign-in page or a 404.
- A **null** `githubRepoPrivate` renders no tag and says why — "visibility
hasn't been recorded yet, it's read from GitHub on the next sync" — rather
than presenting an unrecorded value as public.
- "Refresh from GitHub" calling `POST /api/lists/{id}/refresh`, then re-reading
the list (the refresh envelope is unobserved, and the re-read is also the only
way to pick up a visibility that just changed) and running the host's command
to reload rows.
The endpoint's rejection path is verified live: `POST /api/lists/{id}/refresh`
on a `local` list answers 400 "Refresh is only available for GitHub-backed
lists" and is inert — re-reading gave an identical body with an unchanged
`updatedAt`. The success path could not be exercised: the account owns no
GitHub-backed list and creating one would wire a real repository, so
`ListRefreshResult` keeps the raw body instead of guessing an envelope.
Closes #74
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 16, 2026
ListsView.xaml conflict: GitHubListHeader (#74) and the PoweredTemplatePanel + column form builder (#174/#161) all insert at the top of the right pane. All additive — kept all three. Order is deliberate: GitHubListHeader goes FIRST because it identifies the selected list (owner/repo link, private-repo tag, Refresh from GitHub), so it belongs directly under the title rather than below a large editor panel. Debug and Release both build clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack
main→ #142 (issue-72-github-service) → #175 (issue-73-github-backed-list) → this PR → #76 (reconnect handoff). Base isissue-73-github-backed-list, notmain.What this adds
Views/GitHubListHeader.xaml(.cs)+ViewModels/GitHubListHeaderViewModel.cs— the strip under a GitHub-backed list's name:owner/repo issuesas a link, opening that repository's issues page in the OS browser.Private repotag, with copy that keeps the two visibilities apart.POST /api/lists/{id}/refresh, then a re-read, then the host's row reload.Plus
Models/ListRefreshResult.csandRefreshListFromGitHubAsyncon the GitHub-lists partial.Hosting cost in
ListsView.xaml: 1 lineThe control collapses itself for a local list or a null id, so it needs no conditional wrapper.
ListsViewModelis untouched; so isListsView.xaml.cs; so isModels/ListSummary.cs.The tag is about the repository, not the list — and it has three states
githubRepoPrivateistrue/false/null, and the null case is the one that's easy to get wrong:truePrivate repotag + the explanation belowfalsenullShowPrivateRepoTagfires only on an explicittrue, so a list created before the tag existed is never presented as public — which is exactly what/help/listsrequires ("Lists created before this tag existed show no tag until their first sync"), and whyListSummary.GithubRepoPrivateisbool?in #133.The explanation is shown as body copy, not buried in a tooltip, because the distinction is the point of the tag:
Refresh re-reads, and that isn't belt-and-braces
Two independent reasons the
POSTalone isn't enough:githubRepoPrivatemay have just changed — the re-read is how the tag updates. When it does change, the status line says so explicitly.The re-read also writes back into
GitHubListIndex, so the browser badge stays in step, andAfterRefreshCommandreloads the rows (a refresh rewrites them from the repository's issues).Verified live (test account, 2026-09-16)
POST /api/lists/{id}/refreshagainst a throwaway local list — created asZZ claude-probe refresh, probed, deleted, and confirmed gone with a closingGET(404 not_found), leaving the account's own singleNew listuntouched:So the 400 is safe and specific, and it's what
CanRefreshprevents you reaching — surfaced as "This list isn't GitHub-backed, so there's nothing to refresh from" if the list'ssourceever changes underneath the UI.Also confirmed:
GET /api/listsandGET /api/lists/{id}both carrysource/githubRepo/githubRepoPrivate.dotnet build -c Debugand-c Release— both green, 0 warnings.Deliberately not called
201with the body "not individually modelled yet", soListRefreshResultkeepsRawand picks upmessage/refreshStatus/ a count if they happen to be present, rather than typing an envelope nobody has seen. Needs one live refresh of a real GitHub-backed list before it can be called verified — the field names are the only guess in this PR.POST /api/github/issues, thePATCH, the comments endpoint — real GitHub writes, GitHub: issue create / update / comment from list rows #75's territory.Closes #74
🤖 Generated with Claude Code