Fix some UI preference changes not being reflected immediately (#1146)

This commit is contained in:
Ray 2026-03-25 21:55:00 -04:00 committed by GitHub
parent 2d863e9c32
commit c92de3c33e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 50 additions and 14 deletions

View file

@ -12,6 +12,7 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -45,6 +46,7 @@ fun MainContent(
screensaverService: ScreensaverService,
modifier: Modifier = Modifier,
) {
val preferences by rememberUpdatedState(UserPreferences(appPreferences))
Surface(
modifier =
modifier
@ -93,10 +95,6 @@ fun MainContent(
backdropService.clearBackdrop()
}
val current = key.current
val preferences =
remember(appPreferences) {
UserPreferences(appPreferences)
}
var showContent by remember {
mutableStateOf(true)
}

View file

@ -38,6 +38,8 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.acra.ACRA
@ -434,3 +436,8 @@ fun Response<BaseItemDtoQueryResult>.toBaseItems(
fun Int?.gt(that: Int) = (this ?: 0) > that
fun Int?.lt(that: Int) = (this ?: 0) < that
/**
* Easy way to combine two flows into a [Pair]
*/
fun <T1, T2> Flow<T1>.combinePair(flow: Flow<T2>): Flow<Pair<T1, T2>> = combine(flow) { t1, t2 -> Pair(t1, t2) }

View file

@ -11,6 +11,7 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.relocation.BringIntoViewRequester
import androidx.compose.foundation.relocation.bringIntoViewRequester
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
@ -85,6 +86,7 @@ fun EpisodeDetails(
var showPlaylistDialog by remember { mutableStateOf<Optional<UUID>>(Optional.absent()) }
var showDeleteDialog by remember { mutableStateOf<BaseItem?>(null) }
val playlistState by playlistViewModel.playlistState.observeAsState(PlaylistLoadingState.Pending)
val canDelete by viewModel.canDelete.collectAsState()
val preferredSubtitleLanguage =
viewModel.serverRepository.currentUserDto
@ -226,7 +228,7 @@ fun EpisodeDetails(
onClearChosenStreams = {
viewModel.clearChosenStreams(chosenStreams)
},
canDelete = viewModel.canDelete,
canDelete = canDelete,
),
)
},
@ -236,7 +238,7 @@ fun EpisodeDetails(
favoriteOnClick = {
viewModel.setFavorite(ep.id, !ep.favorite)
},
canDelete = viewModel.canDelete,
canDelete = canDelete,
deleteOnClick = { showDeleteDialog = ep },
modifier = modifier,
)

View file

@ -3,6 +3,7 @@ package com.github.damontecres.wholphin.ui.detail.episode
import android.content.Context
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asFlow
import androidx.lifecycle.viewModelScope
import com.github.damontecres.wholphin.data.ChosenStreams
import com.github.damontecres.wholphin.data.ItemPlaybackRepository
@ -19,6 +20,8 @@ import com.github.damontecres.wholphin.services.StreamChoiceService
import com.github.damontecres.wholphin.services.ThemeSongPlayer
import com.github.damontecres.wholphin.services.UserPreferencesService
import com.github.damontecres.wholphin.services.deleteItem
import com.github.damontecres.wholphin.ui.combinePair
import com.github.damontecres.wholphin.ui.launchDefault
import com.github.damontecres.wholphin.ui.launchIO
import com.github.damontecres.wholphin.ui.nav.Destination
import com.github.damontecres.wholphin.ui.setValueOnMain
@ -34,6 +37,11 @@ import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jellyfin.sdk.api.client.ApiClient
@ -68,11 +76,19 @@ class EpisodeViewModel
val item = MutableLiveData<BaseItem?>(null)
val chosenStreams = MutableLiveData<ChosenStreams?>(null)
var canDelete: Boolean = false
private set
val canDelete = MutableStateFlow(false)
init {
init()
viewModelScope.launchDefault {
item
.asFlow()
.filterNotNull()
.combinePair(userPreferencesService.flow.map { it.appPreferences })
.collectLatest { (item, preferences) ->
canDelete.update { mediaManagementService.canDelete(item, preferences) }
}
}
}
private fun fetchAndSetItem(): Deferred<BaseItem> =
@ -101,7 +117,6 @@ class EpisodeViewModel
) {
val prefs = userPreferencesService.getCurrent()
val item = fetchAndSetItem().await()
canDelete = mediaManagementService.canDelete(item)
val result = itemPlaybackRepository.getSelectedTracks(item.id, item, prefs)
withContext(Dispatchers.Main) {
this@EpisodeViewModel.item.value = item

View file

@ -106,6 +106,7 @@ fun MovieDetails(
val loading by viewModel.loading.observeAsState(LoadingState.Loading)
val chosenStreams by viewModel.chosenStreams.observeAsState(null)
val discovered by viewModel.discovered.collectAsState()
val canDelete by viewModel.canDelete.collectAsState()
var overviewDialog by remember { mutableStateOf<ItemDetailsDialogInfo?>(null) }
var moreDialog by remember { mutableStateOf<DialogParams?>(null) }
@ -211,7 +212,7 @@ fun MovieDetails(
seriesId = null,
sourceId = chosenStreams?.source?.id?.toUUIDOrNull(),
canClearChosenStreams = chosenStreams?.itemPlayback != null || chosenStreams?.plc != null,
canDelete = viewModel.canDelete,
canDelete = canDelete,
actions = moreActions,
onChooseVersion = {
chooseVersion =
@ -323,7 +324,7 @@ fun MovieDetails(
onClickDiscover = { index, item ->
viewModel.navigateTo(item.destination)
},
canDelete = viewModel.canDelete,
canDelete = canDelete,
deleteOnClick = { showDeleteDialog = movie },
modifier = modifier,
)

View file

@ -3,6 +3,7 @@ package com.github.damontecres.wholphin.ui.detail.movie
import android.content.Context
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asFlow
import androidx.lifecycle.viewModelScope
import com.github.damontecres.wholphin.data.ChosenStreams
import com.github.damontecres.wholphin.data.ExtrasItem
@ -29,6 +30,8 @@ import com.github.damontecres.wholphin.services.TrailerService
import com.github.damontecres.wholphin.services.UserPreferencesService
import com.github.damontecres.wholphin.services.deleteItem
import com.github.damontecres.wholphin.ui.SlimItemFields
import com.github.damontecres.wholphin.ui.combinePair
import com.github.damontecres.wholphin.ui.launchDefault
import com.github.damontecres.wholphin.ui.launchIO
import com.github.damontecres.wholphin.ui.letNotEmpty
import com.github.damontecres.wholphin.ui.nav.Destination
@ -46,6 +49,9 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -93,11 +99,19 @@ class MovieViewModel
val chosenStreams = MutableLiveData<ChosenStreams?>(null)
val discovered = MutableStateFlow<List<DiscoverItem>>(listOf())
var canDelete: Boolean = false
private set
val canDelete = MutableStateFlow(false)
init {
init()
viewModelScope.launchDefault {
item
.asFlow()
.filterNotNull()
.combinePair(userPreferencesService.flow.map { it.appPreferences })
.collectLatest { (item, preferences) ->
canDelete.update { mediaManagementService.canDelete(item, preferences) }
}
}
}
private fun fetchAndSetItem(): Deferred<BaseItem> =
@ -112,7 +126,6 @@ class MovieViewModel
api.userLibraryApi.getItem(itemId).content.let {
BaseItem.from(it, api)
}
canDelete = mediaManagementService.canDelete(item)
this@MovieViewModel.item.setValueOnMain(item)
item
}