fix(android): miniplayer content sat at the top of its bar, not centred
android / Build + lint + test (push) Successful in 4m9s
android / Build + lint + test (push) Successful in 4m9s
Reported with a screenshot: the bar drew at full height but the cover, title and transport row hugged its top edge, leaving an empty strip of surface above the gesture area. The Surface is a fixed 80dp. Inside it a plain Column stacked a 4dp progress fill and then MiniRow at its INTRINSIC height — 48dp, set by the cover and the icon buttons. A Column stacks from the top and nothing claimed the remainder, so 80 - 4 - 48 = 28dp collected at the bottom. Measured off the screenshot rather than eyeballed, and the bands agree exactly: progress fill 14px (4dp at 3.5x), surface 280px (80dp), cover 167px (48dp), empty below 99px (28.3dp). That the arithmetic lands on the measurement is what makes this the whole cause rather than one contributor. MiniRow was already centring its content correctly — inside a box that was only ever 48dp tall. Giving it weight(1f) lets it take what the progress fill leaves, so it measures 76dp and centres 48dp of content: 14dp above and below. The fill stays pinned to the top edge, which is where a progress indicator belongs. Not the same bug as issue #2681. That was a dead strip ABOVE the miniplayer from an unclaimed navigation-bar inset, fixed in v2026.08.18. This is inside the bar, pure layout, no insets — the surface already stopped correctly above the gesture area. CI cannot see this one. There are no Compose UI tests in the repo; the Android lane is ktlint, detekt and JVM unit tests, and a layout bug needs an instrumented test to catch. Compilation and lint are all this commit gets from CI — the visual check is on a device, and the APK only builds on a tagged release. Scribe issue #3826. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SQ31KQpYbStyK5y58UmPLH
This commit is contained in:
@@ -109,8 +109,11 @@ private fun MiniCover(coverUrl: String, contentDescription: String) {
|
||||
* NowPlayingScreen via [onExpandClick].
|
||||
*
|
||||
* Layout (Column):
|
||||
* - Slim seek slider at the top (4dp track)
|
||||
* - Row: cover | title/artist column | like | prev | play/pause | next
|
||||
* - Slim seek slider pinned at the top (4dp track)
|
||||
* - Row: cover | title/artist column | like | prev | play/pause | next.
|
||||
* Weighted so it fills the rest of the fixed-height bar and centres its
|
||||
* own content; otherwise the row keeps its intrinsic 48dp and the
|
||||
* leftover height collects at the bottom as dead surface.
|
||||
*
|
||||
* No kebab on the mini bar (operator 2026-06-01): the full kebab
|
||||
* surface lives on NowPlayingScreen, and dropping it from the mini
|
||||
@@ -164,6 +167,12 @@ fun MiniPlayer(
|
||||
durationMs = state.durationMs,
|
||||
)
|
||||
MiniRow(
|
||||
// Take whatever the progress fill leaves. Without this the
|
||||
// Column stacks 4dp + the row's intrinsic 48dp from the top
|
||||
// and the remaining 28dp of an 80dp bar sits empty
|
||||
// underneath — the content looked top-aligned rather than
|
||||
// centred, with a dead strip above the gesture bar.
|
||||
modifier = Modifier.weight(1f),
|
||||
track = track,
|
||||
isPlaying = state.isPlaying,
|
||||
isUpnpLoading = state.isUpnpLoading,
|
||||
@@ -205,6 +214,7 @@ private fun MiniProgressFill(positionMs: Long, durationMs: Long) {
|
||||
@Composable
|
||||
@Suppress("LongParameterList")
|
||||
private fun MiniRow(
|
||||
modifier: Modifier,
|
||||
track: TrackRef,
|
||||
isPlaying: Boolean,
|
||||
isUpnpLoading: Boolean,
|
||||
@@ -216,7 +226,7 @@ private fun MiniRow(
|
||||
onToggleLike: () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
|
||||
Reference in New Issue
Block a user