Skip to content
Snippets Groups Projects
Commit c8b96b4e authored by Nicolas Pomepuy's avatar Nicolas Pomepuy Committed by Duncan McNamara
Browse files

Add the mini visualizer in the browser

parent 21842eb7
No related branches found
No related tags found
1 merge request!1869Add a progress/played indicator to the file browser items
......@@ -70,6 +70,10 @@
<variable
name="isTv"
type="boolean" />
<variable
name="forceCoverHiding"
type="boolean" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
......@@ -111,13 +115,23 @@
android:onClick="@{holder::onImageClick}"
android:scaleType="centerCrop"
android:src="@{cover}"
android:visibility="@{item.getItemType() == MediaLibraryItem.TYPE_STORAGE ? View.GONE : View.VISIBLE}"
android:visibility="@{forceCoverHiding ? View.INVISIBLE : item.getItemType() == MediaLibraryItem.TYPE_STORAGE ? View.GONE : View.VISIBLE}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/browser_checkbox"
app:layout_constraintTop_toTopOf="parent"
app:media="@{item}"
tools:srcCompat="@drawable/ic_am_folder" />
<org.videolan.vlc.gui.view.MiniVisualizer
android:id="@+id/playing"
android:layout_width="32dp"
android:layout_height="32dp"
app:bar_color="?attr/mini_visualizer_color"
app:layout_constraintBottom_toBottomOf="@+id/item_icon"
app:layout_constraintEnd_toEndOf="@+id/item_icon"
app:layout_constraintStart_toStartOf="@+id/item_icon"
app:layout_constraintTop_toTopOf="@+id/item_icon" />
<ImageView
android:id="@+id/ml_item_seen"
android:layout_width="wrap_content"
......
......@@ -81,6 +81,10 @@
<variable
name="bgColor"
type="int" />
<variable
name="forceCoverHiding"
type="boolean" />
</data>
<com.google.android.material.card.MaterialCardView
......@@ -134,12 +138,22 @@
android:layout_marginTop="8dp"
android:scaleType="centerCrop"
android:src="@{cover}"
android:visibility="@{item.getItemType() == MediaLibraryItem.TYPE_STORAGE ? View.GONE : View.VISIBLE}"
android:visibility="@{forceCoverHiding ? View.INVISIBLE : item.getItemType() == MediaLibraryItem.TYPE_STORAGE ? View.GONE : View.VISIBLE}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:media="@{item}" />
<org.videolan.vlc.gui.view.MiniVisualizer
android:id="@+id/playing"
android:layout_width="32dp"
android:layout_height="32dp"
app:bar_color="?attr/mini_visualizer_color"
app:layout_constraintBottom_toBottomOf="@+id/item_icon"
app:layout_constraintEnd_toEndOf="@+id/item_icon"
app:layout_constraintStart_toStartOf="@+id/item_icon"
app:layout_constraintTop_toTopOf="@+id/item_icon" />
<ImageView
android:id="@+id/ml_item_seen"
android:layout_width="wrap_content"
......
......@@ -51,8 +51,10 @@ import org.videolan.vlc.databinding.CardBrowserItemBinding
import org.videolan.vlc.gui.DiffUtilAdapter
import org.videolan.vlc.gui.helpers.*
import org.videolan.vlc.gui.view.FastScroller
import org.videolan.vlc.gui.view.MiniVisualizer
import org.videolan.vlc.util.LifecycleAwareScheduler
import org.videolan.vlc.util.getDescriptionSpan
import org.videolan.vlc.viewmodels.PlaylistModel
const val UPDATE_PROGRESS = "update_progress"
open class BaseBrowserAdapter(val browserContainer: BrowserContainer<MediaLibraryItem>, var sort:Int = Medialibrary.SORT_FILENAME, var asc:Boolean = true) : DiffUtilAdapter<MediaLibraryItem, BaseBrowserAdapter.ViewHolder<ViewDataBinding>>(), MultiSelectAdapter<MediaLibraryItem>, FastScroller.SeparatedAdapter {
......@@ -84,6 +86,19 @@ open class BaseBrowserAdapter(val browserContainer: BrowserContainer<MediaLibrar
private var specialIcons = false
val diffCallback = BrowserDiffCallback()
private var currentPlayingVisu: MiniVisualizer? = null
private var model: PlaylistModel? = null
var currentMedia: MediaWrapper? = null
set(media) {
if (media == currentMedia) return
val former = currentMedia
field = media
if (former != null) notifyItemChanged(dataset.indexOf(former))
if (media != null) {
notifyItemChanged(dataset.indexOf(media))
}
}
private var scheduler: LifecycleAwareScheduler? = null
......@@ -126,9 +141,19 @@ open class BaseBrowserAdapter(val browserContainer: BrowserContainer<MediaLibrar
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
scheduler?.cancelAction(MARQUEE_ACTION)
currentMedia = null
currentPlayingVisu = null
super.onDetachedFromRecyclerView(recyclerView)
}
fun setCurrentlyPlaying(playing: Boolean) {
if (playing) currentPlayingVisu?.start() else currentPlayingVisu?.stop()
}
fun setModel(model: PlaylistModel) {
this.model = model
}
override fun onBindViewHolder(holder: ViewHolder<ViewDataBinding>, position: Int) {
val viewType = getItemViewType(position)
if (viewType == TYPE_MEDIA) {
......@@ -180,6 +205,14 @@ open class BaseBrowserAdapter(val browserContainer: BrowserContainer<MediaLibrar
vh.bindingContainer.setCover(getIcon(media, specialIcons))
vh.selectView(multiSelectHelper.isSelected(position))
itemFocusChanged(position, false, vh.bindingContainer)
if (currentMedia == media) {
if (model?.playing != false) vh.bindingContainer.startVisu() else vh.bindingContainer.stopVisu()
vh.bindingContainer.setVisuVisibility(View.VISIBLE)
currentPlayingVisu = vh.bindingContainer.getVisu()
} else {
vh.bindingContainer.stopVisu()
vh.bindingContainer.setVisuVisibility(View.INVISIBLE)
}
}
override fun onViewRecycled(holder: ViewHolder<ViewDataBinding>) {
......
......@@ -40,6 +40,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asFlow
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.DividerItemDecoration
......@@ -54,6 +55,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.Runnable
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
......@@ -108,6 +111,8 @@ import org.videolan.vlc.util.Permissions
import org.videolan.vlc.util.SchedulerCallback
import org.videolan.vlc.util.isSchemeSupported
import org.videolan.vlc.util.isTalkbackIsEnabled
import org.videolan.vlc.util.launchWhenStarted
import org.videolan.vlc.viewmodels.PlaylistModel
import org.videolan.vlc.viewmodels.browser.BrowserModel
import java.io.File
import java.util.LinkedList
......@@ -217,6 +222,16 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
binding.browserFastScroller.attachToCoordinator(it, view.rootView.findViewById<View>(R.id.coordinator) as CoordinatorLayout, view.rootView.findViewById<View>(R.id.fab) as FloatingActionButton)
binding.browserFastScroller.setRecyclerView(binding.networkList, viewModel.provider)
}
PlaylistManager.currentPlayedMedia.observe(this) {
adapter.currentMedia = it
}
val playlistModel = PlaylistModel.get(this)
adapter.setModel(playlistModel)
playlistModel.dataset.asFlow().conflate().onEach {
adapter.setCurrentlyPlaying(playlistModel.playing)
delay(50L)
}.launchWhenStarted(lifecycleScope)
}
override fun sortBy(sort: Int) {
......
......@@ -36,6 +36,7 @@ import org.videolan.tools.Settings
import org.videolan.vlc.databinding.BrowserItemBinding
import org.videolan.vlc.databinding.CardBrowserItemBinding
import org.videolan.vlc.gui.helpers.ThreeStatesCheckbox
import org.videolan.vlc.gui.view.MiniVisualizer
class BrowserItemBindingContainer(val binding: ViewDataBinding) {
fun setCheckEnabled(enabled: Boolean) {
......@@ -133,6 +134,63 @@ class BrowserItemBindingContainer(val binding: ViewDataBinding) {
}
}
fun getVisu():MiniVisualizer {
return when (binding) {
is CardBrowserItemBinding -> {
binding.playing
}
is BrowserItemBinding -> {
binding.playing
}
else -> throw IllegalStateException("Binding should be either a CardBrowserItemBinding or BrowserItemBinding")
}
}
fun startVisu() {
when (binding) {
is CardBrowserItemBinding -> {
binding.playing.start()
}
is BrowserItemBinding -> {
binding.playing.start()
}
else -> throw IllegalStateException("Binding should be either a CardBrowserItemBinding or BrowserItemBinding")
}
}
fun stopVisu() {
when (binding) {
is CardBrowserItemBinding -> {
binding.playing.start()
}
is BrowserItemBinding -> {
binding.playing.stop()
}
else -> throw IllegalStateException("Binding should be either a CardBrowserItemBinding or BrowserItemBinding")
}
}
fun setVisuVisibility(visible: Int) {
when (binding) {
is CardBrowserItemBinding -> {
binding.playing.visibility = visible
binding.forceCoverHiding = visible == View.VISIBLE
}
is BrowserItemBinding -> {
binding.playing.visibility = visible
binding.forceCoverHiding = visible == View.VISIBLE
}
else -> throw IllegalStateException("Binding should be either a CardBrowserItemBinding or BrowserItemBinding")
}
}
fun setIsTv(isTv:Boolean) {
when (binding) {
is BrowserItemBinding -> binding.isTv = isTv
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment