From 5e2c75bb700450ec12eeed6bc745a58c8e31df0c Mon Sep 17 00:00:00 2001 From: damontecres <154766448+damontecres@users.noreply.github.com> Date: Tue, 11 Nov 2025 20:10:16 -0500 Subject: [PATCH] Log while navigating around the app (#195) Just adds some logging while navigating around the app. If an error or crash occurs and users want to share their logs, this information is useful to know what page. Logs are never sent without explicit user content and they are only shared with the Jellyfin server the app is currently connected to. [See here for more details](https://github.com/damontecres/Wholphin/wiki/Gathering-app-logs#privacy) Also stops theme music when the app is paused similar to #191 --- .../github/damontecres/wholphin/ui/Extensions.kt | 10 ++++++++++ .../wholphin/ui/detail/CollectionFolderLiveTv.kt | 2 ++ .../wholphin/ui/detail/CollectionFolderMovie.kt | 2 ++ .../wholphin/ui/detail/CollectionFolderTv.kt | 2 ++ .../damontecres/wholphin/ui/detail/FavoritesPage.kt | 2 ++ .../ui/detail/series/SeriesOverviewContent.kt | 5 +++++ .../wholphin/ui/nav/ApplicationContent.kt | 2 -- .../wholphin/ui/nav/NavigationManager.kt | 13 +++++++++++++ .../wholphin/util/PlaybackLifecycleObserver.kt | 3 +++ .../damontecres/wholphin/util/ThemeSongPlayer.kt | 2 +- 10 files changed, 40 insertions(+), 3 deletions(-) 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 e8f6071f..b137b439 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 @@ -38,6 +38,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.acra.ACRA import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.extensions.ticks import timber.log.Timber @@ -380,3 +381,12 @@ fun equalsNotNull( a: Any?, b: Any?, ) = a != null && b != null && a == b + +fun logTab( + name: String, + tabIndex: Int, +) { + val info = "$tabIndex, $name" + Timber.i("Current tab: $info") + ACRA.errorReporter.putCustomData("tabInfo", info) +} diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderLiveTv.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderLiveTv.kt index 66dd2779..fdf369f2 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderLiveTv.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderLiveTv.kt @@ -38,6 +38,7 @@ import com.github.damontecres.wholphin.ui.data.VideoSortOptions import com.github.damontecres.wholphin.ui.detail.livetv.DvrSchedule import com.github.damontecres.wholphin.ui.detail.livetv.TvGuideGrid import com.github.damontecres.wholphin.ui.launchIO +import com.github.damontecres.wholphin.ui.logTab import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.nav.NavigationManager import com.github.damontecres.wholphin.ui.setValueOnMain @@ -102,6 +103,7 @@ fun CollectionFolderLiveTv( LaunchedEffect(Unit) { firstTabFocusRequester.tryRequestFocus() } LaunchedEffect(selectedTabIndex) { + logTab("livetv", selectedTabIndex) viewModel.saveRememberedTab(preferences, destination.itemId, selectedTabIndex) } val onClickItem = { item: BaseItem -> diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderMovie.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderMovie.kt index 7cef5122..5c156e28 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderMovie.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderMovie.kt @@ -33,6 +33,7 @@ import com.github.damontecres.wholphin.ui.components.RecommendedMovie import com.github.damontecres.wholphin.ui.components.TabRow import com.github.damontecres.wholphin.ui.data.MovieSortOptions import com.github.damontecres.wholphin.ui.data.VideoSortOptions +import com.github.damontecres.wholphin.ui.logTab import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel import com.github.damontecres.wholphin.ui.tryRequestFocus @@ -62,6 +63,7 @@ fun CollectionFolderMovie( LaunchedEffect(Unit) { firstTabFocusRequester.tryRequestFocus() } LaunchedEffect(selectedTabIndex) { + logTab("movie", selectedTabIndex) preferencesViewModel.saveRememberedTab(preferences, destination.itemId, selectedTabIndex) } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderTv.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderTv.kt index 8155fbc5..3170a0af 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderTv.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/CollectionFolderTv.kt @@ -32,6 +32,7 @@ import com.github.damontecres.wholphin.ui.components.GenreCardGrid import com.github.damontecres.wholphin.ui.components.RecommendedTvShow import com.github.damontecres.wholphin.ui.components.TabRow import com.github.damontecres.wholphin.ui.data.SeriesSortOptions +import com.github.damontecres.wholphin.ui.logTab import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel import com.github.damontecres.wholphin.ui.tryRequestFocus @@ -60,6 +61,7 @@ fun CollectionFolderTv( LaunchedEffect(Unit) { firstTabFocusRequester.tryRequestFocus() } LaunchedEffect(selectedTabIndex) { + logTab("tv", selectedTabIndex) preferencesViewModel.saveRememberedTab(preferences, destination.itemId, selectedTabIndex) } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/FavoritesPage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/FavoritesPage.kt index 002ca4ef..bae04bcb 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/FavoritesPage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/FavoritesPage.kt @@ -32,6 +32,7 @@ import com.github.damontecres.wholphin.ui.components.TabRow import com.github.damontecres.wholphin.ui.data.EpisodeSortOptions import com.github.damontecres.wholphin.ui.data.MovieSortOptions import com.github.damontecres.wholphin.ui.data.SeriesSortOptions +import com.github.damontecres.wholphin.ui.logTab import com.github.damontecres.wholphin.ui.nav.NavDrawerItem import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel import com.github.damontecres.wholphin.ui.tryRequestFocus @@ -63,6 +64,7 @@ fun FavoritesPage( val focusRequester = remember { FocusRequester() } LaunchedEffect(selectedTabIndex) { + logTab("favorites", selectedTabIndex) preferencesViewModel.saveRememberedTab( preferences, NavDrawerItem.Favorites.id, 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 ce73e872..cc326b24 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 @@ -16,6 +16,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.relocation.BringIntoViewRequester import androidx.compose.foundation.relocation.bringIntoViewRequester import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.key import androidx.compose.runtime.mutableIntStateOf @@ -50,6 +51,7 @@ import com.github.damontecres.wholphin.ui.components.LoadingPage import com.github.damontecres.wholphin.ui.components.TabRow import com.github.damontecres.wholphin.ui.ifElse import com.github.damontecres.wholphin.ui.isNotNullOrBlank +import com.github.damontecres.wholphin.ui.logTab import com.github.damontecres.wholphin.ui.tryRequestFocus import com.github.damontecres.wholphin.util.formatDateTime import kotlin.time.Duration @@ -77,6 +79,9 @@ fun SeriesOverviewContent( ) { val bringIntoViewRequester = remember { BringIntoViewRequester() } var selectedTabIndex by rememberSaveable(position) { mutableIntStateOf(position.seasonTabIndex) } + LaunchedEffect(selectedTabIndex) { + logTab("series_overview", selectedTabIndex) + } val tabRowFocusRequester = remember { FocusRequester() } val focusedEpisode = diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/nav/ApplicationContent.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/nav/ApplicationContent.kt index 14476e70..e1aff5ae 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/nav/ApplicationContent.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/nav/ApplicationContent.kt @@ -11,7 +11,6 @@ import com.github.damontecres.wholphin.data.model.JellyfinServer import com.github.damontecres.wholphin.data.model.JellyfinUser import com.github.damontecres.wholphin.preferences.UserPreferences import org.jellyfin.sdk.model.api.DeviceProfile -import timber.log.Timber /** * This is generally the root composable of the of the app @@ -38,7 +37,6 @@ fun ApplicationContent( entryProvider = { key -> key as Destination val contentKey = "${key}_${server?.id}_${user?.id}" - Timber.d("Navigate: %s", key) NavEntry(key, contentKey = contentKey) { if (key.fullScreen) { DestinationContent( diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/nav/NavigationManager.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/nav/NavigationManager.kt index c41fd16e..8a9b50a3 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/nav/NavigationManager.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/nav/NavigationManager.kt @@ -1,6 +1,8 @@ package com.github.damontecres.wholphin.ui.nav import androidx.navigation3.runtime.NavKey +import org.acra.ACRA +import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @@ -18,6 +20,7 @@ class NavigationManager */ fun navigateTo(destination: Destination) { backStack.add(destination) + log() } /** @@ -26,6 +29,7 @@ class NavigationManager fun navigateToFromDrawer(destination: Destination) { goToHome() backStack.add(destination) + log() } /** @@ -33,6 +37,7 @@ class NavigationManager */ fun goBack() { backStack.removeLastOrNull() + log() } /** @@ -45,6 +50,7 @@ class NavigationManager if (backStack[0] !is Destination.Home) { backStack[0] = Destination.Home() } + log() } /** @@ -54,5 +60,12 @@ class NavigationManager goToHome() val id = (backStack[0] as Destination.Home).id + 1 backStack[0] = Destination.Home(id) + log() + } + + private fun log() { + val dest = backStack.lastOrNull().toString() + Timber.i("Current Destination: %s", dest) + ACRA.errorReporter.putCustomData("destination", dest) } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/util/PlaybackLifecycleObserver.kt b/app/src/main/java/com/github/damontecres/wholphin/util/PlaybackLifecycleObserver.kt index fcc49917..be93c292 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/util/PlaybackLifecycleObserver.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/util/PlaybackLifecycleObserver.kt @@ -16,6 +16,7 @@ class PlaybackLifecycleObserver constructor( private val navigationManager: NavigationManager, private val playerFactory: PlayerFactory, + private val themeSongPlayer: ThemeSongPlayer, ) : DefaultLifecycleObserver { private var wasPlaying: Boolean? = null @@ -36,11 +37,13 @@ class PlaybackLifecycleObserver wasPlaying = it.isPlaying it.pause() } + themeSongPlayer.stop() } 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/util/ThemeSongPlayer.kt b/app/src/main/java/com/github/damontecres/wholphin/util/ThemeSongPlayer.kt index 1327b6f2..bb9ec887 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/util/ThemeSongPlayer.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/util/ThemeSongPlayer.kt @@ -78,7 +78,6 @@ class ThemeSongPlayer volumeLevel: ThemeSongVolume, url: String, ) { - stop() val volumeLevel = when (volumeLevel) { ThemeSongVolume.UNRECOGNIZED, @@ -92,6 +91,7 @@ class ThemeSongPlayer ThemeSongVolume.HIGHEST -> 75f } player.apply { + stop() volume = volumeLevel setMediaItem(MediaItem.fromUri(url)) prepare()