mirror of
https://github.com/twinksoftware/Gearslip.git
synced 2026-11-11 00:12:24 +01:00
media: the player card with its cover sits beside every tab, Up next comes after Now playing, and Browse's header gets room
This commit is contained in:
1 parent
15d6721705
commit
324112ca8b
2 files changed
+30
-26
No files matched your search
@@ -84,14 +84,15 @@ internal fun BrowsePanel(browse: app.seb3thehacker.gearslip.media.BrowseState, m
|
|||||||
// row could say that the app's name in the top-left corner hasn't already - showing it
|
// row could say that the app's name in the top-left corner hasn't already - showing it
|
||||||
// again here (as "Browse", or as the app's own name) was just the same label twice.
|
// again here (as "Browse", or as the app's own name) was just the same label twice.
|
||||||
if (media.canGoUp || browse.trail.isNotEmpty()) {
|
if (media.canGoUp || browse.trail.isNotEmpty()) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(Modifier.padding(bottom = 12.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
if (media.canGoUp) {
|
if (media.canGoUp) {
|
||||||
GsIconButton(Icons.Filled.ArrowBack, "Up", media::up)
|
GsIconButton(Icons.Filled.ArrowBack, "Up", media::up, size = 44.dp, shape = CircleShape)
|
||||||
|
Spacer(Modifier.width(14.dp))
|
||||||
}
|
}
|
||||||
browse.trail.lastOrNull()?.let {
|
browse.trail.lastOrNull()?.let {
|
||||||
Text(
|
Text(
|
||||||
it,
|
it,
|
||||||
style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold,
|
style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold,
|
||||||
maxLines = 1, overflow = TextOverflow.Ellipsis,
|
maxLines = 1, overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -251,9 +252,9 @@ private fun QueueRow(track: QueueTrack, media: CarMedia) {
|
|||||||
color = MaterialTheme.colorScheme.surfaceContainer,
|
color = MaterialTheme.colorScheme.surfaceContainer,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
) {
|
) {
|
||||||
Row(Modifier.padding(10.dp), verticalAlignment = Alignment.CenterVertically) {
|
Row(Modifier.padding(8.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
RowArt(icon, MediaIcons.MusicNote)
|
RowArt(icon, MediaIcons.MusicNote)
|
||||||
Column(Modifier.weight(1f).padding(horizontal = 12.dp)) {
|
Column(Modifier.weight(1f).padding(horizontal = 14.dp)) {
|
||||||
Text(track.title, style = MaterialTheme.typography.titleMedium, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
Text(track.title, style = MaterialTheme.typography.titleMedium, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||||
if (track.subtitle.isNotEmpty()) {
|
if (track.subtitle.isNotEmpty()) {
|
||||||
Text(track.subtitle, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
Text(track.subtitle, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||||
@@ -276,9 +277,9 @@ internal fun EntryRow(entry: MediaEntry, media: CarMedia, onClick: () -> Unit =
|
|||||||
color = MaterialTheme.colorScheme.surfaceContainer,
|
color = MaterialTheme.colorScheme.surfaceContainer,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
) {
|
) {
|
||||||
Row(Modifier.padding(10.dp), verticalAlignment = Alignment.CenterVertically) {
|
Row(Modifier.padding(8.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
RowArt(icon, if (entry.browsable) MediaIcons.Folder else MediaIcons.MusicNote)
|
RowArt(icon, if (entry.browsable) MediaIcons.Folder else MediaIcons.MusicNote)
|
||||||
Column(Modifier.weight(1f).padding(horizontal = 12.dp)) {
|
Column(Modifier.weight(1f).padding(horizontal = 14.dp)) {
|
||||||
Text(entry.title, style = MaterialTheme.typography.titleMedium, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
Text(entry.title, style = MaterialTheme.typography.titleMedium, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||||
if (entry.subtitle.isNotEmpty()) {
|
if (entry.subtitle.isNotEmpty()) {
|
||||||
Text(entry.subtitle, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
Text(entry.subtitle, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||||
@@ -296,7 +297,7 @@ internal fun EntryRow(entry: MediaEntry, media: CarMedia, onClick: () -> Unit =
|
|||||||
@Composable
|
@Composable
|
||||||
private fun RowArt(icon: android.graphics.Bitmap?, fallback: ImageVector) {
|
private fun RowArt(icon: android.graphics.Bitmap?, fallback: ImageVector) {
|
||||||
Box(
|
Box(
|
||||||
Modifier.size(62.dp).clip(MaterialTheme.shapes.medium).background(MaterialTheme.colorScheme.surfaceContainerHigh),
|
Modifier.size(56.dp).clip(RoundedCornerShape(12.dp)).background(MaterialTheme.colorScheme.surfaceContainerHigh),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
if (icon != null) Image(icon.asImageBitmap(), null, Modifier.fillMaxSize(), contentScale = ContentScale.Crop)
|
if (icon != null) Image(icon.asImageBitmap(), null, Modifier.fillMaxSize(), contentScale = ContentScale.Crop)
|
||||||
|
|||||||
@@ -175,14 +175,14 @@ fun MediaScreen(app: MediaApp, onExit: () -> Unit) {
|
|||||||
if (tab == Tab.NOW_PLAYING) {
|
if (tab == Tab.NOW_PLAYING) {
|
||||||
CoverArt(art, Modifier.weight(1f).fillMaxWidth())
|
CoverArt(art, Modifier.weight(1f).fillMaxWidth())
|
||||||
} else {
|
} else {
|
||||||
CompactPlayer(now, media, Modifier.weight(1f).fillMaxWidth())
|
CompactPlayer(now, media, art, Modifier.weight(1f).fillMaxWidth())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column(Modifier.weight(1.2f).fillMaxHeight()) {
|
Column(Modifier.weight(1.2f).fillMaxHeight()) {
|
||||||
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
MediaTab("Now playing", tab == Tab.NOW_PLAYING, Modifier.weight(1f)) { tab = Tab.NOW_PLAYING }
|
MediaTab("Now playing", tab == Tab.NOW_PLAYING, Modifier.weight(1f)) { tab = Tab.NOW_PLAYING }
|
||||||
MediaTab("Browse", tab == Tab.BROWSE, Modifier.weight(1f)) { tab = Tab.BROWSE }
|
|
||||||
MediaTab("Up next", tab == Tab.QUEUE, Modifier.weight(1f)) { tab = Tab.QUEUE }
|
MediaTab("Up next", tab == Tab.QUEUE, Modifier.weight(1f)) { tab = Tab.QUEUE }
|
||||||
|
MediaTab("Browse", tab == Tab.BROWSE, Modifier.weight(1f)) { tab = Tab.BROWSE }
|
||||||
MediaTab("Lyrics", tab == Tab.LYRICS, Modifier.weight(1f)) { tab = Tab.LYRICS }
|
MediaTab("Lyrics", tab == Tab.LYRICS, Modifier.weight(1f)) { tab = Tab.LYRICS }
|
||||||
if (now.canSearch || media.canSearchLibrary) {
|
if (now.canSearch || media.canSearchLibrary) {
|
||||||
GsIconButton(
|
GsIconButton(
|
||||||
@@ -603,8 +603,8 @@ internal fun NowPlayingPage(now: NowPlaying, media: CarMedia, modifier: Modifier
|
|||||||
|
|
||||||
/** The cover, as big a square as its space allows, centred in it. */
|
/** The cover, as big a square as its space allows, centred in it. */
|
||||||
@Composable
|
@Composable
|
||||||
private fun CoverArt(art: android.graphics.Bitmap?, modifier: Modifier) {
|
private fun CoverArt(art: android.graphics.Bitmap?, modifier: Modifier, alignment: Alignment = Alignment.Center) {
|
||||||
BoxWithConstraints(modifier, contentAlignment = Alignment.Center) {
|
BoxWithConstraints(modifier, contentAlignment = alignment) {
|
||||||
val shape = RoundedCornerShape(22.dp)
|
val shape = RoundedCornerShape(22.dp)
|
||||||
Surface(
|
Surface(
|
||||||
shape = shape,
|
shape = shape,
|
||||||
@@ -707,30 +707,33 @@ private fun NowPlayingControls(now: NowPlaying, media: CarMedia, modifier: Modif
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The player beside the browse list, the queue and the lyrics: no art, which the list needs the
|
* The player beside the browse list, the queue and the lyrics: the same card as beside the map on
|
||||||
* room for, just what's playing, the seek bar and the controls.
|
* Home, the cover taking whatever the title and controls leave, so every tab keeps the song in
|
||||||
|
* sight and the controls in one place.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
private fun CompactPlayer(now: NowPlaying, media: CarMedia, modifier: Modifier) {
|
private fun CompactPlayer(now: NowPlaying, media: CarMedia, art: android.graphics.Bitmap?, modifier: Modifier) {
|
||||||
Column(
|
val shape = RoundedCornerShape(24.dp)
|
||||||
modifier.verticalScroll(rememberScrollState()),
|
Surface(modifier.gsPanelShadow(shape), shape = shape, color = MaterialTheme.colorScheme.surfaceContainer) {
|
||||||
verticalArrangement = Arrangement.spacedBy(14.dp),
|
AlbumGlow(art, Modifier.fillMaxSize())
|
||||||
) {
|
Column(Modifier.fillMaxSize().padding(14.dp), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
Column {
|
CoverArt(art, Modifier.weight(1f).fillMaxWidth(), Alignment.BottomCenter)
|
||||||
|
Spacer(Modifier.height(10.dp))
|
||||||
Text(
|
Text(
|
||||||
now.title.ifEmpty { "Nothing playing" },
|
now.title.ifEmpty { "Nothing playing" },
|
||||||
style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold,
|
style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold,
|
||||||
maxLines = 2, overflow = TextOverflow.Ellipsis,
|
maxLines = 1, overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
now.artist,
|
now.artist,
|
||||||
style = MaterialTheme.typography.bodyLarge, color = MaterialTheme.colorScheme.onSurfaceVariant,
|
style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
maxLines = 1, overflow = TextOverflow.Ellipsis,
|
maxLines = 1, overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
|
PlayerProgress(now, media, Modifier.fillMaxWidth().padding(vertical = 2.dp), showTimes = false)
|
||||||
|
TransportRow(now, media, skip = 52.dp, modifier = Modifier.fillMaxWidth())
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
PlayModeRow(now, media, size = 46.dp, modifier = Modifier.fillMaxWidth())
|
||||||
}
|
}
|
||||||
PlayerProgress(now, media, Modifier.fillMaxWidth())
|
|
||||||
TransportRow(now, media, skip = 52.dp, modifier = Modifier.fillMaxWidth())
|
|
||||||
PlayModeRow(now, media, size = 48.dp, modifier = Modifier.fillMaxWidth())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user