mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-29 16:30:31 +05:30
Merge pull request #4377 from Bnyro/master
fix: regressions introduced by new chapters layout
This commit is contained in:
commit
5b45d94ccc
@ -37,27 +37,18 @@ class ChaptersAdapter(
|
|||||||
chapterTitle.text = chapter.title
|
chapterTitle.text = chapter.title
|
||||||
timeStamp.text = DateUtils.formatElapsedTime(chapter.start)
|
timeStamp.text = DateUtils.formatElapsedTime(chapter.start)
|
||||||
|
|
||||||
val chapterEnd = chapters.getOrNull(position + 1)?.start ?: (exoPlayer.duration / 1000)
|
val chapterEnd = chapters.getOrNull(position + 1)?.start
|
||||||
|
?: (exoPlayer.duration / 1000)
|
||||||
val durationSpan = chapterEnd - chapter.start
|
val durationSpan = chapterEnd - chapter.start
|
||||||
duration.text = root.context.getString(
|
duration.text = root.context.getString(
|
||||||
R.string.duration_span,
|
R.string.duration_span,
|
||||||
DateUtils.formatElapsedTime(durationSpan)
|
DateUtils.formatElapsedTime(durationSpan)
|
||||||
)
|
)
|
||||||
|
|
||||||
val color = when {
|
val color = if (selectedPosition == position) {
|
||||||
selectedPosition == position -> {
|
ThemeHelper.getThemeColor(root.context, android.R.attr.colorControlHighlight)
|
||||||
ThemeHelper.getThemeColor(root.context, android.R.attr.colorControlHighlight)
|
} else {
|
||||||
}
|
Color.TRANSPARENT
|
||||||
|
|
||||||
chapter.drawable != null -> ColorUtils.setAlphaComponent(
|
|
||||||
ThemeHelper.getThemeColor(
|
|
||||||
root.context,
|
|
||||||
android.R.attr.colorPrimary
|
|
||||||
),
|
|
||||||
50
|
|
||||||
)
|
|
||||||
|
|
||||||
else -> Color.TRANSPARENT
|
|
||||||
}
|
}
|
||||||
root.setBackgroundColor(color)
|
root.setBackgroundColor(color)
|
||||||
|
|
||||||
@ -70,6 +61,8 @@ class ChaptersAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun updateSelectedPosition(newPosition: Int) {
|
fun updateSelectedPosition(newPosition: Int) {
|
||||||
|
if (selectedPosition == newPosition) return
|
||||||
|
|
||||||
val oldPosition = selectedPosition
|
val oldPosition = selectedPosition
|
||||||
selectedPosition = newPosition
|
selectedPosition = newPosition
|
||||||
notifyItemChanged(oldPosition)
|
notifyItemChanged(oldPosition)
|
||||||
|
@ -180,7 +180,7 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
|||||||
val player = playerService.player ?: return@setOnClickListener
|
val player = playerService.player ?: return@setOnClickListener
|
||||||
|
|
||||||
ChaptersBottomSheet(streams.chapters, player)
|
ChaptersBottomSheet(streams.chapters, player)
|
||||||
.show(requireActivity().supportFragmentManager)
|
.show(childFragmentManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.miniPlayerClose.setOnClickListener {
|
binding.miniPlayerClose.setOnClickListener {
|
||||||
|
@ -777,7 +777,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
// enable the chapters dialog in the player
|
// enable the chapters dialog in the player
|
||||||
playerBinding.chapterLL.setOnClickListener {
|
playerBinding.chapterLL.setOnClickListener {
|
||||||
ChaptersBottomSheet(chapters, exoPlayer)
|
ChaptersBottomSheet(chapters, exoPlayer)
|
||||||
.show(requireActivity().supportFragmentManager)
|
.show(childFragmentManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurrentChapterName()
|
setCurrentChapterName()
|
||||||
@ -1181,10 +1181,14 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
|
|
||||||
// set the name of the video chapter in the exoPlayerView
|
// set the name of the video chapter in the exoPlayerView
|
||||||
private fun setCurrentChapterName(forceUpdate: Boolean = false, enqueueNew: Boolean = true) {
|
private fun setCurrentChapterName(forceUpdate: Boolean = false, enqueueNew: Boolean = true) {
|
||||||
playerBinding.chapterLL.isVisible = chapters.isNotEmpty()
|
// return if fragment view got killed already to avoid crashes
|
||||||
|
if (_binding == null) return
|
||||||
|
|
||||||
// return if chapters are empty to avoid crashes
|
// only show the chapters layout if there are some chapters available
|
||||||
if (chapters.isEmpty() || _binding == null) return
|
playerBinding.chapterLL.isInvisible = chapters.isEmpty()
|
||||||
|
|
||||||
|
// the following logic to set the chapter title can be skipped if no chapters are available
|
||||||
|
if (chapters.isEmpty()) return
|
||||||
|
|
||||||
// call the function again in 100ms
|
// call the function again in 100ms
|
||||||
if (enqueueNew) binding.player.postDelayed(this::setCurrentChapterName, 100)
|
if (enqueueNew) binding.player.postDelayed(this::setCurrentChapterName, 100)
|
||||||
@ -1192,8 +1196,9 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
// if the user is scrubbing the time bar, don't update
|
// if the user is scrubbing the time bar, don't update
|
||||||
if (scrubbingTimeBar && !forceUpdate) return
|
if (scrubbingTimeBar && !forceUpdate) return
|
||||||
|
|
||||||
val chapterIndex = PlayerHelper.getCurrentChapterIndex(exoPlayer, chapters) ?: return
|
val chapterName = PlayerHelper.getCurrentChapterIndex(exoPlayer, chapters)?.let {
|
||||||
val chapterName = chapters[chapterIndex].title.trim()
|
chapters[it].title.trim()
|
||||||
|
} ?: getString(R.string.no_chapter)
|
||||||
|
|
||||||
// change the chapter name textView text to the chapterName
|
// change the chapter name textView text to the chapterName
|
||||||
if (chapterName != playerBinding.chapterName.text) {
|
if (chapterName != playerBinding.chapterName.text) {
|
||||||
@ -1453,7 +1458,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
|
|
||||||
if (audioLanguagesAndRoleFlags.isEmpty()) {
|
if (audioLanguagesAndRoleFlags.isEmpty()) {
|
||||||
baseBottomSheet.setSimpleItems(
|
baseBottomSheet.setSimpleItems(
|
||||||
listOf(context.getString(R.string.unknown_or_no_audio)),
|
listOf(getString(R.string.unknown_or_no_audio)),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
} else if (audioLanguagesAndRoleFlags.size == 1 &&
|
} else if (audioLanguagesAndRoleFlags.size == 1 &&
|
||||||
@ -1467,7 +1472,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
// track which has no language or track type set in the video played
|
// track which has no language or track type set in the video played
|
||||||
// Consider it as the default audio track (or unknown)
|
// Consider it as the default audio track (or unknown)
|
||||||
baseBottomSheet.setSimpleItems(
|
baseBottomSheet.setSimpleItems(
|
||||||
listOf(context.getString(R.string.default_or_unknown_audio_track)),
|
listOf(getString(R.string.default_or_unknown_audio_track)),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
package com.github.libretube.ui.sheets
|
package com.github.libretube.ui.sheets
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.children
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@ -15,49 +13,47 @@ import com.github.libretube.R
|
|||||||
import com.github.libretube.api.obj.ChapterSegment
|
import com.github.libretube.api.obj.ChapterSegment
|
||||||
import com.github.libretube.databinding.BottomSheetBinding
|
import com.github.libretube.databinding.BottomSheetBinding
|
||||||
import com.github.libretube.helpers.PlayerHelper
|
import com.github.libretube.helpers.PlayerHelper
|
||||||
import com.github.libretube.helpers.ThemeHelper
|
|
||||||
import com.github.libretube.ui.adapters.ChaptersAdapter
|
import com.github.libretube.ui.adapters.ChaptersAdapter
|
||||||
|
|
||||||
class ChaptersBottomSheet(
|
class ChaptersBottomSheet(
|
||||||
private val chapters: List<ChapterSegment>,
|
private val chapters: List<ChapterSegment>,
|
||||||
private val exoPlayer: ExoPlayer
|
private val exoPlayer: ExoPlayer
|
||||||
): ExpandedBottomSheet() {
|
): ExpandedBottomSheet() {
|
||||||
private lateinit var binding: BottomSheetBinding
|
private var _binding: BottomSheetBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
binding = BottomSheetBinding.inflate(layoutInflater)
|
_binding = BottomSheetBinding.inflate(layoutInflater)
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
binding.optionsRecycler.layoutManager = LinearLayoutManager(context)
|
binding.optionsRecycler.layoutManager = LinearLayoutManager(context)
|
||||||
binding.optionsRecycler.adapter = ChaptersAdapter(chapters, exoPlayer)
|
val adapter = ChaptersAdapter(chapters, exoPlayer)
|
||||||
|
binding.optionsRecycler.adapter = adapter
|
||||||
|
|
||||||
binding.bottomSheetTitle.text = context?.getString(R.string.chapters)
|
binding.bottomSheetTitle.text = context?.getString(R.string.chapters)
|
||||||
binding.bottomSheetTitleLayout.isVisible = true
|
binding.bottomSheetTitleLayout.isVisible = true
|
||||||
|
|
||||||
val handler = Handler(Looper.getMainLooper())
|
val handler = Handler(Looper.getMainLooper())
|
||||||
val highlightColor =
|
|
||||||
ThemeHelper.getThemeColor(requireContext(), android.R.attr.colorControlHighlight)
|
|
||||||
|
|
||||||
val updatePosition = Runnable {
|
val updatePosition = object: Runnable {
|
||||||
// scroll to the current playing index in the chapter
|
override fun run() {
|
||||||
val currentPosition =
|
if (_binding == null) return
|
||||||
PlayerHelper.getCurrentChapterIndex(exoPlayer, chapters) ?: return@Runnable
|
handler.postDelayed(this, 200)
|
||||||
binding.optionsRecycler.smoothScrollToPosition(currentPosition)
|
val currentIndex = PlayerHelper.getCurrentChapterIndex(exoPlayer, chapters) ?: return
|
||||||
|
adapter.updateSelectedPosition(currentIndex)
|
||||||
val children = binding.optionsRecycler.children.toList()
|
}
|
||||||
// reset the background colors of all chapters
|
|
||||||
children.forEach { it.setBackgroundColor(Color.TRANSPARENT) }
|
|
||||||
// highlight the current chapter
|
|
||||||
children.getOrNull(currentPosition)?.setBackgroundColor(highlightColor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePosition.run()
|
updatePosition.run()
|
||||||
handler.postDelayed(updatePosition, 200)
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -460,6 +460,7 @@
|
|||||||
<string name="default_or_unknown_audio_track">default or unknown</string>
|
<string name="default_or_unknown_audio_track">default or unknown</string>
|
||||||
<string name="unknown_or_no_audio">unknown or no audio</string>
|
<string name="unknown_or_no_audio">unknown or no audio</string>
|
||||||
<string name="continue_watching">Continue watching</string>
|
<string name="continue_watching">Continue watching</string>
|
||||||
|
<string name="no_chapter">No chapter</string>
|
||||||
|
|
||||||
<!-- Notification channel strings -->
|
<!-- Notification channel strings -->
|
||||||
<string name="download_channel_name">Download Service</string>
|
<string name="download_channel_name">Download Service</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user