TASK-040: collapse repository-list header buttons into an overflow menu

Replace the three always-visible 설정/알림/로그아웃 OutlinedButtons on the
repository list's top bar with a single hamburger-style overflow menu
("☰" IconButton + DropdownMenu). Same three callbacks, presentation-only
change, no icon library (plain Unicode glyph, matching this app's
established convention).

Build/test/lint green. Not yet live-verified on device — wireless
debugging was intentionally paused for this round per request.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
최민영 2026-08-29 19:00:13 +09:00
parent a26e86f650
commit 2b9a6e091e
3 changed files with 144 additions and 7 deletions

View File

@ -1,6 +1,7 @@
package com.ubisam.ubgitea.feature.repositories package com.ubisam.ubgitea.feature.repositories
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@ -18,9 +19,12 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChip
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.PullToRefreshBox
@ -30,6 +34,10 @@ import androidx.compose.material3.Tab
import androidx.compose.material3.TabRow import androidx.compose.material3.TabRow
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@ -237,13 +245,7 @@ private fun RepositoryContent(
Text(stringResource(R.string.repositories_account, state.accountName)) Text(stringResource(R.string.repositories_account, state.accountName))
} }
Spacer(Modifier.weight(1f)) Spacer(Modifier.weight(1f))
OutlinedButton(onClick = onViewSettings) { Text(stringResource(R.string.repositories_settings)) } OverflowMenuButton(onViewSettings, onViewNotifications, onLogout)
OutlinedButton(onClick = onViewNotifications, modifier = Modifier.padding(start = 8.dp)) {
Text(stringResource(R.string.repositories_notifications))
}
OutlinedButton(onClick = onLogout, modifier = Modifier.padding(start = 8.dp)) {
Text(stringResource(R.string.repositories_logout))
}
} }
} }
item { ModeTabs(state.mode, onShowAllRepositories, onShowFavorites) } item { ModeTabs(state.mode, onShowAllRepositories, onShowFavorites) }
@ -379,6 +381,35 @@ private fun OrganizationFilterRow(
} }
} }
// A single overflow ("hamburger") menu replaces what used to be three separate always-visible
// buttons (설정/알림/로그아웃) on the repository list's top bar — those three buttons crowded the
// header next to the app title. This app has no icon library (see CLAUDE.md's established
// convention), so the trigger is the plain Unicode "☰" glyph, matching how ★/☆ are already used
// elsewhere for favorites rather than a drawable icon.
@Composable
private fun OverflowMenuButton(onViewSettings: () -> Unit, onViewNotifications: () -> Unit, onLogout: () -> Unit) {
var expanded by remember { mutableStateOf(false) }
Box {
IconButton(onClick = { expanded = true }) {
Text("☰", style = MaterialTheme.typography.titleLarge)
}
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
DropdownMenuItem(
text = { Text(stringResource(R.string.repositories_settings)) },
onClick = { expanded = false; onViewSettings() },
)
DropdownMenuItem(
text = { Text(stringResource(R.string.repositories_notifications)) },
onClick = { expanded = false; onViewNotifications() },
)
DropdownMenuItem(
text = { Text(stringResource(R.string.repositories_logout)) },
onClick = { expanded = false; onLogout() },
)
}
}
}
@Composable @Composable
private fun ModeTabs(mode: RepositoryListMode, onShowAllRepositories: () -> Unit, onShowFavorites: () -> Unit) { private fun ModeTabs(mode: RepositoryListMode, onShowAllRepositories: () -> Unit, onShowFavorites: () -> Unit) {
TabRow(selectedTabIndex = if (mode == RepositoryListMode.FAVORITES) 1 else 0) { TabRow(selectedTabIndex = if (mode == RepositoryListMode.FAVORITES) 1 else 0) {

View File

@ -749,3 +749,32 @@ This is the append-only implementation and handoff record shared by Codex and Cl
- Next recommended task: continue into work-item/PR detail views with real content and the text/image/CSV/PDF - Next recommended task: continue into work-item/PR detail views with real content and the text/image/CSV/PDF
file viewers, and extend the dark-mode pass to notifications/settings/work-items. file viewers, and extend the dark-mode pass to notifications/settings/work-items.
- Next owner: Claude, continuing per the standing direction. - Next owner: Claude, continuing per the standing direction.
## 2026-08-29 (continued) — TASK-040: repository-list header overflow menu (code-only, no device install)
- Agent and role: Claude, direct continuation of the same live session. The human product owner asked
to stop growing the repository list's top bar with more always-visible buttons and instead collapse
설정/알림/로그아웃 behind a hamburger-style overflow menu, and explicitly asked for code only this
round with wireless debugging paused ("잠시 무선 디버깅 하지말고 코드만 수정해줘").
- Commit/diff: on `claude/task-015-notifications`; `RepositoryListScreen.kt`'s header now shows one
"☰" `IconButton` opening a `DropdownMenu` (설정/알림/로그아웃) instead of three separate
`OutlinedButton`s; `tasks/040-repository-list-header-overflow-menu.md`.
- How it was implemented: new private `OverflowMenuButton` composable takes the exact same three
callbacks (`onViewSettings`/`onViewNotifications`/`onLogout`) the header already received —
presentation-only change, no navigation/ViewModel/use-case code touched. Uses the plain "☰" Unicode
glyph rather than a drawable icon, consistent with this app's established no-icon-library
convention (the same convention already used for ★/☆ elsewhere).
- Files changed: `feature/repositories/RepositoryListScreen.kt`, `tasks/040-repository-list-header-overflow-menu.md`.
- Checks and results: `./gradlew compileDebugKotlin testDebugUnitTest assembleDebug lintDebug` BUILD
SUCCESSFUL, all unit tests passing unmodified, 0 lint errors.
- Live verification: intentionally not done this round — wireless debugging was paused at the human
product owner's request. Code is ready to install and screenshot-verify (light and dark mode) next
session.
- Review findings and resolutions: None from a separate review pass.
- Known limitations: not yet live-confirmed on-device (see task file).
- Next recommended task: once wireless debugging resumes, install and screenshot-verify the new
overflow menu (button sizing/position, dropdown legibility, correct navigation for each item, both
light and dark mode), then continue the broader design-review pass (work-item/PR detail views, file
viewers) from where TASK-039 left off.
- Next owner: Claude, continuing per the standing direction once wireless debugging resumes or further
code-only work is requested.

View File

@ -0,0 +1,77 @@
# TASK-040: Replace repository-list header buttons with a single overflow menu
Status: implemented; build/test/lint pass; not yet live-verified (wireless debugging paused by the
human product owner for this task — code prepared and ready for the next live session)
Owner: Claude
Reviewer: Codex
## Outcome
The human product owner asked to stop adding more always-visible buttons to the repository list's
top bar and instead collapse 설정/알림/로그아웃 (Settings/Notifications/Logout) behind a single
hamburger-style overflow menu button: "UI에 버튼 이런거 만들지말고 햄버거 버튼인가? 그런거 해서 거기서
눌러서 설정창, 로그아웃, 알림 이런거 확인 할 수 있게 해줘."
`RepositoryListScreen.kt`'s main header now shows one button (a "☰" glyph) instead of three
`OutlinedButton`s. Tapping it opens a `DropdownMenu` with three items — 설정, 알림, 로그아웃 — each
calling the same existing callback (`onViewSettings`/`onViewNotifications`/`onLogout`) the three
buttons already called; no navigation or ViewModel wiring changed, only how the trigger is presented.
## Scope
- Included: `feature/repositories/RepositoryListScreen.kt` — new private `OverflowMenuButton`
composable, `RepositoryContent`'s header `Row` now calls it instead of three `OutlinedButton`s.
- Excluded: the references (repository-detail) screen's lone 로그아웃 button was left as-is — it's a
single button in a different context (viewing one repository, not the account-level menu group),
not the three-button cluster the human product owner was referring to. No change to any
ViewModel/use-case/navigation code — this is a presentation-only change reusing the exact same
three callbacks.
## Design notes
- **Unicode glyph, not an icon library**: this app has never depended on
`androidx.compose.material.icons` (see CLAUDE.md's established convention) — the trigger button
uses the plain "☰" character the same way ★/☆ are already used elsewhere for favorites, not a
drawable/vector icon asset.
- **Same three callbacks, just regrouped**: `OverflowMenuButton` takes the exact same
`onViewSettings`/`onViewNotifications`/`onLogout` lambdas `RepositoryContent` already received —
this is purely how they're triggered from the UI, not a change to what they do.
## Acceptance criteria
- [x] The repository list's top bar shows one overflow-menu button instead of three separate
buttons.
- [x] Tapping it opens a dropdown with 설정/알림/로그아웃; each item navigates exactly like its old
button did.
- [x] Build, unit tests, and lint pass.
- [ ] Live-confirmed on the human product owner's device — pending, since wireless debugging was
intentionally paused for this task at the human product owner's request ("잠시 무선 디버깅
하지말고 코드만 수정해줘"). Code is ready to install and verify next session.
## Required checks
```text
./gradlew compileDebugKotlin testDebugUnitTest assembleDebug lintDebug
```
## Evidence
- `feature/repositories/RepositoryListScreen.kt`: new private `OverflowMenuButton(onViewSettings,
onViewNotifications, onLogout)` (an `IconButton` showing "☰" plus a `DropdownMenu` with three
`DropdownMenuItem`s); `RepositoryContent`'s header now calls it in place of the three
`OutlinedButton`s it used to render directly.
- `./gradlew compileDebugKotlin testDebugUnitTest assembleDebug lintDebug`: BUILD SUCCESSFUL, all
unit tests passing unmodified (no test referenced the old buttons' text/structure), 0 lint errors.
- No `androidTest` UI-test suite exists in this project to update — only JVM unit tests, which don't
touch Compose UI structure.
## Known limitations
- Not yet live-verified on-device (see Acceptance criteria) — the human product owner asked for code
only this round, with wireless debugging paused. Needs a screenshot pass (light and dark mode) once
debugging resumes: confirm the "☰" button renders at a reasonable size/position next to the title,
and that the dropdown's three items are legible and correctly navigate.
## Review findings
None yet — pending Codex/human review.