home: lyrics beside the map get a button back to the player, and the dock button opens and closes the panel on its own side

This commit is contained in:
Seb3thehacker committed 2026-10-25 21:34:39 -07:00
1 parent 08ac6fe117
commit c616f0203a
4 files changed
+31 -9

No files matched your search

@@ -233,8 +233,8 @@ private fun DockedPlayer(now: NowPlaying, modifier: Modifier) {
/**
* Lyrics alone beside the map, big enough to read at a glance. The header is slim, since the
* player goes back to the nav bar meanwhile and names the song there; its dock button swaps these
* back out for the controls.
* player goes back to the nav bar meanwhile and names the song there. Its note button swaps the
* lyrics back for the player; the X closes the panel.
*/
@Composable
private fun SideLyrics(now: NowPlaying, modifier: Modifier) {
@@ -256,6 +256,9 @@ private fun SideLyrics(now: NowPlaying, modifier: Modifier) {
color = scheme.onSurfaceVariant,
maxLines = 1, overflow = TextOverflow.Ellipsis,
)
// The way back to the player, as the player's own Lyrics button is the way here.
GsIconButton(MediaIcons.MusicNote, "Show the player", navigator::showSidePlayer, size = 36.dp, iconSize = 20.dp)
Spacer(Modifier.size(6.dp))
GsIconButton(Icons.Filled.Close, "Hide lyrics", navigator::closeSidePanel, size = 36.dp, iconSize = 20.dp)
}
LyricsPanel(now, Modifier.weight(1f).fillMaxWidth(), lineStyle = MaterialTheme.typography.headlineSmall)
@@ -528,7 +528,7 @@ private fun nowPlayingLabel(title: String, artist: String): String =
* The player in the nav bar, on every screen. Art and title open the full media screen;
* play/pause and skip work right here. The dock button moves the player into the column beside
* the map on Home (see [CarHome]), and the pill steps aside there while it's docked - unless the
* column is showing lyrics instead, when the pill stays and its dock button swaps them back.
* column is showing lyrics instead, when the pill stays and its dock button closes them.
*/
@Composable
private fun NavNowPlaying(navigator: CarNavigator, selected: Boolean, modifier: Modifier = Modifier) {
@@ -620,8 +620,18 @@ private fun NavNowPlaying(navigator: CarNavigator, selected: Boolean, modifier:
enabled = now.canDo(PlaybackState.ACTION_SKIP_TO_NEXT), size = 36.dp, iconSize = 22.dp,
)
}
// Drawn on the side the panel opens on, and filled in while it's open.
val playerLeft by CarSettings.playerLeft.collectAsState()
val docked = navigator.current == CarScreen.Home && navigator.sidePanel != SidePanel.NONE
GsIconButton(
MediaIcons.DockRight, "Move the player beside the map", navigator::togglePlayerDock,
when {
playerLeft && docked -> MediaIcons.DockLeftOpen
playerLeft -> MediaIcons.DockLeft
docked -> MediaIcons.DockRightOpen
else -> MediaIcons.DockRight
},
if (docked) "Close the side panel" else "Move the player beside the map",
navigator::togglePlayerDock,
size = 36.dp, iconSize = 22.dp,
)
}
@@ -90,8 +90,9 @@ class CarNavigator(startId: String) {
private set
/**
* The pill's dock button: moves the player beside the map, going Home first if need be. With
* lyrics already there it swaps them for the controls; with the controls there it closes.
* The pill's dock button, an open/close switch for the panel: moves the player beside the map,
* going Home first if need be, or closes the panel when something is already there. Switching
* between the player and lyrics is done inside the panel itself.
*/
fun togglePlayerDock() {
if (current != CarScreen.Home) {
@@ -99,9 +100,11 @@ class CarNavigator(startId: String) {
home()
return
}
sidePanel = if (sidePanel == SidePanel.CONTROLS) SidePanel.NONE else SidePanel.CONTROLS
sidePanel = if (sidePanel == SidePanel.NONE) SidePanel.CONTROLS else SidePanel.NONE
}
fun showSidePlayer() { sidePanel = SidePanel.CONTROLS }
fun showSideLyrics() { sidePanel = SidePanel.LYRICS }
fun closeSidePanel() { sidePanel = SidePanel.NONE }
@@ -217,8 +217,14 @@ internal object MediaIcons {
val Shuffle = icon("Shuffle", "M10.59,9.17L5.41,4 4,5.41l5.17,5.17 1.42,-1.41zM14.5,4l2.04,2.04L4,18.59 5.41,20 17.96,7.46 20,9.5L20,4h-5.5zM14.83,13.41l-1.41,1.41 3.13,3.13L14.5,20L20,20v-5.5l-2.04,2.04 -3.13,-3.13z")
val Repeat = icon("Repeat", "M7,7h10v3l4,-4 -4,-4v3L5,5v6h2L7,7zM17,17L7,17v-3l-4,4 4,4v-3h12v-6h-2v4z")
val RepeatOne = icon("RepeatOne", "M7,7h10v3l4,-4 -4,-4v3L5,5v6h2L7,7zM17,17L7,17v-3l-4,4 4,4v-3h12v-6h-2v4zM13,15L13,9h-1l-2,1v1h1.5v4L13,15z")
/** A screen with a filled right-hand panel: "put the player beside the map". */
val DockRight = icon("DockRight", "M2,4h20v16H2zM4,6h10v12H4z", PathFillType.EvenOdd)
/**
* A screen split into the map and a side panel: outlined while the panel is closed ("put the
* player beside the map"), filled in while it's open ("close it"), on the side it opens on.
*/
val DockRight = icon("DockRight", "M2,4h20v16H2zM4,6h10v12H4zM16,6h4v12h-4z", PathFillType.EvenOdd)
val DockRightOpen = icon("DockRightOpen", "M2,4h20v16H2zM4,6h10v12H4z", PathFillType.EvenOdd)
val DockLeft = icon("DockLeft", "M2,4h20v16H2zM4,6h4v12H4zM10,6h10v12H10z", PathFillType.EvenOdd)
val DockLeftOpen = icon("DockLeftOpen", "M2,4h20v16H2zM10,6h10v12H10z", PathFillType.EvenOdd)
val Fullscreen = icon("Fullscreen", "M7,14L5,14v5h5v-2L7,17v-3zM5,10h2L7,7h3L10,5L5,5v5zM17,17h-3v2h5v-5h-2v3zM14,5v2h3v3h2L19,5h-5z")
val FullscreenExit = icon("FullscreenExit", "M5,16h3v3h2v-5L5,14v2zM8,8L5,8v2h5L10,5L8,5v3zM14,19h2v-3h3v-2h-5v5zM16,8L16,5h-2v5h5L19,8h-3z")