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>
105 lines
6.5 KiB
Markdown
105 lines
6.5 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 — no Codex review pending (Codex retired, 2026-09-29).
|