mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-21 20:27:06 +03:00
Implement quality sheet
This commit is contained in:
parent
f01083e647
commit
ec099e51cf
7 changed files with 126 additions and 22 deletions
|
@ -889,7 +889,7 @@ class PlayerActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun setVideoList(
|
||||
fun setVideoList(
|
||||
qualityIndex: Int,
|
||||
videos: List<Video>?,
|
||||
fromStart: Boolean = false,
|
||||
|
@ -900,7 +900,7 @@ class PlayerActivity : BaseActivity() {
|
|||
if (videos == null) return
|
||||
|
||||
videos.getOrNull(qualityIndex)?.let {
|
||||
viewModel.selectVideo(qualityIndex)
|
||||
viewModel.setVideoIndex(qualityIndex)
|
||||
setHttpOptions(it)
|
||||
if (viewModel.isLoadingEpisode.value) {
|
||||
viewModel.currentEpisode.value?.let { episode ->
|
||||
|
@ -940,7 +940,7 @@ class PlayerActivity : BaseActivity() {
|
|||
|
||||
private fun setHttpOptions(video: Video) {
|
||||
if (viewModel.isEpisodeOnline() != true) return
|
||||
val source = viewModel.currentSource as AnimeHttpSource
|
||||
val source = viewModel.currentSource.value as? AnimeHttpSource ?: return
|
||||
|
||||
val headers = (video.headers ?: source.headers)
|
||||
.toMultimap()
|
||||
|
|
|
@ -92,6 +92,7 @@ enum class Sheets {
|
|||
PlaybackSpeed,
|
||||
SubtitleTracks,
|
||||
AudioTracks,
|
||||
QualityTracks,
|
||||
Chapters,
|
||||
Decoders,
|
||||
More,
|
||||
|
|
|
@ -227,6 +227,17 @@ class PlayerViewModel @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun isEpisodeOnline(): Boolean? {
|
||||
val anime = currentAnime.value ?: return null
|
||||
val episode = currentEpisode.value ?: return null
|
||||
val source = currentSource.value ?: return null
|
||||
return source is AnimeHttpSource &&
|
||||
!EpisodeLoader.isDownload(
|
||||
episode.toDomainEpisode()!!,
|
||||
anime,
|
||||
)
|
||||
}
|
||||
|
||||
fun updateIsLoadingEpisode(value: Boolean) {
|
||||
_isLoadingEpisode.update { _ -> value }
|
||||
}
|
||||
|
@ -353,10 +364,21 @@ class PlayerViewModel @JvmOverloads constructor(
|
|||
_videoList.update { _ -> videoList }
|
||||
}
|
||||
|
||||
fun selectVideo(idx: Int) {
|
||||
fun setVideoIndex(idx: Int) {
|
||||
_selectedVideoIndex.update { _ -> idx }
|
||||
}
|
||||
|
||||
fun selectVideo(video: Video) {
|
||||
val idx = videoList.value.indexOf(video)
|
||||
|
||||
activity.setVideoList(
|
||||
qualityIndex = idx,
|
||||
videos = videoList.value,
|
||||
)
|
||||
|
||||
sheetShown.update { _ -> Sheets.None }
|
||||
}
|
||||
|
||||
fun addAudio(uri: Uri) {
|
||||
val url = uri.toString()
|
||||
val path = if (url.startsWith("content://")) {
|
||||
|
@ -885,16 +907,6 @@ class PlayerViewModel @JvmOverloads constructor(
|
|||
hasTrackers = tracks.isNotEmpty()
|
||||
}
|
||||
|
||||
fun isEpisodeOnline(): Boolean? {
|
||||
val anime = currentAnime.value ?: return null
|
||||
val episode = currentEpisode.value ?: return null
|
||||
return currentSource is AnimeHttpSource &&
|
||||
!EpisodeLoader.isDownload(
|
||||
episode.toDomainEpisode()!!,
|
||||
anime,
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun loadEpisode(episodeId: Long?): Pair<List<Video>?, String>? {
|
||||
val anime = currentAnime.value ?: return null
|
||||
val source = sourceManager.getOrStub(anime.source)
|
||||
|
|
|
@ -476,7 +476,8 @@ fun PlayerControls(
|
|||
onSubtitlesLongClick = { onOpenPanel(Panels.SubtitleSettings) },
|
||||
onAudioClick = { onOpenSheet(Sheets.AudioTracks) },
|
||||
onAudioLongClick = { onOpenPanel(Panels.AudioDelay) },
|
||||
onQualityClick = {},
|
||||
onQualityClick = { onOpenSheet(Sheets.QualityTracks) },
|
||||
isEpisodeOnline = viewModel.isEpisodeOnline(),
|
||||
onMoreClick = { onOpenSheet(Sheets.More) },
|
||||
onMoreLongClick = { onOpenPanel(Panels.VideoFilters) },
|
||||
)
|
||||
|
@ -562,6 +563,8 @@ fun PlayerControls(
|
|||
val selectedSubtitles by viewModel.selectedSubtitles.collectAsState()
|
||||
val audioTracks by viewModel.audioTracks.collectAsState()
|
||||
val selectedAudio by viewModel.selectedAudio.collectAsState()
|
||||
val videoList by viewModel.videoList.collectAsState()
|
||||
val selectedVideoIndex by viewModel.selectedVideoIndex.collectAsState()
|
||||
val decoder by viewModel.currentDecoder.collectAsState()
|
||||
val speed by viewModel.playbackSpeed.collectAsState()
|
||||
val sleepTimerTimeRemaining by viewModel.remainingTime.collectAsState()
|
||||
|
@ -578,6 +581,11 @@ fun PlayerControls(
|
|||
selectedAudio = selectedAudio,
|
||||
onAddAudio = viewModel::addAudio,
|
||||
onSelectAudio = viewModel::selectAudio,
|
||||
|
||||
videoList = videoList.toImmutableList(),
|
||||
currentVideo = videoList.getOrNull(selectedVideoIndex),
|
||||
onSelectVideo = { viewModel.selectVideo(it) },
|
||||
|
||||
chapter = currentChapter,
|
||||
chapters = viewModel.chapters.toImmutableList(),
|
||||
onSeekToChapter = {
|
||||
|
|
|
@ -5,7 +5,7 @@ import androidx.activity.compose.rememberLauncherForActivityResult
|
|||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.runtime.Composable
|
||||
import dev.vivvvek.seeker.Segment
|
||||
import eu.kanade.tachiyomi.animesource.model.Track
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.ui.player.Decoder
|
||||
import eu.kanade.tachiyomi.ui.player.Panels
|
||||
import eu.kanade.tachiyomi.ui.player.PlayerViewModel.VideoTrack
|
||||
|
@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.ui.player.controls.components.sheets.ChaptersSheet
|
|||
import eu.kanade.tachiyomi.ui.player.controls.components.sheets.DecodersSheet
|
||||
import eu.kanade.tachiyomi.ui.player.controls.components.sheets.MoreSheet
|
||||
import eu.kanade.tachiyomi.ui.player.controls.components.sheets.PlaybackSpeedSheet
|
||||
import eu.kanade.tachiyomi.ui.player.controls.components.sheets.QualitySheet
|
||||
import eu.kanade.tachiyomi.ui.player.controls.components.sheets.SubtitlesSheet
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
@ -35,6 +36,11 @@ fun PlayerSheets(
|
|||
onAddAudio: (Uri) -> Unit,
|
||||
onSelectAudio: (Int) -> Unit,
|
||||
|
||||
// video sheet
|
||||
videoList: ImmutableList<Video>,
|
||||
currentVideo: Video?,
|
||||
onSelectVideo: (Video) -> Unit,
|
||||
|
||||
// chapters sheet
|
||||
chapter: Segment?,
|
||||
chapters: ImmutableList<Segment>,
|
||||
|
@ -94,6 +100,16 @@ fun PlayerSheets(
|
|||
)
|
||||
}
|
||||
|
||||
Sheets.QualityTracks -> {
|
||||
if (videoList.isEmpty()) return
|
||||
QualitySheet(
|
||||
videoList = videoList,
|
||||
currentVideo = currentVideo,
|
||||
onClick = onSelectVideo,
|
||||
onDismissRequest = onDismissRequest,
|
||||
)
|
||||
}
|
||||
|
||||
Sheets.Chapters -> {
|
||||
if (chapter == null) return
|
||||
ChaptersSheet(
|
||||
|
|
|
@ -39,6 +39,7 @@ fun TopRightPlayerControls(
|
|||
|
||||
// video
|
||||
onQualityClick: () -> Unit,
|
||||
isEpisodeOnline: Boolean?,
|
||||
|
||||
// more
|
||||
onMoreClick: () -> Unit,
|
||||
|
@ -70,12 +71,14 @@ fun TopRightPlayerControls(
|
|||
onLongClick = onAudioLongClick,
|
||||
horizontalSpacing = MaterialTheme.MPVKtSpacing.small,
|
||||
)
|
||||
ControlsButton(
|
||||
Icons.Default.HighQuality,
|
||||
onClick = onQualityClick,
|
||||
onLongClick = onQualityClick,
|
||||
horizontalSpacing = MaterialTheme.MPVKtSpacing.small,
|
||||
)
|
||||
if (isEpisodeOnline == true) {
|
||||
ControlsButton(
|
||||
Icons.Default.HighQuality,
|
||||
onClick = onQualityClick,
|
||||
onLongClick = onQualityClick,
|
||||
horizontalSpacing = MaterialTheme.MPVKtSpacing.small,
|
||||
)
|
||||
}
|
||||
ControlsButton(
|
||||
Icons.Default.MoreVert,
|
||||
onClick = onMoreClick,
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package eu.kanade.tachiyomi.ui.player.controls.components.sheets
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import tachiyomi.presentation.core.components.material.MPVKtSpacing
|
||||
|
||||
@Composable
|
||||
fun QualitySheet(
|
||||
videoList: ImmutableList<Video>,
|
||||
currentVideo: Video?,
|
||||
onClick: (Video) -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
GenericTracksSheet(
|
||||
videoList,
|
||||
track = {
|
||||
VideoTrack(
|
||||
it,
|
||||
selected = currentVideo == it,
|
||||
onClick = { onClick(it) },
|
||||
)
|
||||
},
|
||||
onDismissRequest = onDismissRequest,
|
||||
modifier = modifier
|
||||
.padding(vertical = MaterialTheme.MPVKtSpacing.medium),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun VideoTrack(
|
||||
video: Video,
|
||||
selected: Boolean,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Text(
|
||||
text = video.quality,
|
||||
fontStyle = if (selected) FontStyle.Italic else FontStyle.Normal,
|
||||
fontWeight = if (selected) FontWeight.ExtraBold else FontWeight.Normal,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = if (selected) MaterialTheme.colorScheme.primary else Color.Unspecified,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onClick)
|
||||
.padding(
|
||||
vertical = MaterialTheme.MPVKtSpacing.smaller,
|
||||
horizontal = MaterialTheme.MPVKtSpacing.medium,
|
||||
),
|
||||
)
|
||||
}
|
Loading…
Reference in a new issue