Ubisam-MobileGit/tasks/034-favorite-star-count-not-incrementing.md
choiminyeong 6dbb37d067 TASK-034: fix favorite star count not incrementing after a successful star
toggleFavorite's ALL-list success branch updated favoriteAction to
Starred but never touched starsCount, so a row kept showing its
pre-star count even after the server had actually accepted it. Now
increments starsCount by 1 in the same update. Also guards against a
repeat tap on an already-Starred row (the ALL list can't tell a
repo's already-starred state on load, so the star stays tappable)
double-incrementing the displayed count.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-29 16:37:17 +09:00

89 lines
4.9 KiB
Markdown

# TASK-034: Star count doesn't increment after a successful favorite
Status: implemented; all required checks pass; live-installed, awaiting the human product owner's confirmation
Owner: Claude
Reviewer: Codex
## Outcome
Following TASK-033's OAuth scope fix, the human product owner confirmed starring itself now works
("별표 눌러서 즐겨찾기는 되는데") but reported the displayed star count doesn't go up
("카운팅은 안올라가네"). `toggleFavorite`'s ALL-list success branch updated only `favoriteAction`
(to `Starred`) and never touched `starsCount`, so a row kept showing whatever count the last full
list load had returned, even after a star that the server had actually accepted. Fixed by
incrementing the row's `starsCount` in the same state update that marks it `Starred`. While fixing
this, found and closed a related gap: a repeat tap on an already-`Starred` row (the ALL list has no
way to know a repository's already-starred state on initial load, so the star stays tappable) would
have re-called `star()` and double-incremented the client-displayed count each time — now a no-op.
## Scope
- Included: `feature/repositories/RepositoryListViewModel.kt` (`toggleFavorite` only), matching
test additions in `RepositoryListViewModelTest.kt`.
- Excluded: No change to the FAVORITES-list unstar path (removing the row entirely already made
its count irrelevant, no bug there). No change to how the initial list load populates
`starsCount` (that already came from Gitea's own response, unaffected). No attempt to fetch the
server's authoritative post-star count instead of incrementing client-side (see Design notes).
## Design notes
- **Optimistic +1, not a re-fetch**: Gitea's star endpoint (`PUT`, 204 No Content) doesn't return
the new count, so getting the authoritative number back would mean a second network call
(re-fetching the repository) purely to update one number — not worth it for a value the app
already knows how to derive from something it just confirmed itself (the star succeeded, so the
count is exactly one higher than what was last displayed).
- **The repeat-tap guard closes a real double-count bug, not just a hypothetical one**: because the
ALL list can't determine a repository's already-starred state on load (an existing, accepted
limitation from TASK-018/TASK-030), a `Starred` row's star icon stays enabled and tappable —
nothing before this fix stopped a second tap from calling `star()` again and incrementing the
displayed count a second time for a repository the user only starred once. The guard checks the
row's own `favoriteAction` before doing anything, so it also saves a redundant network call, not
just a redundant `+1`.
## Acceptance criteria
- [x] Starring a repository from the ALL list increments its displayed star count by exactly 1.
- [x] Tapping an already-`Starred` row again does not call `star()` a second time and does not
change the displayed count further.
- [x] Unstarring from the FAVORITES list is unaffected (row removal, no count to update).
- [x] Build, unit tests, and lint pass.
- [ ] Live confirmation from the human product owner that the count now visibly increments on tap —
installed on the device but not yet re-tested in this exact session.
## Required checks
```text
./gradlew compileDebugKotlin compileDebugUnitTestKotlin
./gradlew testDebugUnitTest
./gradlew assembleDebug lintDebug
```
## Evidence
- `RepositoryListViewModel.kt`: `toggleFavorite`'s ALL-list success branch now updates
`starsCount = it.starsCount + 1` alongside `favoriteAction = Starred`; new early-return guard
when the row's `favoriteAction` is already `Starred`.
- `RepositoryListViewModelTest.kt`: `repo()` test helper gained a `starsCount` parameter; two new
tests — starring increments the displayed count by 1; a repeat tap after a successful star is a
no-op (no second `star()` call, count stays at 1).
- `./gradlew compileDebugKotlin compileDebugUnitTestKotlin`: BUILD SUCCESSFUL.
- `./gradlew testDebugUnitTest`: BUILD SUCCESSFUL, all unit tests passing (including the two new
ones above).
- `./gradlew assembleDebug lintDebug`: BUILD SUCCESSFUL, 0 lint errors.
- Installed on the human product owner's device over wireless `adb` (`adb install -r`, streamed
install succeeded); not yet re-tested live in this exact session.
## Known limitations
- Still optimistic, not authoritative: if Gitea's real count differs from this app's local
increment for any reason (e.g. another client starred the same repo around the same time), the
displayed number stays off until the next full list reload. Considered an acceptable tradeoff
given the alternative (a second network call per star) for a rarely-contended personal count.
- The underlying "can't tell if already starred on initial load" limitation (TASK-018/TASK-030)
is unchanged — this task only stops it from causing a *visible count* bug, it doesn't resolve the
limitation itself.
## Review findings
None yet — pending Codex/human review.