Closes the known limitation from the previous commit: NotificationsScreen had the identical plain-text state-label gap, in a separate screen/enum (NotificationSubjectState, which also has an UNKNOWN case). Adds its own StatusBadge composable with the same color roles, mapping UNKNOWN to the neutral surfaceVariant treatment VisibilityBadge already uses for private. Live-verified on-device: notifications 전체 list shows all three real colors side by side (닫힘/병합됨/열림). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
105 lines
6.4 KiB
Markdown
105 lines
6.4 KiB
Markdown
# TASK-042: Colored status badges for issue/PR state (열림/닫힘/병합됨)
|
||
|
||
Status: implemented; all required checks pass; live-confirmed on the human product owner's device
|
||
Owner: Claude
|
||
Reviewer: Codex
|
||
|
||
## Outcome
|
||
|
||
Design-review follow-up (continuing the "앱의 아이콘부터 해서 전체적으로 확인해보고 부족한 부분 고쳐줘"
|
||
pass from TASK-039). While verifying that issue/PR body text renders correctly for real content
|
||
(it does — confirmed against a real issue with a multi-paragraph body and an embedded code block),
|
||
noticed the 열림/닫힘/병합됨 state label next to each issue/PR — in both the list row and the detail
|
||
header — rendered as a plain, uncolored `bodySmall` line, visually no more prominent than the
|
||
`#12` issue number sitting right next to it. Gitea's own web UI (and GitHub's, which established the
|
||
convention) colors this label so it reads at a glance while scanning a list. Replaced the plain text
|
||
with a compact colored badge, reusing the `VisibilityBadge` pattern TASK-039 already established for
|
||
공개/비공개 on the repository list.
|
||
|
||
## Scope
|
||
|
||
- Included: `feature/workitems/WorkItemsScreen.kt` — new private `StatusBadge` composable (two
|
||
overloads, one per state enum, sharing one color-agnostic rendering implementation) replacing the
|
||
four plain-`Text` state-label call sites: `IssueRow`, `PullRequestRow`, `IssueDetailView`,
|
||
`PullRequestDetailView`.
|
||
- Excluded: `NotificationsScreen.kt`'s own PR/이슈 state labels (a separate screen/composable, out of
|
||
scope for this pass — noted below as a known limitation, not silently left inconsistent).
|
||
`ReviewState` labels (승인/변경 요청/etc. on `ReviewRow`) — these are a different kind of status
|
||
with no obvious two/three-color GitHub/Gitea convention to borrow, left as plain text.
|
||
|
||
## Design notes
|
||
|
||
- **Reused existing theme roles instead of introducing new colors.** OPEN gets
|
||
`primaryContainer`/`onPrimaryContainer` — the same green `VisibilityBadge` already uses for a
|
||
public repository's affirmative state. CLOSED gets `errorContainer`/`onErrorContainer` — the
|
||
baseline Material3 red `Theme.kt` deliberately left untouched for exactly this kind of
|
||
closed/removed state. MERGED — a third state GitHub/Gitea conventionally color purple, which this
|
||
app's green/teal-accented theme has no role for — gets `tertiaryContainer`/`onTertiaryContainer`
|
||
(teal) rather than a one-off hardcoded color with no theme backing (and no dark-mode variant of its
|
||
own to get wrong).
|
||
- **One rendering composable, two small color-mapping overloads.** `IssueState` and `PullRequestState`
|
||
are different enums (`PullRequestState` has the extra MERGED case), so a single `when` couldn't
|
||
cover both — instead each enum gets its own thin `StatusBadge(state, modifier)` overload that maps
|
||
to a container/content color pair and delegates to the same private `StatusBadge(label, container,
|
||
content, modifier)` for the actual `Surface` + `Text` rendering, keeping the visual treatment
|
||
(rounded 4dp corner, `labelSmall`, 6dp/2dp padding) defined in exactly one place.
|
||
|
||
## Acceptance criteria
|
||
|
||
- [x] Issue list rows show a colored badge (not plain text) for 열림/닫힘.
|
||
- [x] PR list rows show a colored badge for 열림/닫힘/병합됨.
|
||
- [x] Issue detail header shows the same colored badge as its list row.
|
||
- [x] PR detail header shows the same colored badge as its list row.
|
||
- [x] Colors are pulled from the existing Material3 theme (no new hardcoded colors), so dark mode is
|
||
handled automatically.
|
||
- [x] Build, unit tests, and lint pass.
|
||
- [x] Live-confirmed on the human product owner's device: PR list showing 병합됨 (teal) ×2 and 열림
|
||
(green) ×1 side by side; PR detail header showing the same teal 병합됨 badge; both re-confirmed
|
||
unchanged under forced dark mode.
|
||
|
||
## Required checks
|
||
|
||
```text
|
||
./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug
|
||
```
|
||
|
||
## Evidence
|
||
|
||
- `feature/workitems/WorkItemsScreen.kt`: `StatusBadge` composable (two state-typed overloads +
|
||
one shared rendering implementation) added; `IssueRow`, `PullRequestRow`, `IssueDetailView`,
|
||
`PullRequestDetailView` each call it in place of a plain `Text(stringResource(state.labelResource))`.
|
||
- `./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug`:
|
||
BUILD SUCCESSFUL, all unit tests passing (no test changes needed — this is a pure presentation
|
||
change with no new branching logic to cover beyond what the enum `when`s already exhaustively
|
||
check at compile time), 0 lint errors.
|
||
- Live device: installed over wireless `adb`. Notifications → PostActivated 관련 추가 필요 이슈 detail:
|
||
confirmed the issue body (multi-paragraph Korean text plus an indented C# code block) renders
|
||
correctly end to end — this was the original investigation trigger, and it surfaced no bug on its
|
||
own. RobotAutomationDevelopment-Dept/OC5-PilotLine-RectangleTypeWelder PR tab: #6/#5 both show a
|
||
teal "병합됨" badge, #4 shows a green "열림" badge (screenshot); opened #6's detail view and confirmed
|
||
the same teal badge appears in the header (screenshot). Forced dark mode
|
||
(`adb shell cmd uimode night yes`) and reconfirmed the same PR list — both badge colors keep good
|
||
contrast against the dark surface (screenshot) — then restored `night no`.
|
||
|
||
## Known limitations
|
||
|
||
None outstanding for this task — see the follow-up below, which closed the one gap originally
|
||
recorded here.
|
||
|
||
## Follow-up (same session): NotificationsScreen
|
||
|
||
`NotificationsScreen.kt`'s own PR/이슈 상태 column had the identical gap (plain-text state label) in a
|
||
separate screen this task didn't originally touch. Added a second, independent `StatusBadge`
|
||
composable there (for `NotificationSubjectState`, a different enum with its own `UNKNOWN` case —
|
||
mapped to the neutral `surfaceVariant`/`onSurfaceVariant` `VisibilityBadge` already uses for
|
||
"private", since an unrecognized state isn't one to visually emphasize either direction) rather than
|
||
sharing code across the two feature packages. Build/test/lint re-run clean; live-verified on-device:
|
||
the notifications 전체 list now shows all three real colors side by side — red "닫힘", teal "병합됨",
|
||
green "열림" — which also closes the "never visually confirmed the red CLOSED badge live" gap
|
||
originally recorded here, since these are the same `errorContainer`/`onErrorContainer` roles used by
|
||
the work-items screens' badge.
|
||
|
||
## Review findings
|
||
|
||
None yet — pending Codex/human review.
|