mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Fix focus issues & add clear image cache option
This commit is contained in:
parent
370cd2c146
commit
4113f990b2
8 changed files with 50 additions and 22 deletions
|
|
@ -439,6 +439,13 @@ sealed interface AppPreference<T> {
|
|||
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,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ fun FocusedEpisodeHeader(
|
|||
Text(
|
||||
text = dto.episodeTitle ?: dto.name ?: "",
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier,
|
||||
)
|
||||
Row(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -74,5 +74,6 @@
|
|||
<string name="update_url_summary">URL used to check for app updates</string>
|
||||
<string name="updates">Updates</string>
|
||||
<string name="no_update_available">No update available</string>
|
||||
<string name="clear_image_cache">Clear image cache</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue