mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 15:11:58 +01:00
ui: finish the library info dialogs and add playlist info
Sort names and titles are only shown when they differ from the regular name, so artists without a distinct sort name no longer repeat the name. Track info uses plural labels for both the artists and their sort name when the track has more than one artist, and singular labels otherwise. Added and last played sit together in album info. Playlists gain an Info dialog with owner, sharing, song count, length, creation and update dates. Owner and the public flag are synced from getPlaylists, so a schema migration adds both columns.
This commit is contained in:
+2009
File diff suppressed because it is too large
Load Diff
@@ -722,6 +722,14 @@ val MIGRATION_36_37 =
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_37_38 =
|
||||
object : Migration(37, 38) {
|
||||
override suspend fun migrate(connection: SQLiteConnection) {
|
||||
connection.execSQL("ALTER TABLE `playlists` ADD COLUMN `owner` TEXT")
|
||||
connection.execSQL("ALTER TABLE `playlists` ADD COLUMN `shared` INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun artistSearchTriggersOptimized(connection: SQLiteConnection): Boolean {
|
||||
val triggers = mutableListOf<String>()
|
||||
connection.prepare("SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name IN (?, ?)").use { statement ->
|
||||
@@ -799,4 +807,5 @@ val MIGRATIONS: Array<Migration> =
|
||||
MIGRATION_34_35,
|
||||
MIGRATION_35_36,
|
||||
MIGRATION_36_37,
|
||||
MIGRATION_37_38,
|
||||
)
|
||||
|
||||
@@ -57,7 +57,7 @@ import com.subtracks.data.model.UpNextEntry
|
||||
SongDownload::class,
|
||||
PendingAction::class,
|
||||
],
|
||||
version = 37,
|
||||
version = 38,
|
||||
exportSchema = true,
|
||||
)
|
||||
@ColumnTypeConverters(
|
||||
|
||||
@@ -254,6 +254,8 @@ data class Playlist(
|
||||
val created: Long,
|
||||
@ColumnInfo(defaultValue = "0") val changed: Long = 0,
|
||||
@ColumnInfo(defaultValue = "0") val duration: Long = 0,
|
||||
val owner: String? = null,
|
||||
@ColumnInfo(defaultValue = "0") val shared: Boolean = false,
|
||||
)
|
||||
|
||||
@Entity(
|
||||
|
||||
@@ -129,6 +129,8 @@ object SubsonicXml {
|
||||
created = attrs.dateAttr("created") ?: 0L,
|
||||
changed = attrs.dateAttr("changed") ?: 0L,
|
||||
duration = attrs.longAttr("duration") ?: 0L,
|
||||
owner = attrs.attr("owner").ifEmpty { null },
|
||||
shared = attrs.boolAttr("public"),
|
||||
)
|
||||
|
||||
internal fun playlistSong(
|
||||
@@ -365,6 +367,8 @@ internal fun Attributes.attr(name: String): String = getValue(name) ?: ""
|
||||
|
||||
internal fun Attributes.longAttr(name: String): Long? = attr(name).takeIf { it.isNotEmpty() }?.toLongOrNull()
|
||||
|
||||
internal fun Attributes.boolAttr(name: String): Boolean = attr(name).equals("true", ignoreCase = true)
|
||||
|
||||
internal fun Attributes.floatAttr(name: String): Float? = attr(name).takeIf { it.isNotEmpty() }?.toFloatOrNull()?.takeIf { it.isFinite() }
|
||||
|
||||
internal fun Attributes.dateAttr(name: String): Long? = attr(name).takeIf { it.isNotEmpty() }?.let(IsoDate::parse)
|
||||
|
||||
@@ -487,7 +487,8 @@ private val songColumns =
|
||||
"artistSort",
|
||||
)
|
||||
|
||||
private val playlistColumns = listOf("sourceId", "id", "name", "comment", "coverArt", "songCount", "created", "changed", "duration")
|
||||
private val playlistColumns =
|
||||
listOf("sourceId", "id", "name", "comment", "coverArt", "songCount", "created", "changed", "duration", "owner", "shared")
|
||||
|
||||
private fun Song.genreNames(): List<String> =
|
||||
genres
|
||||
@@ -577,7 +578,7 @@ private fun Song.artistPositions(): List<Pair<Long, ArtistRef>> = artistRefs.pos
|
||||
|
||||
private fun SongGenre.values() = listOf<Any?>(sourceId, songId, position, genre)
|
||||
|
||||
private fun Playlist.values() = listOf<Any?>(sourceId, id, name, comment, coverArt, songCount, created, changed, duration)
|
||||
private fun Playlist.values() = listOf<Any?>(sourceId, id, name, comment, coverArt, songCount, created, changed, duration, owner, shared)
|
||||
|
||||
private fun PlaylistSong.values() = listOf<Any?>(sourceId, playlistId, songId, position)
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ import com.subtracks.ui.components.ContextMenuHost
|
||||
import com.subtracks.ui.components.ItemContextMenu
|
||||
import com.subtracks.ui.components.LoadingState
|
||||
import com.subtracks.ui.components.MenuTarget
|
||||
import com.subtracks.ui.components.PlaylistInfoDialog
|
||||
import com.subtracks.ui.components.SongInfoDialog
|
||||
import com.subtracks.ui.components.statusBarScrim
|
||||
import com.subtracks.ui.downloads.DownloadsRoute
|
||||
@@ -832,7 +833,14 @@ private fun MainNavigation() {
|
||||
)
|
||||
}
|
||||
|
||||
is MenuTarget.Playlist, null -> {
|
||||
is MenuTarget.Playlist -> {
|
||||
PlaylistInfoDialog(
|
||||
playlist = target.playlist,
|
||||
onDismiss = { infoTarget = null },
|
||||
)
|
||||
}
|
||||
|
||||
null -> {
|
||||
Unit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +299,9 @@ fun ItemContextMenu(
|
||||
is MenuTarget.Playlist -> {
|
||||
queueItems()
|
||||
BulkDownloadItem(target, actions, ::dismiss)
|
||||
onInfo?.let { info ->
|
||||
MenuItem(Icons.Rounded.Info, stringResource(R.string.info)) { dismiss { info(target) } }
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.subtracks.data.model.Album
|
||||
import com.subtracks.data.model.Artist
|
||||
import com.subtracks.data.model.ArtistRef
|
||||
import com.subtracks.data.model.ListDownloadStatus
|
||||
import com.subtracks.data.model.Playlist
|
||||
|
||||
private const val ARTIST_SEPARATOR = " \u00B7 "
|
||||
|
||||
@@ -40,9 +41,9 @@ fun AlbumInfoDialog(
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
InfoRow(stringResource(R.string.resources_sort_by_title), album.name)
|
||||
InfoRow(stringResource(R.string.info_sort_title), album.sortName)
|
||||
InfoRow(stringResource(R.string.info_sort_title), album.sortName.takeIfDifferentFrom(album.name))
|
||||
InfoRow(stringResource(R.string.info_album_artists), album.artistRefs.names())
|
||||
InfoRow(stringResource(R.string.info_album_artist_sort), album.albumArtistSort)
|
||||
InfoRow(stringResource(R.string.info_album_artist_sort), album.albumArtistSort.takeIfDifferentFrom(album.albumArtist))
|
||||
InfoRow(stringResource(R.string.resources_sort_by_year), album.year?.takeIf { it > 0 }?.toString())
|
||||
InfoRow(stringResource(R.string.resources_filter_genre), album.genre)
|
||||
InfoRow(stringResource(R.string.info_songs), album.songCount.takeIf { it > 0 }?.toString())
|
||||
@@ -53,8 +54,8 @@ fun AlbumInfoDialog(
|
||||
)
|
||||
}
|
||||
InfoRow(stringResource(R.string.info_added), album.created.takeIf { it > 0 }?.let { formatDate(context, it) })
|
||||
InfoRow(stringResource(R.string.info_plays), album.playCount.takeIf { it > 0 }?.toString())
|
||||
InfoRow(stringResource(R.string.info_last_played), album.played?.let { formatDate(context, it) })
|
||||
InfoRow(stringResource(R.string.info_plays), album.playCount.takeIf { it > 0 }?.toString())
|
||||
InfoRow(stringResource(R.string.info_starred), if (album.starred != null) stringResource(R.string.info_yes) else null)
|
||||
}
|
||||
},
|
||||
@@ -74,7 +75,7 @@ fun ArtistInfoDialog(
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
InfoRow(stringResource(R.string.resources_filter_artist), artist.name)
|
||||
InfoRow(stringResource(R.string.info_sort_name), artist.sortName)
|
||||
InfoRow(stringResource(R.string.info_sort_name), artist.sortName.takeIfDifferentFrom(artist.name))
|
||||
InfoRow(stringResource(R.string.info_albums), artist.albumCount.takeIf { it > 0 }?.toString())
|
||||
InfoRow(stringResource(R.string.info_songs), artist.songCount.takeIf { it > 0 }?.toString())
|
||||
InfoRow(stringResource(R.string.info_plays), artist.playCount.takeIf { it > 0 }?.toString())
|
||||
@@ -86,6 +87,33 @@ fun ArtistInfoDialog(
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PlaylistInfoDialog(
|
||||
playlist: Playlist,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = { Text(stringResource(R.string.info)) },
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
InfoRow(stringResource(R.string.resources_sort_by_title), playlist.name)
|
||||
InfoRow(stringResource(R.string.info_owner), playlist.owner)
|
||||
InfoRow(stringResource(R.string.info_shared), if (playlist.shared) stringResource(R.string.info_yes) else null)
|
||||
InfoRow(stringResource(R.string.info_songs), playlist.songCount.takeIf { it > 0 }?.toString())
|
||||
InfoRow(stringResource(R.string.info_length), playlist.duration.takeIf { it > 0 }?.let(DateUtils::formatElapsedTime))
|
||||
InfoRow(stringResource(R.string.info_created), playlist.created.takeIf { it > 0 }?.let { formatDate(context, it) })
|
||||
InfoRow(stringResource(R.string.info_updated), playlist.changed.takeIf { it > 0 }?.let { formatDate(context, it) })
|
||||
}
|
||||
},
|
||||
confirmButton = { TextButton(onClick = onDismiss) { Text(stringResource(R.string.info_close)) } },
|
||||
)
|
||||
}
|
||||
|
||||
internal fun String?.takeIfDifferentFrom(regular: String?): String? =
|
||||
this?.trim()?.takeIf { value -> value.isNotEmpty() && !value.equals(regular?.trim(), ignoreCase = true) }
|
||||
|
||||
@Composable
|
||||
internal fun InfoRow(
|
||||
label: String,
|
||||
|
||||
@@ -46,15 +46,25 @@ fun SongInfoDialog(
|
||||
title = { Text(stringResource(R.string.info)) },
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
val multipleArtists =
|
||||
song.artistRefs
|
||||
.map { it.name }
|
||||
.filter { it.isNotBlank() }
|
||||
.distinct()
|
||||
.size > 1
|
||||
val regularArtistSort = song.artist?.takeIf { it.isNotBlank() } ?: song.artistRefs.firstOrNull()?.name
|
||||
InfoRow(stringResource(R.string.resources_sort_by_title), song.title)
|
||||
InfoRow(stringResource(R.string.info_sort_title), song.sortName)
|
||||
InfoRow(stringResource(R.string.info_sort_title), song.sortName.takeIfDifferentFrom(song.title))
|
||||
InfoRow(
|
||||
stringResource(
|
||||
if (song.artistRefs.size > 1) R.string.info_artists else R.string.resources_filter_artist,
|
||||
if (multipleArtists) R.string.info_artists else R.string.resources_filter_artist,
|
||||
),
|
||||
song.artistSubtitle(),
|
||||
)
|
||||
InfoRow(stringResource(R.string.info_artist_sort), song.artistSort)
|
||||
InfoRow(
|
||||
stringResource(if (multipleArtists) R.string.info_artists_sort else R.string.info_artist_sort),
|
||||
song.artistSort.takeIfDifferentFrom(regularArtistSort),
|
||||
)
|
||||
InfoRow(stringResource(R.string.resources_filter_album), song.album)
|
||||
InfoRow(stringResource(R.string.info_duration), song.duration?.let(DateUtils::formatElapsedTime))
|
||||
InfoRow(
|
||||
|
||||
@@ -198,6 +198,7 @@
|
||||
<string name="info_channels">Channels</string>
|
||||
<string name="info_close">Close</string>
|
||||
<string name="info_artists">Artists</string>
|
||||
<string name="info_artists_sort">Artists sort</string>
|
||||
<string name="info_album_artists">Album artists</string>
|
||||
<string name="info_album_artist_sort">Album artist sort</string>
|
||||
<string name="info_sort_title">Sort title</string>
|
||||
@@ -208,6 +209,11 @@
|
||||
<string name="info_plays">Plays</string>
|
||||
<string name="info_last_played">Last played</string>
|
||||
<string name="info_added">Added</string>
|
||||
<string name="info_created">Created</string>
|
||||
<string name="info_updated">Updated</string>
|
||||
<string name="info_owner">Owner</string>
|
||||
<string name="info_shared">Shared</string>
|
||||
<string name="info_length">Length</string>
|
||||
<string name="info_downloaded_count">%1$d of %2$d</string>
|
||||
|
||||
<string name="disc_header">Disc %1$d</string>
|
||||
|
||||
@@ -745,6 +745,27 @@ class SubsonicXmlTest {
|
||||
assertEquals(true, failure.exceptionOrNull() is SubsonicException)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mapsPlaylistOwnerAndSharing() {
|
||||
val playlists =
|
||||
parse(
|
||||
"""
|
||||
<subsonic-response status="ok">
|
||||
<playlists>
|
||||
<playlist id="pl1" name="Shared" owner="austin" public="true" songCount="2" duration="120"/>
|
||||
<playlist id="pl2" name="Private" owner="austin" public="false" songCount="1" duration="60"/>
|
||||
</playlists>
|
||||
</subsonic-response>
|
||||
""".trimIndent(),
|
||||
tag = "playlist",
|
||||
create = { SubsonicXml.playlist(1, it) },
|
||||
)
|
||||
|
||||
assertEquals("austin", playlists[0].owner)
|
||||
assertTrue(playlists[0].shared)
|
||||
assertEquals(false, playlists[1].shared)
|
||||
}
|
||||
|
||||
private class CountingInputStream(
|
||||
input: InputStream,
|
||||
) : FilterInputStream(input) {
|
||||
|
||||
@@ -258,6 +258,19 @@ class SyncServiceTest {
|
||||
assertEquals(5678L, stored?.starred)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun syncStoresPlaylistOwnerAndSharing() =
|
||||
runTest {
|
||||
insertSource()
|
||||
val source = FakeMusicSource(playlists = listOf(playlist("p1").copy(owner = "austin", shared = true)))
|
||||
|
||||
SyncService(db, source).sync()
|
||||
|
||||
val stored = db.libraryDao().playlist(1, "p1").first()
|
||||
assertEquals("austin", stored?.owner)
|
||||
assertEquals(true, stored?.shared)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun syncStoresSongGenresInOrder() =
|
||||
runTest {
|
||||
|
||||
@@ -7,6 +7,7 @@ import androidx.compose.ui.test.performClick
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.subtracks.data.model.Album
|
||||
import com.subtracks.data.model.Artist
|
||||
import com.subtracks.data.model.Playlist
|
||||
import com.subtracks.ui.theme.SubtracksTheme
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Rule
|
||||
@@ -83,4 +84,35 @@ class ItemContextMenuInfoTest {
|
||||
|
||||
assertEquals("ar1", (opened as? MenuTarget.Artist)?.artist?.id)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aPlaylistMenuOpensItsInfo() {
|
||||
var opened: MenuTarget? = null
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
ItemContextMenu(
|
||||
target =
|
||||
MenuTarget.Playlist(
|
||||
Playlist(
|
||||
sourceId = 1,
|
||||
id = "pl1",
|
||||
name = "Playlist",
|
||||
comment = null,
|
||||
coverArt = null,
|
||||
songCount = 1,
|
||||
created = 0,
|
||||
),
|
||||
),
|
||||
actions = ItemActions(),
|
||||
onDismiss = {},
|
||||
onInfo = { opened = it },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
composeRule.onNodeWithText("Info").performClick()
|
||||
composeRule.mainClock.advanceTimeBy(1_000)
|
||||
|
||||
assertEquals("pl1", (opened as? MenuTarget.Playlist)?.playlist?.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.subtracks.data.model.Album
|
||||
import com.subtracks.data.model.Artist
|
||||
import com.subtracks.data.model.ArtistRef
|
||||
import com.subtracks.data.model.Playlist
|
||||
import com.subtracks.data.model.Song
|
||||
import com.subtracks.ui.theme.SubtracksTheme
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Rule
|
||||
@@ -83,4 +85,212 @@ class LibraryInfoDialogTest {
|
||||
composeRule.onNodeWithText("4").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("40").assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun anArtistHidesASortNameThatMatchesItsName() {
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
ArtistInfoDialog(
|
||||
artist =
|
||||
Artist(
|
||||
sourceId = 1,
|
||||
id = "ar1",
|
||||
name = "The Artist",
|
||||
albumCount = 1,
|
||||
starred = null,
|
||||
sortName = "the artist",
|
||||
),
|
||||
onDismiss = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
composeRule.onNodeWithText("Sort name").assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun anAlbumHidesSortNamesThatMatchTheRegularNames() {
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
AlbumInfoDialog(
|
||||
album =
|
||||
Album(
|
||||
sourceId = 1,
|
||||
id = "al1",
|
||||
artistId = "ar1",
|
||||
name = "Album",
|
||||
albumArtist = "Artist",
|
||||
created = 0,
|
||||
coverArt = null,
|
||||
genre = null,
|
||||
year = null,
|
||||
starred = null,
|
||||
songCount = 1,
|
||||
sortName = "album",
|
||||
albumArtistSort = "artist",
|
||||
),
|
||||
download = null,
|
||||
onDismiss = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
composeRule.onNodeWithText("Sort title").assertDoesNotExist()
|
||||
composeRule.onNodeWithText("Album artist sort").assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun anAlbumsDatesAreListedTogether() {
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
AlbumInfoDialog(
|
||||
album =
|
||||
Album(
|
||||
sourceId = 1,
|
||||
id = "al1",
|
||||
artistId = "ar1",
|
||||
name = "Album",
|
||||
albumArtist = "Artist",
|
||||
created = 86400,
|
||||
coverArt = null,
|
||||
genre = null,
|
||||
year = null,
|
||||
starred = null,
|
||||
songCount = 1,
|
||||
playCount = 3,
|
||||
played = 172800,
|
||||
),
|
||||
download = null,
|
||||
onDismiss = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val added = composeRule.onNodeWithText("Added").fetchSemanticsNode().boundsInRoot
|
||||
val lastPlayed = composeRule.onNodeWithText("Last played").fetchSemanticsNode().boundsInRoot
|
||||
val plays = composeRule.onNodeWithText("Plays").fetchSemanticsNode().boundsInRoot
|
||||
assertTrue("last played must follow added", lastPlayed.top >= added.bottom)
|
||||
assertTrue("plays must not sit between the dates", plays.top >= lastPlayed.bottom)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aPlaylistShowsOwnerSharingLengthAndDates() {
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
PlaylistInfoDialog(
|
||||
playlist =
|
||||
Playlist(
|
||||
sourceId = 1,
|
||||
id = "pl1",
|
||||
name = "Mix",
|
||||
comment = null,
|
||||
coverArt = null,
|
||||
songCount = 12,
|
||||
created = 1600000000,
|
||||
changed = 1700000000,
|
||||
duration = 3725,
|
||||
owner = "austin",
|
||||
shared = true,
|
||||
),
|
||||
onDismiss = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
composeRule.onNodeWithText("Owner").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("austin").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("Shared").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("Yes").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("12").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("1:02:05").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("Created").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("Updated").assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aSingleArtistTrackUsesSingularLabels() {
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
SongInfoDialog(
|
||||
song = song(artists = listOf(ArtistRef("ar1", "Alpha")), artistSort = "Beta"),
|
||||
download = null,
|
||||
localFile = null,
|
||||
streamEncoding = null,
|
||||
onDismiss = {},
|
||||
genres = emptyList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
composeRule.onNodeWithText("Artist").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("Artist sort").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("Artists").assertDoesNotExist()
|
||||
composeRule.onNodeWithText("Artists sort").assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aMixedArtistTrackUsesPluralLabelsForBothRows() {
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
SongInfoDialog(
|
||||
song =
|
||||
song(
|
||||
artists = listOf(ArtistRef("ar1", "Artist A"), ArtistRef("ar2", "Artist B")),
|
||||
artistSort = "Alpha",
|
||||
),
|
||||
download = null,
|
||||
localFile = null,
|
||||
streamEncoding = null,
|
||||
onDismiss = {},
|
||||
genres = emptyList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
composeRule.onNodeWithText("Artists").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("Artists sort").assertIsDisplayed()
|
||||
composeRule.onNodeWithText("Artist").assertDoesNotExist()
|
||||
composeRule.onNodeWithText("Artist sort").assertDoesNotExist()
|
||||
composeRule.onNodeWithText("Alpha").assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aTrackHidesATitleAndArtistSortThatMatchTheRegularNames() {
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
SongInfoDialog(
|
||||
song = song(artists = listOf(ArtistRef("ar1", "Artist")), sortName = "song", artistSort = "artist"),
|
||||
download = null,
|
||||
localFile = null,
|
||||
streamEncoding = null,
|
||||
onDismiss = {},
|
||||
genres = emptyList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
composeRule.onNodeWithText("Sort title").assertDoesNotExist()
|
||||
composeRule.onNodeWithText("Artist sort").assertDoesNotExist()
|
||||
}
|
||||
|
||||
private fun song(
|
||||
artists: List<ArtistRef>,
|
||||
sortName: String = "Song",
|
||||
artistSort: String = "Artist",
|
||||
) = Song(
|
||||
sourceId = 1,
|
||||
id = "s1",
|
||||
albumId = "al1",
|
||||
artistId = artists.first().id,
|
||||
title = "Song",
|
||||
album = "Album",
|
||||
artist = artists.first().name,
|
||||
duration = 200,
|
||||
track = 1,
|
||||
disc = 1,
|
||||
starred = null,
|
||||
artists = artists,
|
||||
sortName = sortName,
|
||||
artistSort = artistSort,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user