Ubisam-MobileGit/tasks/042-workitem-status-badges.md
choiminyeong f6ac20c8ed TASK-063: task records say what is actually open
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>
2026-09-29 20:25:49 +09:00

105 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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