TASK-028 follow-up: visible feedback for an out-of-range page-jump value

The Issues/PR numbered-pagination page-jump field silently clamped any
typed number to [1, totalPages] only on submit -- typing '999' would
quietly land on the last page with no explanation. The field now shows
isError/supportingText whenever the currently-typed value is out of
range, making the clamp visible before the tap. Submitting still
clamps exactly as before; this only adds visible feedback.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
최민영 2026-08-29 17:41:51 +09:00
parent 683305e6c8
commit 75f887c497
4 changed files with 41 additions and 2 deletions

View File

@ -349,12 +349,24 @@ private fun NumberedPageFooter(page: Int, totalPages: Int, onPrevious: () -> Uni
fun submit() {
input.toIntOrNull()?.let { onGoToPage(it.coerceIn(1, totalPages)) }
}
// Submitting still clamps regardless (coerceIn above), so an out-of-range value never
// requests a page that doesn't exist -- this only makes that clamping visible before
// the tap, instead of the field silently accepting e.g. "999" and quietly landing on
// the last page with no explanation.
val typedPage = input.toIntOrNull()
val isOutOfRange = typedPage != null && typedPage !in 1..totalPages
Text("[", style = MaterialTheme.typography.bodyLarge)
OutlinedTextField(
value = input,
onValueChange = { input = it.filter(Char::isDigit).take(6) },
modifier = Modifier.width(72.dp),
singleLine = true,
isError = isOutOfRange,
supportingText = if (isOutOfRange) {
{ Text(stringResource(R.string.workitems_page_jump_out_of_range, totalPages)) }
} else {
null
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Go),
keyboardActions = KeyboardActions(onGo = { submit() }),
)

View File

@ -9,6 +9,7 @@
<string name="workitems_page_number">%1$d페이지</string>
<string name="workitems_page_jump_suffix">/ %1$d ]</string>
<string name="workitems_page_jump_go">이동</string>
<string name="workitems_page_jump_out_of_range">1~%1$d 사이의 페이지를 입력하세요.</string>
<string name="workitems_by_author">%1$s · 댓글 %2$d개</string>
<string name="workitems_author">작성자: %1$s</string>
<string name="workitems_author_unavailable">(알 수 없는 사용자)</string>

View File

@ -659,3 +659,16 @@ This is the append-only implementation and handoff record shared by Codex and Cl
- Known limitations: still session-scoped (re-fetches on a fresh session, same as every other cached list in this app); doesn't reflect a starred-set change made elsewhere (Gitea web, another device) until the next pull-to-refresh or re-login.
- Next recommended task: this closes a real, previously-documented gap rather than adding new surface area. Remaining work across this whole session is now mostly live-confirmation of already-built features (TASK-027 through TASK-036) that haven't been directly exercised by the human product owner yet.
- Next owner: Claude, continuing per the standing direction.
## 2026-08-29 (continued) — TASK-028 follow-up: visible feedback for an out-of-range page-jump
- Agent and role: Claude, direct continuation of the same live session — "계속 이어서 개발해줘 멈추지말고" (keep developing, don't stop). Picked up a small, contained item TASK-028 itself had documented as a known limitation.
- Commit/diff: on `claude/task-015-notifications`; `feature/workitems/WorkItemsScreen.kt`, `strings_workitems.xml`, `tasks/028-issues-prs-numbered-pagination.md`.
- Fix implemented: the Issues/PR numbered-pagination page-jump field previously accepted any typed number and silently clamped it to `[1, totalPages]` only on submit (typing "999" would quietly land on the last page with no explanation). It now sets `isError`/`supportingText` on the field whenever the currently-typed value falls outside that range, making the clamp visible before the tap instead of after.
- How it was implemented: pure Compose-only change (`isOutOfRange` derived from the field's own current text, compared against `totalPages`) — submitting still clamps exactly as before, this only adds visible feedback. No test coverage added since this file's pagination UI has never had dedicated tests (matches this codebase's established pattern of not unit-testing pure Compose screens).
- Files changed: `WorkItemsScreen.kt`, `strings_workitems.xml`, `tasks/028-issues-prs-numbered-pagination.md`.
- Checks and results: `./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug` BUILD SUCCESSFUL, all unit tests passing, 0 lint errors. Installed on the human product owner's device over wireless `adb`.
- Review findings and resolutions: None from a separate review pass.
- Known limitations: same as the rest of TASK-028 — not yet seen live against a repository with enough real issues/PRs to populate the numbered UI, since no such repository was found this session.
- Next recommended task: this was a small, contained polish item. Larger remaining candidates (e.g. a reactive 401-retry fallback at the network layer, per-repository notification settings) were considered but judged too large/risky for unrequested autonomous continuation without a dedicated task scoping pass — flagging them for the human product owner's direction rather than proceeding further unrequested into security-adjacent or larger-surface-area territory.
- Next owner: Claude, continuing per the standing direction once the human product owner responds, or awaiting live confirmation of everything already built this session.

View File

@ -107,6 +107,10 @@ previous/next, since Gitea's endpoints for those don't report a total count —
requests, so the numbered-pagination UI itself was never actually populated with real data this
session (see Known limitations) — confirmed instead that the screen doesn't crash and correctly
shows the existing empty state on all four.
- Same-session follow-up: `WorkItemsScreen.kt`'s page-jump field gained `isError`/`supportingText`
for an out-of-range typed value; `strings_workitems.xml` gained `workitems_page_jump_out_of_range`.
`./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug`
BUILD SUCCESSFUL; installed on-device, no crash.
## Known limitations
@ -115,9 +119,18 @@ previous/next, since Gitea's endpoints for those don't report a total count —
requests. The header-parsing, total-page-count, and jump-to-page logic are covered by unit tests
instead, but the actual rendered page-button row and jump field haven't been seen with real
multi-page data yet.
- The page-jump text field accepts any positive integer typed, including one exceeding
- ~~The page-jump text field accepts any positive integer typed, including one exceeding
`totalPages` — it's clamped before being submitted (`coerceIn(1, totalPages)`), so this can't
request an out-of-range page, but the field itself doesn't visually reject the keystroke.
request an out-of-range page, but the field itself doesn't visually reject the keystroke.~~
**Addressed in a same-session follow-up**: the field now sets `isError`/`supportingText` (a new
string, `workitems_page_jump_out_of_range`) whenever the currently-typed number falls outside
`[1, totalPages]`, so the clamp-on-submit behavior is now visible before the tap instead of a
silent "999 quietly becomes the last page." Submitting still clamps regardless — this only adds
visible feedback, it doesn't change what actually happens on submit. Like the rest of this
feature, this specific change hasn't been seen live against real multi-page data either (same
blocker as the item above), but it's a small, self-contained Compose-only change consistent with
this file's existing, unit-tested `coerceIn` behavior — build/lint pass, installed on-device with
no crash.
## Review findings