diff --git a/android/app/src/main/java/com/fabledsword/minstrel/player/ui/NowPlayingScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/player/ui/NowPlayingScreen.kt index 8002842b..b3149c03 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/player/ui/NowPlayingScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/player/ui/NowPlayingScreen.kt @@ -88,6 +88,8 @@ private const val PLAY_PAUSE_ICON_DP = 56 private const val POP_GRACE_MS = 500L private val SCRUB_TRACK_HEIGHT_DP = 4.dp private val SCRUB_TRACK_CORNER_DP = 2.dp +private val SCRUB_THUMB_WIDTH_DP = 4.dp +private val SCRUB_THUMB_HEIGHT_DP = 18.dp // Vertical drag-down threshold (in pixels) past which the gesture // pops the player. Matches Flutter's 80px threshold in spirit; @@ -478,15 +480,22 @@ private fun ScrubberRow(positionMs: Long, durationMs: Long, onSeek: (Long) -> Un modifier = Modifier.fillMaxWidth(), colors = sliderColors, interactionSource = interactionSource, - // Plain filled circle to match the web client's `` thumb — flat, no state-layer - // ring, no border. M3's SliderDefaults.Thumb paints a state - // layer halo on press; we drop it for visual parity. Slider's - // 48dp hit slop still applies, so tapability is unchanged. + // Thin vertical pill (4dp wide × 18dp tall, fully rounded). + // A small circle on a thin horizontal bar reads as visually + // off-center even when geometrically aligned — the eye + // expects the bar to bisect the thumb but a 14dp circle's + // mass extends above and below in equal amounts that the + // brain perceives as offset. A vertical pill the same width + // as the track removes the ambiguity: the bar passes through + // the pill's horizontal axis cleanly. Also matches M3's + // expressive-slider handle direction. State-layer halo is + // still dropped for visual parity with the web scrubber. + // Slider's 48dp hit slop still applies, so tapability is + // unchanged. thumb = { Box( modifier = Modifier - .size(14.dp) + .size(width = SCRUB_THUMB_WIDTH_DP, height = SCRUB_THUMB_HEIGHT_DP) .clip(CircleShape) .background(accent), ) @@ -513,12 +522,11 @@ private fun ScrubberRow(positionMs: Long, durationMs: Long, onSeek: (Long) -> Un /** * Custom 4dp rounded scrubber track. M3's default Track is 16dp tall - * and reads as a heavy pill rather than a measurement line; making - * the thumb visibly taller than the track (14dp thumb on a 4dp bar) - * restores the "handle on a string" cue your eye reads as "tool, - * draggable." Also drops M3's stop indicator dot, which the web - * scrubber doesn't have. Extracted so [ScrubberRow] stays under - * detekt's LongMethod ceiling. + * and reads as a heavy pill rather than a measurement line; the + * pill-thumb-on-thin-track pairing restores the "handle on a string" + * cue your eye reads as "tool, draggable." Also drops M3's stop + * indicator dot, which the web scrubber doesn't have. Extracted so + * [ScrubberRow] stays under detekt's LongMethod ceiling. */ @Composable private fun ScrubTrack(fraction: Float, accent: Color) {