refactor(android): add shared slot-based TrackRow

This commit is contained in:
2026-05-29 21:40:38 -04:00
parent dfb7245db8
commit bbd483603d
@@ -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()
}
}