diff --git a/android/app/src/main/java/com/fabledsword/minstrel/history/ui/HistoryTab.kt b/android/app/src/main/java/com/fabledsword/minstrel/history/ui/HistoryTab.kt index aa584fdb..68fe457c 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/history/ui/HistoryTab.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/history/ui/HistoryTab.kt @@ -1,11 +1,9 @@ package com.fabledsword.minstrel.history.ui -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -14,9 +12,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.ViewModel @@ -27,7 +23,7 @@ import com.fabledsword.minstrel.history.data.HistoryEntry import com.fabledsword.minstrel.history.data.HistoryRepository import com.fabledsword.minstrel.models.TrackRef import com.fabledsword.minstrel.player.PlayerController -import com.fabledsword.minstrel.shared.widgets.CachedDot +import com.fabledsword.minstrel.shared.widgets.TrackRow import com.fabledsword.minstrel.shared.widgets.EmptyState import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold @@ -171,48 +167,30 @@ private fun HistoryRow( onNavigateToAlbum: (String) -> Unit, onNavigateToArtist: (String) -> Unit, ) { - val titleColor = if (nowPlaying) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.onSurface - } - Row( - modifier = Modifier - .fillMaxWidth() - .clickable(enabled = entry.track.streamUrl.isNotEmpty(), onClick = onClick) - .padding(horizontal = 16.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically, + TrackRow( + title = entry.track.title, + artist = entry.track.artistName.ifEmpty { entry.track.albumTitle }, + trackId = entry.track.id, + onClick = onClick, + nowPlaying = nowPlaying, + enabled = entry.track.streamUrl.isNotEmpty(), horizontalArrangement = Arrangement.spacedBy(12.dp), - ) { - TrackCoverThumb(coverUrl = entry.track.coverUrl, contentDescription = entry.track.title) - Column(modifier = Modifier.weight(1f)) { + leading = { + TrackCoverThumb(coverUrl = entry.track.coverUrl, contentDescription = entry.track.title) + }, + trailing = { Text( - text = entry.track.title, - style = MaterialTheme.typography.bodyLarge, - color = titleColor, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - Text( - text = entry.track.artistName.ifEmpty { entry.track.albumTitle }, + text = relativeTime(entry.playedAt), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, - maxLines = 1, - overflow = TextOverflow.Ellipsis, ) - } - CachedDot(entry.track.id) - Text( - text = relativeTime(entry.playedAt), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - TrackActionsButton( - track = entry.track, - onNavigateToAlbum = onNavigateToAlbum, - onNavigateToArtist = onNavigateToArtist, - ) - } + TrackActionsButton( + track = entry.track, + onNavigateToAlbum = onNavigateToAlbum, + onNavigateToArtist = onNavigateToArtist, + ) + }, + ) } // ─── Time helpers ──────────────────────────────────────────────────── diff --git a/android/app/src/main/java/com/fabledsword/minstrel/likes/ui/LikedTab.kt b/android/app/src/main/java/com/fabledsword/minstrel/likes/ui/LikedTab.kt index 48e06895..3dbd043c 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/likes/ui/LikedTab.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/likes/ui/LikedTab.kt @@ -1,6 +1,5 @@ package com.fabledsword.minstrel.likes.ui -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues @@ -20,7 +19,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.ViewModel @@ -37,7 +35,7 @@ import com.fabledsword.minstrel.models.TrackRef import com.fabledsword.minstrel.nav.AlbumDetail import com.fabledsword.minstrel.nav.ArtistDetail import com.fabledsword.minstrel.player.PlayerController -import com.fabledsword.minstrel.shared.widgets.CachedDot +import com.fabledsword.minstrel.shared.widgets.TrackRow import com.fabledsword.minstrel.shared.widgets.EmptyState import com.fabledsword.minstrel.shared.widgets.HorizontalScrollRow import com.fabledsword.minstrel.shared.widgets.LikeButton @@ -259,42 +257,24 @@ private fun LikedTrackRow( onNavigateToAlbum: (String) -> Unit, onNavigateToArtist: (String) -> Unit, ) { - val titleColor = if (nowPlaying) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.onSurface - } - Row( - modifier = Modifier - .fillMaxWidth() - .clickable(enabled = track.streamUrl.isNotEmpty(), onClick = onClick) - .padding(horizontal = 16.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically, + TrackRow( + title = track.title, + artist = track.artistName.ifEmpty { track.albumTitle }, + trackId = track.id, + onClick = onClick, + nowPlaying = nowPlaying, + enabled = track.streamUrl.isNotEmpty(), horizontalArrangement = Arrangement.spacedBy(12.dp), - ) { - TrackCoverThumb(coverUrl = track.coverUrl, contentDescription = track.title) - Column(modifier = Modifier.weight(1f)) { - Text( - text = track.title, - style = MaterialTheme.typography.bodyLarge, - color = titleColor, - maxLines = 1, - overflow = TextOverflow.Ellipsis, + leading = { + TrackCoverThumb(coverUrl = track.coverUrl, contentDescription = track.title) + }, + trailing = { + LikeButton(liked = true, onToggle = onUnlike) + TrackActionsButton( + track = track, + onNavigateToAlbum = onNavigateToAlbum, + onNavigateToArtist = onNavigateToArtist, ) - Text( - text = track.artistName.ifEmpty { track.albumTitle }, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } - CachedDot(track.id) - LikeButton(liked = true, onToggle = onUnlike) - TrackActionsButton( - track = track, - onNavigateToAlbum = onNavigateToAlbum, - onNavigateToArtist = onNavigateToArtist, - ) - } + }, + ) } diff --git a/android/app/src/main/java/com/fabledsword/minstrel/playlists/ui/PlaylistDetailScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/playlists/ui/PlaylistDetailScreen.kt index 83000c9f..1744ff22 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/playlists/ui/PlaylistDetailScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/playlists/ui/PlaylistDetailScreen.kt @@ -4,7 +4,6 @@ package com.fabledsword.minstrel.playlists.ui import androidx.compose.animation.Crossfade import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -73,7 +72,7 @@ import com.fabledsword.minstrel.likes.data.LikesRepository import com.fabledsword.minstrel.playlists.data.PlaylistDetailRef import com.fabledsword.minstrel.playlists.data.PlaylistsRepository import com.fabledsword.minstrel.shared.formatDuration -import com.fabledsword.minstrel.shared.widgets.CachedDot +import com.fabledsword.minstrel.shared.widgets.TrackRow import com.fabledsword.minstrel.shared.widgets.LikeButton import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold import com.fabledsword.minstrel.shared.widgets.SkeletonTrackRow @@ -497,55 +496,38 @@ private fun TrackRow( ) { val enabled = row.isAvailable val rowAlpha = if (enabled) 1f else UNAVAILABLE_ALPHA - val baseTitleColor = 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, - ) { - TrackCoverThumb( - coverUrl = row.coverUrl, - contentDescription = row.title, - modifier = Modifier.padding(end = 12.dp), - ) - Column(modifier = Modifier.weight(1f)) { - Text( - text = row.title, - style = MaterialTheme.typography.bodyLarge, - color = baseTitleColor.copy(alpha = rowAlpha), - maxLines = 1, - overflow = TextOverflow.Ellipsis, + TrackRow( + title = row.title, + artist = row.artistName.ifEmpty { row.albumTitle }, + trackId = row.trackId.orEmpty(), + onClick = onClick, + nowPlaying = nowPlaying, + enabled = enabled, + contentAlpha = rowAlpha, + leading = { + TrackCoverThumb( + coverUrl = row.coverUrl, + contentDescription = row.title, + modifier = Modifier.padding(end = 12.dp), ) + }, + trailing = { Text( - text = row.artistName.ifEmpty { row.albumTitle }, + text = formatDuration(row.durationSec, zero = "--:--"), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = rowAlpha), - maxLines = 1, - overflow = TextOverflow.Ellipsis, + modifier = Modifier.padding(start = 12.dp), ) - } - row.trackId?.let { CachedDot(it) } - Text( - text = formatDuration(row.durationSec, zero = "--:--"), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = rowAlpha), - modifier = Modifier.padding(start = 12.dp), - ) - if (enabled) { - LikeButton(liked = liked, onToggle = onToggleLike) - TrackActionsButton( - track = row.toTrackRef(), - onNavigateToAlbum = onNavigateToAlbum, - onNavigateToArtist = onNavigateToArtist, - ) - } - } + if (enabled) { + LikeButton(liked = liked, onToggle = onToggleLike) + TrackActionsButton( + track = row.toTrackRef(), + onNavigateToAlbum = onNavigateToAlbum, + onNavigateToArtist = onNavigateToArtist, + ) + } + }, + ) } private const val SKELETON_PLAYLIST_ROWS = 8 diff --git a/android/app/src/main/java/com/fabledsword/minstrel/search/ui/SearchScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/search/ui/SearchScreen.kt index 2c8d9086..36c84f65 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/search/ui/SearchScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/search/ui/SearchScreen.kt @@ -6,7 +6,6 @@ package com.fabledsword.minstrel.search.ui -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -42,7 +41,6 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -59,7 +57,7 @@ import com.fabledsword.minstrel.models.TrackRef import com.fabledsword.minstrel.nav.AlbumDetail import com.fabledsword.minstrel.nav.ArtistDetail import com.fabledsword.minstrel.nav.Search as SearchRoute -import com.fabledsword.minstrel.shared.widgets.CachedDot +import com.fabledsword.minstrel.shared.widgets.TrackRow import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.MainAppBarActions import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb @@ -278,47 +276,25 @@ private fun TrackResultRow( onNavigateToAlbum: (String) -> Unit, onNavigateToArtist: (String) -> Unit, ) { - val titleColor = if (nowPlaying) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.onSurface - } - Row( - modifier = Modifier - .fillMaxWidth() - .clickable(enabled = track.streamUrl.isNotEmpty(), onClick = onClick) - .padding(horizontal = 16.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically, + TrackRow( + title = track.title, + artist = track.artistName.ifEmpty { track.albumTitle }, + trackId = track.id, + onClick = onClick, + nowPlaying = nowPlaying, + enabled = track.streamUrl.isNotEmpty(), horizontalArrangement = Arrangement.spacedBy(12.dp), - ) { - TrackCoverThumb(coverUrl = track.coverUrl, contentDescription = track.title) - Column(modifier = Modifier.weight(1f)) { - Text( - text = track.title, - style = MaterialTheme.typography.bodyLarge, - color = titleColor, - maxLines = 1, - overflow = TextOverflow.Ellipsis, + leading = { + TrackCoverThumb(coverUrl = track.coverUrl, contentDescription = track.title) + }, + trailing = { + TrackActionsButton( + track = track, + onNavigateToAlbum = onNavigateToAlbum, + onNavigateToArtist = onNavigateToArtist, ) - val secondary = track.artistName.takeIf { it.isNotEmpty() } - ?: track.albumTitle.takeIf { it.isNotEmpty() } - if (secondary != null) { - Text( - text = secondary, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } - } - CachedDot(track.id) - TrackActionsButton( - track = track, - onNavigateToAlbum = onNavigateToAlbum, - onNavigateToArtist = onNavigateToArtist, - ) - } + }, + ) } @Composable diff --git a/android/app/src/main/java/com/fabledsword/minstrel/shared/widgets/TrackRow.kt b/android/app/src/main/java/com/fabledsword/minstrel/shared/widgets/TrackRow.kt index e4e88cbc..0b5c95c1 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/shared/widgets/TrackRow.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/shared/widgets/TrackRow.kt @@ -1,6 +1,7 @@ package com.fabledsword.minstrel.shared.widgets import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope @@ -40,6 +41,7 @@ fun TrackRow( nowPlaying: Boolean = false, enabled: Boolean = true, contentAlpha: Float = 1f, + horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, leading: @Composable () -> Unit = {}, trailing: @Composable RowScope.() -> Unit = {}, ) { @@ -54,6 +56,7 @@ fun TrackRow( .clickable(enabled = enabled, onClick = onClick) .padding(horizontal = 16.dp, vertical = 8.dp), verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = horizontalArrangement, ) { leading() Column(modifier = Modifier.weight(1f)) {