mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-13 13:50:30 +05:30
fix: chapters dont work in audio mode
This commit is contained in:
parent
f3049b5118
commit
596230aa61
@ -45,6 +45,7 @@ import com.github.libretube.obj.PlayerNotificationData
|
||||
import com.github.libretube.ui.base.BaseActivity
|
||||
import com.github.libretube.ui.interfaces.TimeFrameReceiver
|
||||
import com.github.libretube.ui.listeners.SeekbarPreviewListener
|
||||
import com.github.libretube.ui.models.ChaptersViewModel
|
||||
import com.github.libretube.ui.models.PlayerViewModel
|
||||
import com.github.libretube.util.NowPlayingNotification
|
||||
import com.github.libretube.util.OfflineTimeFrameReceiver
|
||||
@ -66,6 +67,7 @@ class OfflinePlayerActivity : BaseActivity() {
|
||||
|
||||
private lateinit var playerBinding: ExoStyledPlayerControlViewBinding
|
||||
private val playerViewModel: PlayerViewModel by viewModels()
|
||||
private val chaptersViewModel: ChaptersViewModel by viewModels()
|
||||
|
||||
private val watchPositionTimer = PauseableTimer(
|
||||
onTick = this::saveWatchPosition,
|
||||
@ -177,7 +179,8 @@ class OfflinePlayerActivity : BaseActivity() {
|
||||
|
||||
binding.player.initialize(
|
||||
binding.doubleTapOverlay.binding,
|
||||
binding.playerGestureControlsView.binding
|
||||
binding.playerGestureControlsView.binding,
|
||||
chaptersViewModel
|
||||
)
|
||||
|
||||
nowPlayingNotification = NowPlayingNotification(this, player, NowPlayingNotification.Companion.NowPlayingNotificationType.VIDEO_OFFLINE)
|
||||
@ -189,7 +192,7 @@ class OfflinePlayerActivity : BaseActivity() {
|
||||
Database.downloadDao().findById(videoId)
|
||||
}
|
||||
val chapters = downloadChapters.map(DownloadChapter::toChapterSegment)
|
||||
playerViewModel.chaptersLiveData.value = chapters
|
||||
chaptersViewModel.chaptersLiveData.value = chapters
|
||||
binding.player.setChapters(chapters)
|
||||
|
||||
val downloadFiles = downloadItems.filter { it.path.exists() }
|
||||
|
@ -14,7 +14,7 @@ import com.github.libretube.ui.viewholders.ChaptersViewHolder
|
||||
|
||||
class ChaptersAdapter(
|
||||
var chapters: List<ChapterSegment>,
|
||||
private val videoDuration: Long,
|
||||
private val videoDurationSeconds: Long,
|
||||
private val seekTo: (Long) -> Unit
|
||||
) : RecyclerView.Adapter<ChaptersViewHolder>() {
|
||||
private var selectedPosition = 0
|
||||
@ -36,12 +36,11 @@ class ChaptersAdapter(
|
||||
chapterTitle.text = chapter.title
|
||||
timeStamp.text = DateUtils.formatElapsedTime(chapter.start)
|
||||
|
||||
val playerDurationSeconds = videoDuration / 1000
|
||||
val chapterEnd = if (chapter.highlightDrawable == null) {
|
||||
chapters.getOrNull(position + 1)?.start ?: playerDurationSeconds
|
||||
chapters.getOrNull(position + 1)?.start ?: videoDurationSeconds
|
||||
} else {
|
||||
// the duration for chapters is hardcoded, since it's not provided by the SB API
|
||||
minOf(chapter.start + ChapterSegment.HIGHLIGHT_LENGTH, playerDurationSeconds)
|
||||
minOf(chapter.start + ChapterSegment.HIGHLIGHT_LENGTH, videoDurationSeconds)
|
||||
}
|
||||
val durationSpan = chapterEnd - chapter.start
|
||||
duration.text = root.context.getString(
|
||||
|
@ -31,6 +31,7 @@ import com.github.libretube.extensions.normalize
|
||||
import com.github.libretube.extensions.seekBy
|
||||
import com.github.libretube.extensions.toID
|
||||
import com.github.libretube.extensions.togglePlayPauseState
|
||||
import com.github.libretube.extensions.updateIfChanged
|
||||
import com.github.libretube.helpers.AudioHelper
|
||||
import com.github.libretube.helpers.BackgroundHelper
|
||||
import com.github.libretube.helpers.ImageHelper
|
||||
@ -42,6 +43,7 @@ import com.github.libretube.services.OnlinePlayerService
|
||||
import com.github.libretube.ui.activities.MainActivity
|
||||
import com.github.libretube.ui.interfaces.AudioPlayerOptions
|
||||
import com.github.libretube.ui.listeners.AudioPlayerThumbnailListener
|
||||
import com.github.libretube.ui.models.ChaptersViewModel
|
||||
import com.github.libretube.ui.models.PlayerViewModel
|
||||
import com.github.libretube.ui.sheets.ChaptersBottomSheet
|
||||
import com.github.libretube.ui.sheets.PlaybackOptionsSheet
|
||||
@ -61,6 +63,7 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
private lateinit var audioHelper: AudioHelper
|
||||
private val mainActivity get() = context as MainActivity
|
||||
private val viewModel: PlayerViewModel by activityViewModels()
|
||||
private val chaptersModel: ChaptersViewModel by activityViewModels()
|
||||
|
||||
// for the transition
|
||||
private var transitionStartId = 0
|
||||
@ -167,12 +170,24 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
)
|
||||
}
|
||||
|
||||
requireActivity().supportFragmentManager.setFragmentResultListener(
|
||||
ChaptersBottomSheet.SEEK_TO_POSITION_REQUEST_KEY,
|
||||
viewLifecycleOwner
|
||||
) { _, bundle ->
|
||||
playerService?.player?.seekTo(bundle.getLong(IntentData.currentPosition))
|
||||
}
|
||||
|
||||
binding.openChapters.setOnClickListener {
|
||||
val playerService = playerService ?: return@setOnClickListener
|
||||
viewModel.chaptersLiveData.value = playerService.streams?.chapters.orEmpty()
|
||||
chaptersModel.chaptersLiveData.value = playerService.streams?.chapters.orEmpty()
|
||||
|
||||
ChaptersBottomSheet()
|
||||
.show(childFragmentManager)
|
||||
.apply {
|
||||
arguments = bundleOf(
|
||||
IntentData.duration to playerService.player?.duration?.div(1000)
|
||||
)
|
||||
}
|
||||
.show(requireActivity().supportFragmentManager)
|
||||
}
|
||||
|
||||
binding.miniPlayerClose.setOnClickListener {
|
||||
@ -205,6 +220,8 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
}
|
||||
|
||||
if (!PlayerHelper.playAutomatically) updatePlayPauseButton()
|
||||
|
||||
updateChapterIndex()
|
||||
}
|
||||
|
||||
private fun killFragment() {
|
||||
@ -435,4 +452,14 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
|
||||
binding.volumeTextView.text = "${bar.progress.normalize(0, bar.max, 0, 100)}"
|
||||
}
|
||||
|
||||
private fun updateChapterIndex() {
|
||||
if (_binding == null) return
|
||||
handler.postDelayed(this::updateChapterIndex, 100)
|
||||
|
||||
val player = playerService?.player ?: return
|
||||
|
||||
val currentIndex = PlayerHelper.getCurrentChapterIndex(player.currentPosition, chaptersModel.chapters)
|
||||
chaptersModel.currentChapterIndex.updateIfChanged(currentIndex ?: return)
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +97,7 @@ import com.github.libretube.ui.extensions.animateDown
|
||||
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
||||
import com.github.libretube.ui.interfaces.OnlinePlayerOptions
|
||||
import com.github.libretube.ui.listeners.SeekbarPreviewListener
|
||||
import com.github.libretube.ui.models.ChaptersViewModel
|
||||
import com.github.libretube.ui.models.CommentsViewModel
|
||||
import com.github.libretube.ui.models.PlayerViewModel
|
||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||
@ -127,6 +128,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
|
||||
private val viewModel: PlayerViewModel by activityViewModels()
|
||||
private val commentsViewModel: CommentsViewModel by activityViewModels()
|
||||
private val chaptersViewModel: ChaptersViewModel by activityViewModels()
|
||||
|
||||
// Video information passed by the intent
|
||||
private lateinit var videoId: String
|
||||
@ -467,6 +469,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
}
|
||||
(activity as MainActivity).requestOrientationChange()
|
||||
}
|
||||
|
||||
updateMaxSheetHeight()
|
||||
}
|
||||
})
|
||||
|
||||
@ -634,7 +638,9 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
}
|
||||
|
||||
private fun updateMaxSheetHeight() {
|
||||
viewModel.maxSheetHeightPx = binding.root.height - binding.player.height
|
||||
val maxHeight = binding.root.height - binding.player.height
|
||||
viewModel.maxSheetHeightPx = viewModel.maxSheetHeightPx
|
||||
chaptersViewModel.maxSheetHeightPx = maxHeight
|
||||
}
|
||||
|
||||
private fun playOnBackground() {
|
||||
@ -1022,7 +1028,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun initializePlayerView() {
|
||||
// initialize the player view actions
|
||||
binding.player.initialize(doubleTapOverlayBinding, playerGestureControlsViewBinding)
|
||||
binding.player.initialize(doubleTapOverlayBinding, playerGestureControlsViewBinding, chaptersViewModel)
|
||||
binding.player.initPlayerOptions(viewModel, viewLifecycleOwner, trackSelector, this)
|
||||
|
||||
binding.descriptionLayout.setStreams(streams)
|
||||
@ -1040,7 +1046,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
playerBinding.exoTitle.text = streams.title
|
||||
|
||||
// init the chapters recyclerview
|
||||
viewModel.chaptersLiveData.value = streams.chapters
|
||||
chaptersViewModel.chaptersLiveData.value = streams.chapters
|
||||
|
||||
if (PlayerHelper.relatedStreamsEnabled) {
|
||||
val relatedLayoutManager = binding.relatedRecView.layoutManager as LinearLayoutManager
|
||||
@ -1132,8 +1138,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
start = highlightStart,
|
||||
highlightDrawable = frame?.toDrawable(requireContext().resources)
|
||||
)
|
||||
viewModel.chaptersLiveData.postValue(
|
||||
viewModel.chapters.plus(highlightChapter).sortedBy { it.start }
|
||||
chaptersViewModel.chaptersLiveData.postValue(
|
||||
chaptersViewModel.chapters.plus(highlightChapter).sortedBy { it.start }
|
||||
)
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.github.libretube.ui.models
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.github.libretube.api.obj.ChapterSegment
|
||||
|
||||
class ChaptersViewModel: ViewModel() {
|
||||
val chaptersLiveData = MutableLiveData<List<ChapterSegment>>()
|
||||
val chapters get() = chaptersLiveData.value.orEmpty()
|
||||
val currentChapterIndex = MutableLiveData<Int>()
|
||||
var maxSheetHeightPx = 0
|
||||
}
|
@ -10,7 +10,6 @@ import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.JsonHelper
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
import com.github.libretube.api.obj.ChapterSegment
|
||||
import com.github.libretube.api.obj.Message
|
||||
import com.github.libretube.api.obj.Segment
|
||||
import com.github.libretube.api.obj.Streams
|
||||
@ -48,9 +47,6 @@ class PlayerViewModel : ViewModel() {
|
||||
|
||||
var maxSheetHeightPx = 0
|
||||
|
||||
val chaptersLiveData = MutableLiveData<List<ChapterSegment>>()
|
||||
|
||||
val chapters get() = chaptersLiveData.value.orEmpty()
|
||||
var sponsorBlockEnabled = PlayerHelper.sponsorBlockEnabled
|
||||
|
||||
/**
|
||||
|
@ -2,29 +2,32 @@ package com.github.libretube.ui.sheets
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewTreeObserver
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.constants.IntentData
|
||||
import com.github.libretube.databinding.BottomSheetBinding
|
||||
import com.github.libretube.helpers.PlayerHelper
|
||||
import com.github.libretube.ui.adapters.ChaptersAdapter
|
||||
import com.github.libretube.ui.models.PlayerViewModel
|
||||
import com.github.libretube.ui.models.ChaptersViewModel
|
||||
|
||||
@UnstableApi
|
||||
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 val chaptersViewModel: ChaptersViewModel by activityViewModels()
|
||||
private var duration = 0L
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
duration = requireArguments().getLong(IntentData.duration, 0L)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
@ -35,61 +38,45 @@ class ChaptersBottomSheet : UndimmedBottomSheet() {
|
||||
return binding.root
|
||||
}
|
||||
|
||||
private val updatePosition = object : Runnable {
|
||||
override fun run() {
|
||||
val binding = _binding ?: return
|
||||
handler.postDelayed(this, 200)
|
||||
|
||||
val currentIndex = getCurrentIndex() ?: 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(playerViewModel.chapters, playerViewModel.player?.duration ?: 0) {
|
||||
playerViewModel.player?.seekTo(it)
|
||||
ChaptersAdapter(chaptersViewModel.chapters, duration) {
|
||||
setFragmentResult(SEEK_TO_POSITION_REQUEST_KEY, bundleOf(IntentData.currentPosition to it))
|
||||
}
|
||||
binding.optionsRecycler.adapter = adapter
|
||||
|
||||
binding.optionsRecycler.viewTreeObserver.addOnGlobalLayoutListener(
|
||||
object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
val currentIndex = getCurrentIndex() ?: return
|
||||
binding.optionsRecycler.scrollToPosition(currentIndex)
|
||||
chaptersViewModel.currentChapterIndex.value?.let {
|
||||
binding.optionsRecycler.scrollToPosition(it)
|
||||
}
|
||||
|
||||
binding.optionsRecycler.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
chaptersViewModel.currentChapterIndex.observe(viewLifecycleOwner) { currentIndex ->
|
||||
if (_binding == null) return@observe
|
||||
|
||||
adapter.updateSelectedPosition(currentIndex)
|
||||
}
|
||||
|
||||
binding.bottomSheetTitle.text = context?.getString(R.string.chapters)
|
||||
binding.bottomSheetTitleLayout.isVisible = true
|
||||
|
||||
playerViewModel.chaptersLiveData.observe(viewLifecycleOwner) {
|
||||
chaptersViewModel.chaptersLiveData.observe(viewLifecycleOwner) {
|
||||
adapter.chapters = it
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
updatePosition.run()
|
||||
}
|
||||
|
||||
private fun getCurrentIndex(): Int? {
|
||||
val player = playerViewModel.player ?: return null
|
||||
|
||||
return PlayerHelper.getCurrentChapterIndex(
|
||||
player.currentPosition,
|
||||
playerViewModel.chapters
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSheetMaxHeightPx() = playerViewModel.maxSheetHeightPx
|
||||
override fun getSheetMaxHeightPx() = chaptersViewModel.maxSheetHeightPx
|
||||
|
||||
override fun getDragHandle() = binding.dragHandle
|
||||
|
||||
@ -99,4 +86,8 @@ class ChaptersBottomSheet : UndimmedBottomSheet() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SEEK_TO_POSITION_REQUEST_KEY = "seek_to_position_request_key"
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.TooltipCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.os.postDelayed
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.isGone
|
||||
@ -26,6 +27,7 @@ import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.marginStart
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.text.Cue
|
||||
@ -36,7 +38,7 @@ import androidx.media3.ui.PlayerView
|
||||
import androidx.media3.ui.SubtitleView
|
||||
import androidx.media3.ui.TimeBar
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.obj.ChapterSegment
|
||||
import com.github.libretube.constants.IntentData
|
||||
import com.github.libretube.constants.PreferenceKeys
|
||||
import com.github.libretube.databinding.DoubleTapOverlayBinding
|
||||
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
|
||||
@ -46,6 +48,7 @@ import com.github.libretube.extensions.normalize
|
||||
import com.github.libretube.extensions.round
|
||||
import com.github.libretube.extensions.seekBy
|
||||
import com.github.libretube.extensions.togglePlayPauseState
|
||||
import com.github.libretube.extensions.updateIfChanged
|
||||
import com.github.libretube.helpers.AudioHelper
|
||||
import com.github.libretube.helpers.BrightnessHelper
|
||||
import com.github.libretube.helpers.ContextHelper
|
||||
@ -59,6 +62,7 @@ import com.github.libretube.ui.fragments.PlayerFragment
|
||||
import com.github.libretube.ui.interfaces.PlayerGestureOptions
|
||||
import com.github.libretube.ui.interfaces.PlayerOptions
|
||||
import com.github.libretube.ui.listeners.PlayerGestureController
|
||||
import com.github.libretube.ui.models.ChaptersViewModel
|
||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||
import com.github.libretube.ui.sheets.ChaptersBottomSheet
|
||||
import com.github.libretube.ui.sheets.PlaybackOptionsSheet
|
||||
@ -81,6 +85,7 @@ abstract class CustomExoPlayerView(
|
||||
private lateinit var playerGestureController: PlayerGestureController
|
||||
private lateinit var brightnessHelper: BrightnessHelper
|
||||
private lateinit var audioHelper: AudioHelper
|
||||
private lateinit var chaptersViewModel: ChaptersViewModel
|
||||
private var doubleTapOverlayBinding: DoubleTapOverlayBinding? = null
|
||||
private var chaptersBottomSheet: ChaptersBottomSheet? = null
|
||||
private var scrubbingTimeBar = false
|
||||
@ -114,10 +119,12 @@ abstract class CustomExoPlayerView(
|
||||
|
||||
fun initialize(
|
||||
doubleTapOverlayBinding: DoubleTapOverlayBinding,
|
||||
playerGestureControlsViewBinding: PlayerGestureControlsViewBinding
|
||||
playerGestureControlsViewBinding: PlayerGestureControlsViewBinding,
|
||||
chaptersViewModel: ChaptersViewModel
|
||||
) {
|
||||
this.doubleTapOverlayBinding = doubleTapOverlayBinding
|
||||
this.gestureViewBinding = playerGestureControlsViewBinding
|
||||
this.chaptersViewModel = chaptersViewModel
|
||||
this.playerGestureController = PlayerGestureController(context as BaseActivity, this)
|
||||
this.brightnessHelper = BrightnessHelper(context as Activity)
|
||||
this.audioHelper = AudioHelper(context)
|
||||
@ -216,11 +223,24 @@ abstract class CustomExoPlayerView(
|
||||
|
||||
updateCurrentPosition()
|
||||
|
||||
activity.supportFragmentManager.setFragmentResultListener(
|
||||
ChaptersBottomSheet.SEEK_TO_POSITION_REQUEST_KEY,
|
||||
findViewTreeLifecycleOwner() ?: activity
|
||||
) { _, bundle ->
|
||||
player?.seekTo(bundle.getLong(IntentData.currentPosition))
|
||||
}
|
||||
|
||||
// enable the chapters dialog in the player
|
||||
binding.chapterName.setOnClickListener {
|
||||
val sheet = chaptersBottomSheet ?: ChaptersBottomSheet().also {
|
||||
chaptersBottomSheet = it
|
||||
}
|
||||
val sheet = chaptersBottomSheet ?: ChaptersBottomSheet()
|
||||
.apply {
|
||||
arguments = bundleOf(
|
||||
IntentData.duration to player?.duration?.div(1000)
|
||||
)
|
||||
}
|
||||
.also {
|
||||
chaptersBottomSheet = it
|
||||
}
|
||||
|
||||
if (sheet.isVisible) {
|
||||
sheet.dismiss()
|
||||
@ -231,9 +251,9 @@ abstract class CustomExoPlayerView(
|
||||
}
|
||||
|
||||
// set the name of the video chapter in the exoPlayerView
|
||||
fun setCurrentChapterName(forceUpdate: Boolean = false, enqueueNew: Boolean = true) {
|
||||
val player = player ?: return
|
||||
val chapters = getChapters()
|
||||
fun setCurrentChapterName(forceUpdate: Boolean = false, enqueueNew: Boolean = true) {
|
||||
val player = player ?: return
|
||||
val chapters = chaptersViewModel.chapters
|
||||
|
||||
binding.chapterName.isInvisible = chapters.isEmpty()
|
||||
|
||||
@ -246,10 +266,9 @@ abstract class CustomExoPlayerView(
|
||||
// if the user is scrubbing the time bar, don't update
|
||||
if (scrubbingTimeBar && !forceUpdate) return
|
||||
|
||||
val newChapterName =
|
||||
PlayerHelper.getCurrentChapterIndex(player.currentPosition, chapters)
|
||||
?.let { chapters[it].title.trim() }
|
||||
?: context.getString(R.string.no_chapter)
|
||||
val currentIndex = PlayerHelper.getCurrentChapterIndex(player.currentPosition, chapters)
|
||||
val newChapterName = currentIndex?.let { chapters[it].title.trim() } ?: context.getString(R.string.no_chapter)
|
||||
chaptersViewModel.currentChapterIndex.updateIfChanged(currentIndex ?: return)
|
||||
|
||||
// change the chapter name textView text to the chapterName
|
||||
if (newChapterName != binding.chapterName.text) {
|
||||
@ -627,8 +646,10 @@ abstract class CustomExoPlayerView(
|
||||
if (!activity.hasCutout && binding.topBar.marginStart == LANDSCAPE_MARGIN_HORIZONTAL_NONE) return
|
||||
|
||||
// add a margin to the top and the bottom bar in landscape mode for notches
|
||||
val isForcedPortrait = activity.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
||||
val horizontalMargin = if (isFullscreen() && !isForcedPortrait) LANDSCAPE_MARGIN_HORIZONTAL else LANDSCAPE_MARGIN_HORIZONTAL_NONE
|
||||
val isForcedPortrait =
|
||||
activity.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
||||
val horizontalMargin =
|
||||
if (isFullscreen() && !isForcedPortrait) LANDSCAPE_MARGIN_HORIZONTAL else LANDSCAPE_MARGIN_HORIZONTAL_NONE
|
||||
|
||||
listOf(binding.topBar, binding.bottomBar).forEach {
|
||||
it.updateLayoutParams<MarginLayoutParams> {
|
||||
@ -784,23 +805,29 @@ abstract class CustomExoPlayerView(
|
||||
KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
|
||||
player?.togglePlayPauseState()
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD -> {
|
||||
forward()
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_MEDIA_REWIND -> {
|
||||
rewind()
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_N, KeyEvent.KEYCODE_NAVIGATE_NEXT -> {
|
||||
PlayingQueue.navigateNext()
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_NAVIGATE_PREVIOUS -> {
|
||||
PlayingQueue.navigatePrev()
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_F -> {
|
||||
val fragmentManager = ContextHelper.unwrapActivity(context).supportFragmentManager
|
||||
fragmentManager.fragments.filterIsInstance<PlayerFragment>().firstOrNull()
|
||||
?.toggleFullscreen()
|
||||
}
|
||||
|
||||
else -> return false
|
||||
}
|
||||
|
||||
@ -826,8 +853,6 @@ abstract class CustomExoPlayerView(
|
||||
|
||||
open fun minimizeOrExitPlayer() = Unit
|
||||
|
||||
abstract fun getChapters(): List<ChapterSegment>
|
||||
|
||||
open fun getWindow(): Window = activity.window
|
||||
|
||||
companion object {
|
||||
|
@ -31,6 +31,4 @@ class OfflinePlayerView(
|
||||
this.chapters = chapters
|
||||
setCurrentChapterName()
|
||||
}
|
||||
|
||||
override fun getChapters(): List<ChapterSegment> = chapters
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import androidx.media3.common.Player
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.trackselection.TrackSelector
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.obj.ChapterSegment
|
||||
import com.github.libretube.constants.IntentData
|
||||
import com.github.libretube.constants.PreferenceKeys
|
||||
import com.github.libretube.extensions.toID
|
||||
@ -281,10 +280,6 @@ class OnlinePlayerView(
|
||||
playerOptions?.exitFullscreen()
|
||||
}
|
||||
|
||||
override fun getChapters(): List<ChapterSegment> {
|
||||
return playerViewModel?.chapters.orEmpty()
|
||||
}
|
||||
|
||||
override fun onPlaybackEvents(player: Player, events: Player.Events) {
|
||||
super.onPlaybackEvents(player, events)
|
||||
updateDisplayedDuration()
|
||||
|
Loading…
Reference in New Issue
Block a user