mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-29 00:10:32 +05:30
Merge pull request #4916 from Bnyro/master
fix: conflicts between chapters and video highlight
This commit is contained in:
commit
bc048e015b
@ -330,7 +330,10 @@ object PlayerHelper {
|
||||
)
|
||||
|
||||
fun shouldPlayNextVideo(isPlaylist: Boolean = false): Boolean {
|
||||
return autoPlayEnabled || (isPlaylist && PreferenceHelper.getBoolean(PreferenceKeys.AUTOPLAY_PLAYLISTS, false))
|
||||
return autoPlayEnabled || (isPlaylist && PreferenceHelper.getBoolean(
|
||||
PreferenceKeys.AUTOPLAY_PLAYLISTS,
|
||||
false
|
||||
))
|
||||
}
|
||||
|
||||
private val handleAudioFocus
|
||||
@ -442,7 +445,11 @@ object PlayerHelper {
|
||||
* Create a basic player, that is used for all types of playback situations inside the app
|
||||
*/
|
||||
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
||||
fun createPlayer(context: Context, trackSelector: DefaultTrackSelector, isBackgroundMode: Boolean): ExoPlayer {
|
||||
fun createPlayer(
|
||||
context: Context,
|
||||
trackSelector: DefaultTrackSelector,
|
||||
isBackgroundMode: Boolean
|
||||
): ExoPlayer {
|
||||
val cronetDataSourceFactory = CronetDataSource.Factory(
|
||||
CronetHelper.cronetEngine,
|
||||
Executors.newCachedThreadPool()
|
||||
@ -579,15 +586,16 @@ object PlayerHelper {
|
||||
fun getCurrentChapterIndex(currentPositionMs: Long, chapters: List<ChapterSegment>): Int? {
|
||||
val currentPositionSeconds = currentPositionMs / 1000
|
||||
return chapters
|
||||
.filter {
|
||||
it.highlightDrawable == null ||
|
||||
// remove the video highlight if it's already longer ago than [ChapterSegment.HIGHLIGHT_LENGTH],
|
||||
// otherwise the SponsorBlock highlight would be shown from its starting point to the end
|
||||
(currentPositionSeconds - it.start) < ChapterSegment.HIGHLIGHT_LENGTH
|
||||
}
|
||||
.sortedBy { it.start }
|
||||
.indexOfLast { currentPositionSeconds >= it.start }
|
||||
.takeIf { it >= 0 }
|
||||
?.takeIf { index ->
|
||||
val chapter = chapters[index]
|
||||
// remove the video highlight if it's already longer ago than [ChapterSegment.HIGHLIGHT_LENGTH],
|
||||
// otherwise the SponsorBlock highlight would be shown from its starting point to the end
|
||||
val isWithinMaxHighlightDuration = (currentPositionSeconds - chapter.start) < ChapterSegment.HIGHLIGHT_LENGTH
|
||||
chapter.highlightDrawable == null || isWithinMaxHighlightDuration
|
||||
}
|
||||
}
|
||||
|
||||
fun getPosition(videoId: String, duration: Long?): Long? {
|
||||
|
@ -13,7 +13,7 @@ import com.github.libretube.helpers.ThemeHelper
|
||||
import com.github.libretube.ui.viewholders.ChaptersViewHolder
|
||||
|
||||
class ChaptersAdapter(
|
||||
private val chapters: List<ChapterSegment>,
|
||||
var chapters: List<ChapterSegment>,
|
||||
private val videoDuration: Long,
|
||||
private val seekTo: (Long) -> Unit
|
||||
) : RecyclerView.Adapter<ChaptersViewHolder>() {
|
||||
|
@ -191,7 +191,7 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
|
||||
binding.chapters.setOnClickListener {
|
||||
val playerService = playerService ?: return@setOnClickListener
|
||||
viewModel.chapters = playerService.streams?.chapters.orEmpty().toMutableList()
|
||||
viewModel.chaptersLiveData.value = playerService.streams?.chapters.orEmpty()
|
||||
|
||||
ChaptersBottomSheet()
|
||||
.show(childFragmentManager)
|
||||
|
@ -15,6 +15,7 @@ import android.os.Looper
|
||||
import android.os.PowerManager
|
||||
import android.text.format.DateUtils
|
||||
import android.text.util.Linkify
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -44,11 +45,9 @@ import androidx.media3.common.MediaItem.SubtitleConfiguration
|
||||
import androidx.media3.common.MimeTypes
|
||||
import androidx.media3.common.PlaybackException
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.datasource.DefaultDataSource
|
||||
import androidx.media3.datasource.cronet.CronetDataSource
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.media3.exoplayer.hls.HlsMediaSource
|
||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
||||
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.github.libretube.R
|
||||
@ -90,7 +89,6 @@ import com.github.libretube.helpers.PlayerHelper.SPONSOR_HIGHLIGHT_CATEGORY
|
||||
import com.github.libretube.helpers.PlayerHelper.checkForSegments
|
||||
import com.github.libretube.helpers.PlayerHelper.getVideoStats
|
||||
import com.github.libretube.helpers.PlayerHelper.isInSegment
|
||||
import com.github.libretube.helpers.PlayerHelper.loadPlaybackParams
|
||||
import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.helpers.ProxyHelper
|
||||
import com.github.libretube.obj.PlayerNotificationData
|
||||
@ -922,7 +920,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
playerBinding.exoTitle.text = streams.title
|
||||
|
||||
// init the chapters recyclerview
|
||||
viewModel.chapters = streams.chapters.toMutableList()
|
||||
viewModel.chaptersLiveData.value = streams.chapters
|
||||
|
||||
// Listener for play and pause icon change
|
||||
exoPlayer.addListener(object : Player.Listener {
|
||||
@ -1212,16 +1210,18 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
|
||||
private suspend fun initializeHighlight(highlight: Segment) {
|
||||
val frameReceiver = OnlineTimeFrameReceiver(requireContext(), streams.previewFrames)
|
||||
val highlightStart = highlight.segmentStartAndEnd.first.toLong()
|
||||
val frame = withContext(Dispatchers.IO) {
|
||||
frameReceiver.getFrameAtTime(highlight.segmentStartAndEnd.first.toLong() * 1000)
|
||||
frameReceiver.getFrameAtTime(highlightStart * 1000)
|
||||
}
|
||||
val highlightChapter = ChapterSegment(
|
||||
title = getString(R.string.chapters_videoHighlight),
|
||||
start = highlight.segmentStartAndEnd.first.toLong(),
|
||||
start = highlightStart,
|
||||
highlightDrawable = frame?.toDrawable(requireContext().resources)
|
||||
)
|
||||
viewModel.chapters.add(highlightChapter)
|
||||
viewModel.chapters.sortBy { it.start }
|
||||
viewModel.chaptersLiveData.postValue(
|
||||
viewModel.chapters.plus(highlightChapter).sortedBy { it.start }
|
||||
)
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
setCurrentChapterName()
|
||||
|
@ -17,5 +17,7 @@ class PlayerViewModel : ViewModel() {
|
||||
|
||||
var maxSheetHeightPx = 0
|
||||
|
||||
var chapters: MutableList<ChapterSegment> = mutableListOf()
|
||||
val chaptersLiveData = MutableLiveData<List<ChapterSegment>>()
|
||||
|
||||
val chapters get() = chaptersLiveData.value.orEmpty()
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.github.libretube.ui.sheets
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
@ -10,7 +11,6 @@ import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.obj.ChapterSegment
|
||||
import com.github.libretube.databinding.BottomSheetBinding
|
||||
import com.github.libretube.helpers.PlayerHelper
|
||||
import com.github.libretube.ui.adapters.ChaptersAdapter
|
||||
@ -19,14 +19,9 @@ import com.github.libretube.ui.models.PlayerViewModel
|
||||
class ChaptersBottomSheet : UndimmedBottomSheet() {
|
||||
private var _binding: BottomSheetBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
private val playerViewModel: PlayerViewModel by activityViewModels()
|
||||
private lateinit var chapters: List<ChapterSegment>
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
chapters = playerViewModel.chapters
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
@ -37,11 +32,28 @@ class ChaptersBottomSheet : UndimmedBottomSheet() {
|
||||
return binding.root
|
||||
}
|
||||
|
||||
private val updatePosition = object : Runnable {
|
||||
override fun run() {
|
||||
val binding = _binding ?: return
|
||||
handler.postDelayed(this, 200)
|
||||
|
||||
val player = playerViewModel.player ?: return
|
||||
val currentIndex = PlayerHelper.getCurrentChapterIndex(
|
||||
player.currentPosition,
|
||||
playerViewModel.chapters
|
||||
) ?: return
|
||||
|
||||
val adapter = binding.optionsRecycler.adapter as ChaptersAdapter
|
||||
adapter.updateSelectedPosition(currentIndex)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.optionsRecycler.layoutManager = LinearLayoutManager(context)
|
||||
val adapter = ChaptersAdapter(chapters, playerViewModel.player?.duration ?: 0) {
|
||||
val adapter = ChaptersAdapter(playerViewModel.chapters, playerViewModel.player?.duration ?: 0) {
|
||||
playerViewModel.player?.seekTo(it)
|
||||
}
|
||||
binding.optionsRecycler.adapter = adapter
|
||||
@ -49,17 +61,11 @@ class ChaptersBottomSheet : UndimmedBottomSheet() {
|
||||
binding.bottomSheetTitle.text = context?.getString(R.string.chapters)
|
||||
binding.bottomSheetTitleLayout.isVisible = true
|
||||
|
||||
val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
val updatePosition = object : Runnable {
|
||||
override fun run() {
|
||||
if (_binding == null) return
|
||||
handler.postDelayed(this, 200)
|
||||
val player = playerViewModel.player ?: return
|
||||
val currentIndex = PlayerHelper.getCurrentChapterIndex(player.currentPosition, chapters) ?: return
|
||||
adapter.updateSelectedPosition(currentIndex)
|
||||
}
|
||||
playerViewModel.chaptersLiveData.observe(viewLifecycleOwner) {
|
||||
adapter.chapters = it
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
updatePosition.run()
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user