Replaces Compose Material3's unthemed default (purple) with a real color scheme built from Gitea's own brand green, verified against Gitea's source (--color-logo: #609926). Fixes a live-reported bug where pagination footer button heights visibly varied by pinning one explicit height on every button across all four screens' footers, and by sharing one SimplePaginationFooter for the plain previous/next case. Each repository row now shows its Gitea-reported primary language and a tappable star toggle wired to the existing toggleFavorite action. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
11 KiB
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(reallightColorScheme/darkColorSchemevalues instead of Compose's defaults), newui/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(RepositorySummarygainslanguage/starsCount),data/repositories/GiteaRepositoryBrowserApi.kt(parses both from the repository list response Gitea already returns),feature/repositories/RepositoryListViewModel.kt(RepositoryRowUiModelgains the same two fields),feature/repositories/RepositoryListScreen.kt(renders language + aFavoriteStartoggle per row, wiresonToggleFavorite),MainActivity.kt(onToggleFavoritewiring). - 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 Material3primaryrole itself uses a slightly deeper tone of that same green (#3B6A1F) rather than the exact logo value — white text on#609926directly 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/onErrorContainerwere 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 mixingTextButtonandOutlinedButtonwith a custom, tightercontentPaddingon the numbered buttons specifically) now each setModifier.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'sRepositorystruct) already returns bothlanguageandstars_counton the exact same call this app already makes to populate the list. - The favorite-star toggle reuses
toggleFavoriteexactly 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 (andfavoriteActiononly reflects this session's interaction, defaulting toIdle/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 oneRowclickable 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
linguistproject) 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
- 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.
- Dark mode has its own complete, coherent color scheme (not just the light one shown at a lower opacity).
error/diff-removed-line coloring is visually unchanged (still red).- 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).
- Each repository row shows its Gitea-reported primary language (when non-blank) and star count.
- 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
toggleFavoriteaction TASK-018 already built — confirmed live on the device (star count/outline visibly responded to a tap). - 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
./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 fromColor.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 ownButtonDefaults.MinHeight, made explicit rather than trusted implicitly) andSimplePaginationFooter.HistoryScreen.kt/NotificationsScreen.kt/RepositoryListScreen.kt: each screen'sPageFooter(or, for repositories, its inline paginationRow) now delegates toSimplePaginationFooter, passing its own existing string resources; now-unusedOutlinedButtonimports removed where applicable.WorkItemsScreen.kt: plain fallbackPageFooteralso now usesSimplePaginationFooter;NumberedPageFooter'sTextButton/OutlinedButtoncalls each gainedModifier.height(PaginationButtonHeight).RepositoryModels.kt:RepositorySummarygainedlanguage: String? = nullandstarsCount: Int = 0(both defaulted so no existing call site needed to change).GiteaRepositoryBrowserApi.kt:RepositoryDtogainedlanguage/stars_countfields;mapRepositorypopulates both (blank language becomesnull).RepositoryListViewModel.kt:RepositoryRowUiModelgained the same two fields;toUiModel()updated.RepositoryListScreen.kt: newFavoriteStarcomposable (mode-aware rendering described in Design notes); each row gained aRowshowing language (or a blankSpacerwhen absent) and the star toggle;onToggleFavoritethreaded throughRepositoryListScreen/RepositoryContent.MainActivity.kt:onToggleFavorite = viewModel::toggleFavorite.- New test:
GiteaRepositoryBrowserApiTest.kt(language/stars_countmapped correctly; a blanklanguagestring becomesnull). ./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 —
favoriteActiononly 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 — pending Codex/human review.