[Android] Dynamically update current chapter
Robert Stone
git at videolan.org
Wed Nov 20 06:47:54 UTC 2024
vlc-android | branch: master | Robert Stone <rhstone at gmail.com> | Sat Aug 10 08:51:18 2024 -0700| [d970c0e40d4a5bbfdb3e6e41264bd1a4ebf5c33c] | committer: Duncan McNamara
Dynamically update current chapter
> https://code.videolan.org/videolan/vlc-android/commit/d970c0e40d4a5bbfdb3e6e41264bd1a4ebf5c33c
---
.../vlc/gui/dialogs/SelectChapterDialog.kt | 57 ++++++++++++++++------
1 file changed, 42 insertions(+), 15 deletions(-)
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/dialogs/SelectChapterDialog.kt b/application/vlc-android/src/org/videolan/vlc/gui/dialogs/SelectChapterDialog.kt
index afddda093b..e5940b5acb 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/dialogs/SelectChapterDialog.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/dialogs/SelectChapterDialog.kt
@@ -32,7 +32,10 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
+import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
+import org.videolan.libvlc.MediaPlayer
+import org.videolan.libvlc.interfaces.IMedia
import org.videolan.medialibrary.Tools
import org.videolan.vlc.PlaybackService
import org.videolan.vlc.R
@@ -40,7 +43,7 @@ import org.videolan.vlc.databinding.ChapterListItemBinding
import org.videolan.vlc.util.TextUtils
import org.videolan.vlc.util.launchWhenStarted
-class SelectChapterDialog : VLCBottomSheetDialogFragment(), IOnChapterSelectedListener {
+class SelectChapterDialog : VLCBottomSheetDialogFragment(), IOnChapterSelectedListener, PlaybackService.Callback {
companion object {
@@ -50,6 +53,7 @@ class SelectChapterDialog : VLCBottomSheetDialogFragment(), IOnChapterSelectedLi
}
private lateinit var chapterList: RecyclerView
+ private lateinit var chapterAdapter: ChapterAdapter
private lateinit var nestedScrollView: NestedScrollView
private var service: PlaybackService? = null
@@ -67,13 +71,18 @@ class SelectChapterDialog : VLCBottomSheetDialogFragment(), IOnChapterSelectedLi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- PlaybackService.serviceFlow.onEach { onServiceChanged(it) }.launchWhenStarted(lifecycleScope)
+ PlaybackService.serviceFlow.onEach { onServiceChanged(it) }
+ .onCompletion { onServiceChanged(null) }
+ .launchWhenStarted(lifecycleScope)
}
private fun initChapterList() {
val svc = service ?: return
val chapters = svc.getChapters(-1)
- if (chapters == null || chapters.size <= 1) return
+ if (chapters == null || chapters.size <= 1) {
+ dismiss()
+ return
+ }
val chapterData = ArrayList<Chapter>()
@@ -82,7 +91,7 @@ class SelectChapterDialog : VLCBottomSheetDialogFragment(), IOnChapterSelectedLi
chapterData.add(Chapter(name, Tools.millisToString(chapters[i].timeOffset)))
}
- val adapter = ChapterAdapter(chapterData, svc.chapterIdx, this)
+ chapterAdapter = ChapterAdapter(chapterData, svc.chapterIdx, this)
chapterList.layoutManager = object : LinearLayoutManager(activity, VERTICAL, false) {
override fun onLayoutCompleted(state: RecyclerView.State?) {
@@ -97,21 +106,26 @@ class SelectChapterDialog : VLCBottomSheetDialogFragment(), IOnChapterSelectedLi
}
}
ViewCompat.setNestedScrollingEnabled(chapterList, false)
- chapterList.adapter = adapter
+ chapterList.adapter = chapterAdapter
}
override fun onChapterSelected(position: Int) {
service?.chapterIdx = position
dismiss()
-
}
private fun onServiceChanged(service: PlaybackService?) {
+ if (this.service == service) return
if (service != null) {
this.service = service
+ service.addCallback(this)
initChapterList()
- } else
+ } else {
+ this.service?.apply {
+ removeCallback(this at SelectChapterDialog)
+ }
this.service = null
+ }
}
override fun getDefaultState(): Int {
@@ -125,23 +139,29 @@ class SelectChapterDialog : VLCBottomSheetDialogFragment(), IOnChapterSelectedLi
data class Chapter(val name: String, val time: String)
- inner class ChapterAdapter(private val chapters: List<Chapter>, private val selectedIndex: Int?, private val listener: IOnChapterSelectedListener) : RecyclerView.Adapter<ChapterViewHolder>() {
- private lateinit var binding: ChapterListItemBinding
+ inner class ChapterAdapter(private val chapters: List<Chapter>, private var selectedIndex: Int, private val listener: IOnChapterSelectedListener) : RecyclerView.Adapter<ChapterViewHolder>() {
override fun onBindViewHolder(holder: ChapterViewHolder, position: Int) {
- binding.chapter = chapters[position]
- binding.selected = selectedIndex == position
+ holder.binding.chapter = chapters[position]
+ holder.binding.selected = selectedIndex == position
+ holder.binding.executePendingBindings()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChapterViewHolder {
- binding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.chapter_list_item, parent, false) as ChapterListItemBinding
+ val binding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.chapter_list_item, parent, false) as ChapterListItemBinding
return ChapterViewHolder(binding, listener)
-
}
override fun getItemCount(): Int {
return chapters.size
}
+
+ fun updateSelectedIndex(newIndex: Int) {
+ val oldIndex = selectedIndex
+ selectedIndex = newIndex
+ notifyItemChanged(oldIndex)
+ notifyItemChanged(newIndex)
+ }
}
inner class ChapterViewHolder(var binding: ChapterListItemBinding, private val listener: IOnChapterSelectedListener) : RecyclerView.ViewHolder(binding.root) {
@@ -152,13 +172,20 @@ class SelectChapterDialog : VLCBottomSheetDialogFragment(), IOnChapterSelectedLi
fun onClick(@Suppress("UNUSED_PARAMETER") v: View) {
listener.onChapterSelected(layoutPosition)
-
}
+ }
-
+ override fun update() {
+ service?.let { chapterAdapter.updateSelectedIndex(it.chapterIdx) }
+ chapterList.requestLayout()
}
+ override fun onMediaEvent(event: IMedia.Event) {
+ }
+ override fun onMediaPlayerEvent(event: MediaPlayer.Event) {
+ if (event.type == MediaPlayer.Event.Opening) initChapterList()
+ }
}
interface IOnChapterSelectedListener {
More information about the Android
mailing list