fix(web): Zurück-Knopf tat oft nichts + Besitzer geteilter Playlists (2.6)
navigate() ließ den Stack-Eintrag weg, wenn sich die Ansicht nicht geändert hatte, rief history.pushState aber trotzdem. Zweimal auf denselben Tab geklickt = zwei Browser-Einträge auf dieselbe Ansicht, jeder davon ein Zurück-Druck ohne sichtbare Wirkung. Im Test: 3x "Alben" -> 3 Browser-Einträge bei 1 Stack-Eintrag, danach bewegten 4 Zurück- Drücke die Ansicht einmal. Jetzt pusht nur eine wirklich neue Ansicht, sonst replaceState. Vorwärts mitgetestet, unverändert. Playlists: Navidrome liefert owner mit, das Web nutzte es nie. Übersicht und Detail zeigen "· von <Name>", nur bei fremden Listen. Android zeigte ihn bisher bei jeder Liste und unbeschriftet; beide Plattformen jetzt gleich, Bibliotheks-Übersicht ebenfalls. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ea448e109f
commit
568bb5002c
8 files changed
+85
-14
No files matched your search
@@ -14,8 +14,8 @@ android {
|
||||
applicationId = "com.novasonic.app"
|
||||
minSdk = 26
|
||||
targetSdk = 35
|
||||
versionCode = 11
|
||||
versionName = "1.8"
|
||||
versionCode = 12
|
||||
versionName = "1.9"
|
||||
// Host der eigenen NovaSonic-Web-App — Ziel der geteilten Links. Einmal in
|
||||
// gradle.properties setzen (novasonicHost=music.example.com); ohne Angabe bleibt der
|
||||
// Platzhalter stehen und der App-Link greift schlicht nicht.
|
||||
|
||||
@@ -327,9 +327,11 @@ fun LibraryScreen(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
items(state.playlists, key = { it.id }) { pl ->
|
||||
// Besitzer nur bei fremden (geteilten) Listen — bei den eigenen waere er Rauschen.
|
||||
val von = pl.owner?.takeIf { it.isNotBlank() && it != state.currentUser }
|
||||
PlaylistCard(
|
||||
name = pl.name,
|
||||
subtitle = "${pl.songCount} Titel",
|
||||
subtitle = "${pl.songCount} Titel" + (von?.let { " · von $it" } ?: ""),
|
||||
coverUrl = coverUrl(pl.coverArt),
|
||||
downloaded = pl.id in downloadedPlaylistIds,
|
||||
onClick = { onPlaylistClick(pl) },
|
||||
|
||||
@@ -174,9 +174,11 @@ fun PlaylistDetailScreen(
|
||||
fontSize = 26.sp, color = Color.White,
|
||||
maxLines = 2, overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
// Der Besitzer stand hier bisher bei JEDER Liste, auch bei den eigenen, und ohne
|
||||
// Beschriftung — bei einer geteilten Liste ist genau das die interessante Angabe.
|
||||
val meta = listOfNotNull(
|
||||
pl.owner?.takeIf { it.isNotBlank() },
|
||||
if (pl.songCount > 0) "${pl.songCount} Songs" else null,
|
||||
pl.owner?.takeIf { it.isNotBlank() && it != state.currentUser }?.let { "von $it" },
|
||||
).joinToString(" · ")
|
||||
if (meta.isNotBlank()) {
|
||||
Spacer(Modifier.height(4.dp))
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.novasonic.app.api.model.Playlist
|
||||
import com.novasonic.app.app
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -25,6 +26,8 @@ data class LibraryUiState(
|
||||
val albumSort: AlbumSort = AlbumSort.NEWEST,
|
||||
val artistIndexes: List<ArtistIndex> = emptyList(),
|
||||
val playlists: List<Playlist> = emptyList(),
|
||||
/** Angemeldeter Nutzer — der Besitzer wird nur bei FREMDEN Playlists angezeigt. */
|
||||
val currentUser: String = "",
|
||||
val isLoading: Boolean = false,
|
||||
val error: String? = null,
|
||||
)
|
||||
@@ -42,7 +45,13 @@ class LibraryViewModel(app: Application) : AndroidViewModel(app) {
|
||||
val albumsGridState = LazyGridState()
|
||||
val artistsListState = LazyListState()
|
||||
|
||||
init { loadPlaylists() }
|
||||
init {
|
||||
loadPlaylists()
|
||||
viewModelScope.launch {
|
||||
val u = runCatching { repo.credentialsFlow().first().username }.getOrDefault("")
|
||||
_state.value = _state.value.copy(currentUser = u)
|
||||
}
|
||||
}
|
||||
|
||||
fun setAlbumSort(sort: AlbumSort) {
|
||||
if (sort == _state.value.albumSort) return
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.novasonic.app.offline.DownloadState
|
||||
import com.novasonic.app.offline.GroupType
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
@@ -22,6 +23,8 @@ data class PlaylistUiState(
|
||||
val isSaving: Boolean = false,
|
||||
val deleted: Boolean = false,
|
||||
val error: String? = null,
|
||||
/** Angemeldeter Nutzer — der Besitzer wird nur bei FREMDEN Playlists angezeigt. */
|
||||
val currentUser: String = "",
|
||||
)
|
||||
|
||||
class PlaylistViewModel(app: Application, savedState: SavedStateHandle) : AndroidViewModel(app) {
|
||||
@@ -42,7 +45,13 @@ class PlaylistViewModel(app: Application, savedState: SavedStateHandle) : Androi
|
||||
.map { tracks -> tracks.any { it.state == DownloadState.QUEUED || it.state == DownloadState.DOWNLOADING } }
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), false)
|
||||
|
||||
init { load() }
|
||||
init {
|
||||
load()
|
||||
viewModelScope.launch {
|
||||
val u = runCatching { repo.credentialsFlow().first().username }.getOrDefault("")
|
||||
_state.value = _state.value.copy(currentUser = u)
|
||||
}
|
||||
}
|
||||
|
||||
fun load() {
|
||||
val id = playlistId
|
||||
|
||||
Reference in new issue
Block a user