diff --git a/app/src/main/java/com/github/damontecres/wholphin/services/PlaybackLifecycleObserver.kt b/app/src/main/java/com/github/damontecres/wholphin/services/PlaybackLifecycleObserver.kt index 86906280..3c32a497 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/services/PlaybackLifecycleObserver.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/services/PlaybackLifecycleObserver.kt @@ -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() } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/Extensions.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/Extensions.kt index 4eba1b32..31754ef9 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/Extensions.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/Extensions.kt @@ -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() +// } } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/series/SeriesOverview.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/series/SeriesOverview.kt index 9377aa1d..b5d4ea4b 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/series/SeriesOverview.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/series/SeriesOverview.kt @@ -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, diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/series/SeriesOverviewContent.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/series/SeriesOverviewContent.kt index 75d8344b..1495285d 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/series/SeriesOverviewContent.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/series/SeriesOverviewContent.kt @@ -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, diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt index 31a4ecf0..6cc69dcd 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomePage.kt @@ -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) { diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt index 39cee993..064434c4 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt @@ -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() val nextUp = MutableLiveData() private var isPlaylist = false @@ -166,20 +167,22 @@ class PlaybackViewModel val subtitleSearchLanguage = MutableLiveData(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() .onEach { message -> @@ -1085,7 +1089,6 @@ class PlaybackViewModel } } }.launchIn(viewModelScope) - } /** * Atomically update [currentMediaInfo]