mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-15 14:50:30 +05:30
Chapters support in audio player
This commit is contained in:
parent
0e6ef50159
commit
83899affaa
@ -6,6 +6,7 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.text.format.DateUtils
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.view.accessibility.CaptioningManager
|
import android.view.accessibility.CaptioningManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@ -23,11 +24,13 @@ import androidx.media3.exoplayer.ExoPlayer
|
|||||||
import androidx.media3.exoplayer.LoadControl
|
import androidx.media3.exoplayer.LoadControl
|
||||||
import androidx.media3.ui.CaptionStyleCompat
|
import androidx.media3.ui.CaptionStyleCompat
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.api.obj.ChapterSegment
|
||||||
import com.github.libretube.api.obj.Segment
|
import com.github.libretube.api.obj.Segment
|
||||||
import com.github.libretube.api.obj.Streams
|
import com.github.libretube.api.obj.Streams
|
||||||
import com.github.libretube.constants.PreferenceKeys
|
import com.github.libretube.constants.PreferenceKeys
|
||||||
import com.github.libretube.enums.PlayerEvent
|
import com.github.libretube.enums.PlayerEvent
|
||||||
import com.github.libretube.enums.SbSkipOptions
|
import com.github.libretube.enums.SbSkipOptions
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@ -440,7 +443,7 @@ object PlayerHelper {
|
|||||||
if ((duration - currentPosition).absoluteValue < 500) continue
|
if ((duration - currentPosition).absoluteValue < 500) continue
|
||||||
|
|
||||||
if (currentPosition in segmentStart until segmentEnd) {
|
if (currentPosition in segmentStart until segmentEnd) {
|
||||||
if (sponsorBlockConfig.get(segment.category) == SbSkipOptions.AUTOMATIC) {
|
if (sponsorBlockConfig[segment.category] == SbSkipOptions.AUTOMATIC) {
|
||||||
if (sponsorBlockNotifications) {
|
if (sponsorBlockNotifications) {
|
||||||
runCatching {
|
runCatching {
|
||||||
Toast.makeText(context, R.string.segment_skipped, Toast.LENGTH_SHORT)
|
Toast.makeText(context, R.string.segment_skipped, Toast.LENGTH_SHORT)
|
||||||
@ -455,4 +458,19 @@ object PlayerHelper {
|
|||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a dialog with the chapters provided, even if the list is empty
|
||||||
|
*/
|
||||||
|
fun showChaptersDialog(context: Context, chapters: List<ChapterSegment>, player: ExoPlayer) {
|
||||||
|
val titles = chapters.map { chapter ->
|
||||||
|
"(${DateUtils.formatElapsedTime(chapter.start)}) ${chapter.title}"
|
||||||
|
}
|
||||||
|
MaterialAlertDialogBuilder(context)
|
||||||
|
.setTitle(R.string.chapters)
|
||||||
|
.setItems(titles.toTypedArray()) { _, index ->
|
||||||
|
player.seekTo(chapters[index].start * 1000)
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,8 @@ class OnlinePlayerService : LifecycleService() {
|
|||||||
/**
|
/**
|
||||||
* The response that gets when called the Api.
|
* The response that gets when called the Api.
|
||||||
*/
|
*/
|
||||||
private var streams: Streams? = null
|
var streams: Streams? = null
|
||||||
|
private set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The [ExoPlayer] player. Followed tutorial [here](https://developer.android.com/codelabs/exoplayer-intro)
|
* The [ExoPlayer] player. Followed tutorial [here](https://developer.android.com/codelabs/exoplayer-intro)
|
||||||
|
@ -13,6 +13,7 @@ import android.text.format.DateUtils
|
|||||||
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 android.widget.Toast
|
||||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||||
import androidx.constraintlayout.motion.widget.TransitionAdapter
|
import androidx.constraintlayout.motion.widget.TransitionAdapter
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
@ -29,6 +30,7 @@ import com.github.libretube.helpers.AudioHelper
|
|||||||
import com.github.libretube.helpers.BackgroundHelper
|
import com.github.libretube.helpers.BackgroundHelper
|
||||||
import com.github.libretube.helpers.ImageHelper
|
import com.github.libretube.helpers.ImageHelper
|
||||||
import com.github.libretube.helpers.NavigationHelper
|
import com.github.libretube.helpers.NavigationHelper
|
||||||
|
import com.github.libretube.helpers.PlayerHelper
|
||||||
import com.github.libretube.obj.ShareData
|
import com.github.libretube.obj.ShareData
|
||||||
import com.github.libretube.services.OnlinePlayerService
|
import com.github.libretube.services.OnlinePlayerService
|
||||||
import com.github.libretube.ui.activities.MainActivity
|
import com.github.libretube.ui.activities.MainActivity
|
||||||
@ -153,10 +155,20 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
|||||||
).show(childFragmentManager, null)
|
).show(childFragmentManager, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.close.setOnClickListener {
|
binding.chapters.setOnClickListener {
|
||||||
activity?.unbindService(connection)
|
val playerService = playerService ?: return@setOnClickListener
|
||||||
BackgroundHelper.stopBackgroundPlay(requireContext())
|
if (playerService.streams == null || playerService.player == null) return@setOnClickListener
|
||||||
killFragment()
|
|
||||||
|
if (playerService.streams!!.chapters.isEmpty()) {
|
||||||
|
Toast.makeText(context, R.string.emptyList, Toast.LENGTH_SHORT).show()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerHelper.showChaptersDialog(
|
||||||
|
requireContext(),
|
||||||
|
playerService.streams!!.chapters,
|
||||||
|
playerService.player!!
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.miniPlayerClose.setOnClickListener {
|
binding.miniPlayerClose.setOnClickListener {
|
||||||
|
@ -1191,16 +1191,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
binding.chaptersRecView.adapter = ChaptersAdapter(chapters, exoPlayer)
|
binding.chaptersRecView.adapter = ChaptersAdapter(chapters, exoPlayer)
|
||||||
|
|
||||||
// enable the chapters dialog in the player
|
// enable the chapters dialog in the player
|
||||||
val titles = chapters.map { chapter ->
|
|
||||||
"(${DateUtils.formatElapsedTime(chapter.start)}) ${chapter.title}"
|
|
||||||
}
|
|
||||||
playerBinding.chapterLL.setOnClickListener {
|
playerBinding.chapterLL.setOnClickListener {
|
||||||
MaterialAlertDialogBuilder(requireContext())
|
PlayerHelper.showChaptersDialog(requireContext(), chapters, exoPlayer)
|
||||||
.setTitle(R.string.chapters)
|
|
||||||
.setItems(titles.toTypedArray()) { _, index ->
|
|
||||||
exoPlayer.seekTo(chapters[index].start * 1000)
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurrentChapterName()
|
setCurrentChapterName()
|
||||||
|
@ -238,9 +238,9 @@
|
|||||||
android:src="@drawable/ic_share" />
|
android:src="@drawable/ic_share" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/close"
|
android:id="@+id/chapters"
|
||||||
style="@style/AudioPlayerButton"
|
style="@style/AudioPlayerButton"
|
||||||
android:src="@drawable/ic_close" />
|
android:src="@drawable/ic_frame" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user