# 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.