diff --git a/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreference.kt b/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreference.kt index 912e31d9..7ac87673 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreference.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/preferences/AppPreference.kt @@ -439,6 +439,13 @@ sealed interface AppPreference { indexToValue = { SkipSegmentBehavior.forNumber(it) }, valueToIndex = { it.number }, ) + + val ClearImageCache = + AppClickablePreference( + title = R.string.clear_image_cache, + getter = { }, + setter = { prefs, _ -> prefs }, + ) } } @@ -513,6 +520,7 @@ val advancedPreferences = title = R.string.more, preferences = listOf( + AppPreference.ClearImageCache, AppPreference.OssLicenseInfo, ), ), diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/components/PlayButtons.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/components/PlayButtons.kt index 6d816c6d..7b5e0b4d 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/components/PlayButtons.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/components/PlayButtons.kt @@ -15,7 +15,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusState -import androidx.compose.ui.focus.focusProperties import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRestorer import androidx.compose.ui.focus.onFocusChanged @@ -29,7 +28,6 @@ import androidx.tv.material3.Text import com.github.damontecres.dolphin.R import com.github.damontecres.dolphin.ui.PreviewTvSpec import com.github.damontecres.dolphin.ui.theme.DolphinTheme -import com.github.damontecres.dolphin.ui.tryRequestFocus import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds @@ -139,14 +137,10 @@ fun ExpandablePlayButtons( modifier = modifier .focusGroup() - .focusProperties { - onEnter = { - firstFocus.tryRequestFocus() - } - }, + .focusRestorer(firstFocus), ) { if (resumePosition > Duration.ZERO) { - item { + item("play") { ExpandablePlayButton( R.string.resume, resumePosition, @@ -157,7 +151,7 @@ fun ExpandablePlayButtons( .focusRequester(firstFocus), ) } - item { + item("restart") { ExpandablePlayButton( R.string.restart, Duration.ZERO, @@ -168,7 +162,7 @@ fun ExpandablePlayButtons( ) } } else { - item { + item("play") { ExpandablePlayButton( R.string.play, Duration.ZERO, @@ -182,7 +176,7 @@ fun ExpandablePlayButtons( } // Watched button - item { + item("watched") { ExpandableFaButton( title = if (watched) R.string.mark_unwatched else R.string.mark_watched, iconStringRes = if (watched) R.string.fa_eye else R.string.fa_eye_slash, @@ -192,7 +186,7 @@ fun ExpandablePlayButtons( } // More button - item { + item("more") { ExpandablePlayButton( R.string.more, Duration.ZERO, diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt index 1e6de9a1..be1212ab 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/FocusedEpisodeHeader.kt @@ -50,6 +50,8 @@ fun FocusedEpisodeHeader( Text( text = dto.episodeTitle ?: dto.name ?: "", style = MaterialTheme.typography.headlineSmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis, modifier = Modifier, ) Row( diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/SeriesOverviewContent.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/SeriesOverviewContent.kt index 6da98e3c..3a48d6fd 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/SeriesOverviewContent.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/series/SeriesOverviewContent.kt @@ -16,7 +16,6 @@ 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 @@ -34,6 +33,7 @@ import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Tab @@ -77,8 +77,6 @@ fun SeriesOverviewContent( val tabRowFocusRequester = remember { FocusRequester() } val focusedEpisode = episodes.getOrNull(position.episodeRowIndex) - LaunchedEffect(position) { - } Box( modifier = @@ -184,6 +182,8 @@ fun SeriesOverviewContent( Text( text = it, style = MaterialTheme.typography.headlineMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis, modifier = Modifier, ) } diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/main/HomePage.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/main/HomePage.kt index 9b7608f6..a0310d9d 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/main/HomePage.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/main/HomePage.kt @@ -249,12 +249,16 @@ fun MainPageHeader( Text( text = title, style = MaterialTheme.typography.headlineMedium.copy(fontWeight = FontWeight.SemiBold), + maxLines = 1, + overflow = TextOverflow.Ellipsis, ) } subtitle?.let { Text( text = subtitle, style = MaterialTheme.typography.headlineSmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis, ) } if (details.isNotEmpty()) { diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackViewModel.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackViewModel.kt index 8df90178..763b4a28 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackViewModel.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/playback/PlaybackViewModel.kt @@ -280,10 +280,11 @@ class PlaybackViewModel Timber.i("No change in playback for changeStreams") return } + // TODO if the new audio or subtitle index is already in the streams (eg direct play), should toggle in the player instead val maxBitrate = preferences.appPreferences.playbackPreferences.maxBitrate .takeIf { it > 0 } ?: AppPreference.DEFAULT_BITRATE - val response = + val response by api.mediaInfoApi .getPostedPlaybackInfo( itemId, @@ -302,7 +303,7 @@ class PlaybackViewModel alwaysBurnInSubtitleWhenTranscoding = null, maxStreamingBitrate = maxBitrate.toInt(), ), - ).content + ) val source = response.mediaSources.firstOrNull() source?.let { source -> val mediaUrl = @@ -335,8 +336,8 @@ class PlaybackViewModel ?.let { it.deliveryUrl?.let { deliveryUrl -> var flags = 0 - if (it.isForced) flags = flags.and(C.SELECTION_FLAG_FORCED) - if (it.isDefault) flags = flags.and(C.SELECTION_FLAG_DEFAULT) + if (it.isForced) flags = flags.or(C.SELECTION_FLAG_FORCED) + if (it.isDefault) flags = flags.or(C.SELECTION_FLAG_DEFAULT) MediaItem.SubtitleConfiguration .Builder( api.createUrl(deliveryUrl).toUri(), @@ -368,6 +369,7 @@ class PlaybackViewModel ) withContext(Dispatchers.Main) { + // TODO, don't need to release & recreate when switching streams this@PlaybackViewModel.activityListener?.let { it.release() player.removeListener(it) @@ -389,7 +391,7 @@ class PlaybackViewModel positionMs, ) if (audioIndex != null || subtitleIndex != null) { - val trackActivationListener = + val onTracksChangedListener = object : Player.Listener { override fun onTracksChanged(tracks: Tracks) { Timber.v("onTracksChanged: $tracks") @@ -408,7 +410,7 @@ class PlaybackViewModel } } } - player.addListener(trackActivationListener) + player.addListener(onTracksChangedListener) } } val trickPlayInfo = @@ -416,7 +418,7 @@ class PlaybackViewModel ?.get(source.id) ?.values ?.firstOrNull() - Timber.v("Trickplay info: $trickPlayInfo") +// Timber.v("Trickplay info: $trickPlayInfo") withContext(Dispatchers.Main) { trickplay.value = trickPlayInfo } diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/preferences/PreferencesContent.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/preferences/PreferencesContent.kt index f7fa5bc7..013b5a85 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/preferences/PreferencesContent.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/preferences/PreferencesContent.kt @@ -39,6 +39,7 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.tv.material3.MaterialTheme import androidx.tv.material3.Text import androidx.tv.material3.surfaceColorAtElevation +import coil3.SingletonImageLoader import com.github.damontecres.dolphin.R import com.github.damontecres.dolphin.preferences.AppPreference import com.github.damontecres.dolphin.preferences.AppPreferences @@ -245,6 +246,22 @@ fun PreferencesContent( ) } + AppPreference.ClearImageCache -> { + ClickPreference( + title = stringResource(pref.title), + onClick = { + SingletonImageLoader.get(context).let { + it.memoryCache?.clear() + it.diskCache?.clear() + } + }, + modifier = Modifier, + summary = null, + onLongClick = {}, + interactionSource = interactionSource, + ) + } + else -> { val value = pref.getter.invoke(preferences) ComposablePreference( diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index adfa8142..afad58ef 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -74,5 +74,6 @@ URL used to check for app updates Updates No update available + Clear image cache