mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-09 16:11:20 +02:00
Fix some issues with restoring focus between pages (#613)
## Description Yet more focus issue fixes: - Restore focus when going back to home page from a later row - Don't jump to episode row when going back to series overview (such as from a person page) This PR also changes how backgrounding the app during playback works. Now the only goes back to the previous page when the app comes back to the foreground. This helps with focusing back on the page properly. There's also a bit more clean up performed.
This commit is contained in:
parent
26a913b05e
commit
3c11d4ba12
6 changed files with 35 additions and 31 deletions
|
|
@ -20,6 +20,10 @@ class PlaybackLifecycleObserver
|
|||
private var wasPlaying: Boolean? = null
|
||||
|
||||
override fun onStart(owner: LifecycleOwner) {
|
||||
val lastDest = navigationManager.backStack.lastOrNull()
|
||||
if (lastDest is Destination.Playback || lastDest is Destination.PlaybackList) {
|
||||
navigationManager.goBack()
|
||||
}
|
||||
wasPlaying = null
|
||||
}
|
||||
|
||||
|
|
@ -40,9 +44,6 @@ class PlaybackLifecycleObserver
|
|||
}
|
||||
|
||||
override fun onStop(owner: LifecycleOwner) {
|
||||
if (navigationManager.backStack.lastOrNull() is Destination.Playback) {
|
||||
navigationManager.goBack()
|
||||
}
|
||||
themeSongPlayer.stop()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||
import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.compose.LifecycleEventEffect
|
||||
import androidx.media3.common.Player
|
||||
import coil3.request.ErrorResult
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
|
|
@ -182,10 +180,10 @@ fun RequestOrRestoreFocus(
|
|||
debugKey?.let { Timber.v("RequestOrRestoreFocus: %s", it) }
|
||||
focusRequester.tryRequestFocus()
|
||||
}
|
||||
LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
|
||||
debugKey?.let { Timber.v("RequestOrRestoreFocus onResume: %s", it) }
|
||||
focusRequester.tryRequestFocus()
|
||||
}
|
||||
// LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
|
||||
// debugKey?.let { Timber.v("RequestOrRestoreFocus onResume: %s", it) }
|
||||
// focusRequester.tryRequestFocus()
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import androidx.lifecycle.map
|
|||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.ui.RequestOrRestoreFocus
|
||||
import com.github.damontecres.wholphin.ui.components.DialogParams
|
||||
import com.github.damontecres.wholphin.ui.components.DialogPopup
|
||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||
|
|
@ -37,7 +38,6 @@ import com.github.damontecres.wholphin.ui.detail.buildMoreDialogItems
|
|||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.ui.rememberInt
|
||||
import com.github.damontecres.wholphin.ui.seasonEpisode
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.serialization.Serializable
|
||||
|
|
@ -158,13 +158,15 @@ fun SeriesOverview(
|
|||
LoadingState.Success -> {
|
||||
series?.let { series ->
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
RequestOrRestoreFocus(
|
||||
when (rowFocused) {
|
||||
EPISODE_ROW -> episodeRowFocusRequester.tryRequestFocus()
|
||||
CAST_AND_CREW_ROW -> castCrewRowFocusRequester.tryRequestFocus()
|
||||
GUEST_STAR_ROW -> guestStarRowFocusRequester.tryRequestFocus()
|
||||
}
|
||||
}
|
||||
EPISODE_ROW -> episodeRowFocusRequester
|
||||
CAST_AND_CREW_ROW -> castCrewRowFocusRequester
|
||||
GUEST_STAR_ROW -> guestStarRowFocusRequester
|
||||
else -> episodeRowFocusRequester
|
||||
},
|
||||
"series_overview",
|
||||
)
|
||||
LifecycleStartEffect(destination.itemId) {
|
||||
viewModel.maybePlayThemeSong(
|
||||
destination.itemId,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ import com.github.damontecres.wholphin.data.model.BaseItem
|
|||
import com.github.damontecres.wholphin.data.model.Person
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.ui.AspectRatios
|
||||
import com.github.damontecres.wholphin.ui.RequestOrRestoreFocus
|
||||
import com.github.damontecres.wholphin.ui.cards.BannerCard
|
||||
import com.github.damontecres.wholphin.ui.cards.PersonRow
|
||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||
|
|
@ -182,7 +181,6 @@ fun SeriesOverviewContent(
|
|||
|
||||
is EpisodeList.Success -> {
|
||||
val state = rememberLazyListState(position.episodeRowIndex)
|
||||
RequestOrRestoreFocus(firstItemFocusRequester)
|
||||
|
||||
LazyRow(
|
||||
state = state,
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ fun HomePageContent(
|
|||
|
||||
val listState = rememberLazyListState()
|
||||
val rowFocusRequesters = remember(homeRows.size) { List(homeRows.size) { FocusRequester() } }
|
||||
var focused by remember { mutableStateOf(false) }
|
||||
var focused by rememberSaveable { mutableStateOf(false) }
|
||||
LaunchedEffect(homeRows) {
|
||||
if (!focused) {
|
||||
homeRows
|
||||
|
|
@ -246,6 +246,8 @@ fun HomePageContent(
|
|||
listState.animateScrollToItem(position.row)
|
||||
focused = true
|
||||
}
|
||||
} else {
|
||||
rowFocusRequesters.getOrNull(position.row)?.tryRequestFocus()
|
||||
}
|
||||
}
|
||||
LaunchedEffect(position) {
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ class PlaybackViewModel
|
|||
internal lateinit var item: BaseItem
|
||||
internal var forceTranscoding: Boolean = false
|
||||
private var activityListener: TrackActivityPlaybackListener? = null
|
||||
private val jobs = mutableListOf<Job>()
|
||||
|
||||
val nextUp = MutableLiveData<BaseItem?>()
|
||||
private var isPlaylist = false
|
||||
|
|
@ -166,20 +167,22 @@ class PlaybackViewModel
|
|||
val subtitleSearchLanguage = MutableLiveData<String>(Locale.current.language)
|
||||
|
||||
init {
|
||||
viewModelScope.launch(ExceptionHandler()) { controllerViewState.observe() }
|
||||
player.addListener(this)
|
||||
(player as? ExoPlayer)?.addAnalyticsListener(this)
|
||||
addCloseable { player.removeListener(this@PlaybackViewModel) }
|
||||
addCloseable { (player as? ExoPlayer)?.removeAnalyticsListener(this@PlaybackViewModel) }
|
||||
addCloseable {
|
||||
player.removeListener(this@PlaybackViewModel)
|
||||
(player as? ExoPlayer)?.removeAnalyticsListener(this@PlaybackViewModel)
|
||||
|
||||
this@PlaybackViewModel.activityListener?.let {
|
||||
it.release()
|
||||
player.removeListener(it)
|
||||
}
|
||||
jobs.forEach { it.cancel() }
|
||||
player.release()
|
||||
}
|
||||
addCloseable { player.release() }
|
||||
subscribe()
|
||||
listenForTranscodeReason()
|
||||
viewModelScope.launch(ExceptionHandler()) { controllerViewState.observe() }
|
||||
player.addListener(this)
|
||||
(player as? ExoPlayer)?.addAnalyticsListener(this)
|
||||
jobs.add(subscribe())
|
||||
jobs.add(listenForTranscodeReason())
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -874,7 +877,7 @@ class PlaybackViewModel
|
|||
}
|
||||
}
|
||||
|
||||
private fun listenForTranscodeReason() {
|
||||
private fun listenForTranscodeReason(): Job =
|
||||
viewModelScope.launchIO {
|
||||
currentPlayback.collectLatest {
|
||||
if (it != null) {
|
||||
|
|
@ -905,7 +908,6 @@ class PlaybackViewModel
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var lastInteractionDate: Date = Date()
|
||||
|
||||
|
|
@ -1026,11 +1028,13 @@ class PlaybackViewModel
|
|||
}
|
||||
|
||||
fun release() {
|
||||
Timber.v("release")
|
||||
activityListener?.release()
|
||||
player.release()
|
||||
activityListener = null
|
||||
}
|
||||
|
||||
fun subscribe() {
|
||||
fun subscribe(): Job =
|
||||
api.webSocket
|
||||
.subscribe<PlaystateMessage>()
|
||||
.onEach { message ->
|
||||
|
|
@ -1085,7 +1089,6 @@ class PlaybackViewModel
|
|||
}
|
||||
}
|
||||
}.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update [currentMediaInfo]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue