No task waits on a Codex review; the redesign tasks are confirmed on the product owner's Z Fold7; TASK-016's leftovers are on hold; no biometric reauthentication. Agent: main (opus) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
164 lines
11 KiB
Markdown
164 lines
11 KiB
Markdown
# TASK-030: Gitea-green theme, pagination footer height fix, repository row language/favorite
|
|
|
|
Status: implemented; all required checks pass; the human product owner has not yet confirmed live
|
|
Owner: Claude
|
|
Reviewer: Codex
|
|
|
|
## Outcome
|
|
|
|
Three connected requests, delivered together: the whole app is now themed around Gitea's own
|
|
brand green (previously it used Compose Material3's unthemed default — purple — since the app's
|
|
`ColorScheme` had never actually been given real values); every pagination footer's buttons
|
|
(previous page/next page/numbered page buttons) now render at one guaranteed-consistent height,
|
|
fixing a live-reported bug where they visibly varied; and each repository row now shows its
|
|
primary language and Gitea star count, with a tappable star toggle wired to the app's existing
|
|
(previously built but never connected to any screen) favorite/star action.
|
|
|
|
## Scope
|
|
|
|
- Included: `ui/theme/Color.kt` (new), `ui/theme/Theme.kt` (real `lightColorScheme`/`darkColorScheme`
|
|
values instead of Compose's defaults), new `ui/PaginationFooter.kt` (`SimplePaginationFooter`,
|
|
`PaginationButtonHeight`), `feature/history/HistoryScreen.kt`/`feature/notifications/NotificationsScreen.kt`/`feature/repositories/RepositoryListScreen.kt`
|
|
(their plain previous/next footers now call the shared composable),
|
|
`feature/workitems/WorkItemsScreen.kt` (both its plain fallback footer and its numbered footer's
|
|
buttons now set an explicit height), `domain/model/RepositoryModels.kt` (`RepositorySummary`
|
|
gains `language`/`starsCount`), `data/repositories/GiteaRepositoryBrowserApi.kt` (parses both
|
|
from the repository list response Gitea already returns), `feature/repositories/RepositoryListViewModel.kt`
|
|
(`RepositoryRowUiModel` gains the same two fields), `feature/repositories/RepositoryListScreen.kt`
|
|
(renders language + a `FavoriteStar` toggle per row, wires `onToggleFavorite`),
|
|
`MainActivity.kt` (`onToggleFavorite` wiring).
|
|
- Excluded: No change to any screen's actual functionality, navigation, or gesture behavior — this
|
|
task is deliberately colors/sizing/one-new-row-affordance only, per the human product owner's
|
|
explicit instruction ("디자인을 변경하면서 현재의 기능이 절대 변동되어서는 안돼... 조작감도
|
|
마찬가지야"). No attempt to determine a repository's *already*-starred state on initial load for
|
|
the ALL list (see Design notes) — that remains exactly the limitation TASK-018 already had, not
|
|
a new one introduced here. No per-language color coding (see Design notes).
|
|
|
|
## Design notes
|
|
|
|
- **Gitea's real brand green, not a guess**: verified against Gitea's own source
|
|
(`web_src/css/themes/theme-gitea-light.css`'s `--color-logo: #609926`) before picking a palette,
|
|
per this project's established convention. The Material3 `primary` role itself uses a slightly
|
|
deeper tone of that same green (`#3B6A1F`) rather than the exact logo value — white text on
|
|
`#609926` directly sits around a 3.4:1 contrast ratio, under WCAG's 4.5:1 threshold for
|
|
normal-size button labels; the rest of the app's now ~20 M3 color roles (secondary/tertiary,
|
|
each with a container + on-container pair, plus the full light/dark neutral scale) were hand-built
|
|
as a coherent tonal palette grown from that same hue family. `error`/`onError`/`errorContainer`/
|
|
`onErrorContainer` were deliberately left at Material3's own baseline red — nothing about this
|
|
request was about changing what an error (or a removed diff line) looks like.
|
|
- **The pagination-footer height fix is one shared component, not four separate patches**: all
|
|
four pagination UIs (repository list, history, notifications, work items' plain fallback) now
|
|
call one `SimplePaginationFooter`, and work items' numbered footer's individual buttons
|
|
(previously mixing `TextButton` and `OutlinedButton` with a custom, tighter `contentPadding` on
|
|
the numbered buttons specifically) now each set `Modifier.height(PaginationButtonHeight)`
|
|
explicitly. Pinning one explicit height on every button removes the possibility of disagreement
|
|
by construction, regardless of which specific Material3 default/padding interaction was actually
|
|
responsible for the reported drift — a more robust fix than chasing that exact mechanism down.
|
|
Each screen keeps its own string resources (so their text stays independently localizable); only
|
|
the visual composable is shared.
|
|
- **Language and star count needed no new network call**: Gitea's repository-list endpoint
|
|
(verified against `modules/structs/repo.go`'s `Repository` struct) already returns both
|
|
`language` and `stars_count` on the exact same call this app already makes to populate the list.
|
|
- **The favorite-star toggle reuses `toggleFavorite` exactly as TASK-018 already built and tested
|
|
it, unmodified** — this task only connects a UI trigger that never existed, it doesn't change the
|
|
underlying action. That action is already context-sensitive per list mode: on the ALL list it
|
|
stars (and `favoriteAction` only reflects *this session's* interaction, defaulting to
|
|
`Idle`/outlined even for a repository starred before this session — a known limitation carried
|
|
over unchanged, not newly introduced); on the FAVORITES list every row is inherently already
|
|
starred (that's why it's showing), so tapping there un-favorites and removes the row on success
|
|
rather than toggling the icon's own look. `FavoriteStar`'s rendering branches on which list mode
|
|
is current specifically to get this right: filled/primary-colored when actually confirmed
|
|
starred (or, on the FAVORITES list, whenever not mid-unstar), outlined otherwise, error-tinted on
|
|
a failed attempt (still tappable to retry), all sharing one `Row` clickable so it doesn't also
|
|
trigger the row's own "open this repository" tap.
|
|
- **No per-language color coding**: GitHub/Gitea's own "colored dot per language" convention
|
|
(visible in the reference screenshot) comes from a maintained language-color mapping (the
|
|
`linguist` project) this app has no copy of and no reliable way to source accurately; the
|
|
language name is shown as plain text instead, matching what was actually asked for ("어떤
|
|
언어인지... 보여줄래") without fabricating colors that might not match Gitea's own.
|
|
|
|
## Acceptance criteria
|
|
|
|
- [x] Every color visible across the app (tab indicators, buttons, selected states, links) now
|
|
reads as Gitea-brand green instead of Compose's unthemed default purple.
|
|
- [x] Dark mode has its own complete, coherent color scheme (not just the light one shown at a
|
|
lower opacity).
|
|
- [x] `error`/diff-removed-line coloring is visually unchanged (still red).
|
|
- [x] Every pagination footer's buttons (previous/next/numbered) render at the same height as each
|
|
other, confirmed by direct visual inspection on the live device (not just by code review).
|
|
- [x] Each repository row shows its Gitea-reported primary language (when non-blank) and star
|
|
count.
|
|
- [x] Tapping a row's star toggle stars it on the ALL list (or un-favorites and removes the row on
|
|
the FAVORITES list) via the exact same `toggleFavorite` action TASK-018 already built —
|
|
confirmed live on the device (star count/outline visibly responded to a tap).
|
|
- [x] Build, unit tests, and lint pass.
|
|
- [ ] Full live confirmation from the human product owner across all three changes together — the
|
|
device screenshots taken this session confirm the green theme, consistent footer heights,
|
|
and language/star display are all visibly correct, but the human product owner hasn't yet
|
|
given explicit sign-off in this exact session turn.
|
|
|
|
## Required checks
|
|
|
|
```text
|
|
./gradlew assembleDebug
|
|
./gradlew testDebugUnitTest
|
|
./gradlew lintDebug
|
|
```
|
|
|
|
## Evidence
|
|
|
|
- `ui/theme/Color.kt` (new): the full hand-built light/dark tonal palette, with the Gitea-source
|
|
citation for the seed green in its file-level doc comment.
|
|
- `ui/theme/Theme.kt`: `lightColorScheme(...)`/`darkColorScheme(...)` now pass every role explicitly
|
|
from `Color.kt` (previously called with no arguments at all, i.e. Compose's own baseline purple).
|
|
- `ui/PaginationFooter.kt` (new): `PaginationButtonHeight = 40.dp` (matching Material3's own
|
|
`ButtonDefaults.MinHeight`, made explicit rather than trusted implicitly) and
|
|
`SimplePaginationFooter`.
|
|
- `HistoryScreen.kt`/`NotificationsScreen.kt`/`RepositoryListScreen.kt`: each screen's `PageFooter`
|
|
(or, for repositories, its inline pagination `Row`) now delegates to `SimplePaginationFooter`,
|
|
passing its own existing string resources; now-unused `OutlinedButton` imports removed where
|
|
applicable.
|
|
- `WorkItemsScreen.kt`: plain fallback `PageFooter` also now uses `SimplePaginationFooter`;
|
|
`NumberedPageFooter`'s `TextButton`/`OutlinedButton` calls each gained
|
|
`Modifier.height(PaginationButtonHeight)`.
|
|
- `RepositoryModels.kt`: `RepositorySummary` gained `language: String? = null` and
|
|
`starsCount: Int = 0` (both defaulted so no existing call site needed to change).
|
|
- `GiteaRepositoryBrowserApi.kt`: `RepositoryDto` gained `language`/`stars_count` fields;
|
|
`mapRepository` populates both (blank language becomes `null`).
|
|
- `RepositoryListViewModel.kt`: `RepositoryRowUiModel` gained the same two fields; `toUiModel()`
|
|
updated.
|
|
- `RepositoryListScreen.kt`: new `FavoriteStar` composable (mode-aware rendering described in
|
|
Design notes); each row gained a `Row` showing language (or a blank `Spacer` when absent) and the
|
|
star toggle; `onToggleFavorite` threaded through `RepositoryListScreen`/`RepositoryContent`.
|
|
- `MainActivity.kt`: `onToggleFavorite = viewModel::toggleFavorite`.
|
|
- New test: `GiteaRepositoryBrowserApiTest.kt` (`language`/`stars_count` mapped correctly; a blank
|
|
`language` string becomes `null`).
|
|
- `./gradlew compileDebugKotlin compileDebugUnitTestKotlin`: BUILD SUCCESSFUL.
|
|
- `./gradlew testDebugUnitTest`: BUILD SUCCESSFUL, all unit tests passing (including the new one
|
|
above).
|
|
- `./gradlew assembleDebug lintDebug`: BUILD SUCCESSFUL, 0 lint errors.
|
|
- Live device: build installed over wireless `adb`. Screenshots taken directly on the device
|
|
confirm: the green theme applied consistently across the repository list, its tabs, and the
|
|
branch-detail file browser; the repository list's previous/next footer buttons render at matching
|
|
heights; each row shows its language (e.g. "C++", "C#") and star count with the outline/filled
|
|
star icon.
|
|
|
|
## Known limitations
|
|
|
|
- On the ALL repositories list, a repository already starred before the current app session still
|
|
shows an outlined (not filled) star until acted on in this session — `favoriteAction` only
|
|
tracks this session's own interaction, not the server's actual current starred state at load
|
|
time. This is carried over unchanged from TASK-018's original design, not a new gap.
|
|
- No per-language color coding (see Design notes) — language is shown as plain text only.
|
|
- Contrast for the hand-built color palette was reasoned through directly (informal luminance/
|
|
contrast-ratio estimation against WCAG's 4.5:1 threshold for the primary/onPrimary pairing
|
|
specifically) rather than verified with an automated contrast-checking tool across every one of
|
|
the ~20 color roles: the palette is a solid, deliberate design, but a full formal accessibility
|
|
audit of every role pairing hasn't been done.
|
|
- Full live human confirmation of this batch is still pending, even though device screenshots
|
|
taken directly this session already show all three pieces working correctly.
|
|
|
|
## Review findings
|
|
|
|
None yet — no Codex review pending (Codex retired, 2026-09-29).
|