refactor(android): add shared slot-based TrackRow
This commit is contained in:
@@ -0,0 +1,80 @@
|
|||||||
|
package com.fabledsword.minstrel.shared.widgets
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.RowScope
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared track-list row. Replaces the 5 per-screen `TrackRow`s — every
|
||||||
|
* track list shares the same row skeleton (clickable Row, title + artist
|
||||||
|
* column, CachedDot, nowPlaying highlight); only the leading element
|
||||||
|
* (track number vs cover thumb) and the trailing controls (duration,
|
||||||
|
* relative time, LikeButton, TrackActionsButton) vary. Callers fill
|
||||||
|
* those via the [leading] and [trailing] slots so each screen's row is
|
||||||
|
* a thin wrapper that no longer re-implements the Row layout.
|
||||||
|
*
|
||||||
|
* [enabled] gates the click (use for unavailable rows). [contentAlpha]
|
||||||
|
* dims the title + artist text colors — pass <1f for the
|
||||||
|
* playlist-track-unavailable case. The trailing slot is responsible
|
||||||
|
* for applying its own alpha if it should match (the row doesn't
|
||||||
|
* cascade because the trailing slot's content is the caller's, not
|
||||||
|
* ours).
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun TrackRow(
|
||||||
|
title: String,
|
||||||
|
artist: String,
|
||||||
|
trackId: String,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
nowPlaying: Boolean = false,
|
||||||
|
enabled: Boolean = true,
|
||||||
|
contentAlpha: Float = 1f,
|
||||||
|
leading: @Composable () -> Unit = {},
|
||||||
|
trailing: @Composable RowScope.() -> Unit = {},
|
||||||
|
) {
|
||||||
|
val titleColor = if (nowPlaying) {
|
||||||
|
MaterialTheme.colorScheme.primary
|
||||||
|
} else {
|
||||||
|
MaterialTheme.colorScheme.onSurface
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable(enabled = enabled, onClick = onClick)
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
leading()
|
||||||
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
|
color = titleColor.copy(alpha = contentAlpha),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
if (artist.isNotEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = artist,
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = contentAlpha),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CachedDot(trackId)
|
||||||
|
trailing()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user