Skip to content
Snippets Groups Projects
Commit dad30193 authored by Nicolas Pomepuy's avatar Nicolas Pomepuy
Browse files

Implement favorites for videos, groups and folders

parent 934ce121
No related branches found
No related tags found
2 merge requests!1702Bump the aar artifacts,!1691Draft: Implement the only favorites queries
......@@ -29,6 +29,10 @@
name="isPresent"
type="boolean" />
<variable
name="isFavorite"
type="boolean" />
<variable
name="inSelection"
type="boolean" />
......@@ -168,6 +172,20 @@
vlc:layout_constraintStart_toStartOf="parent"
vlc:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/media_favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="4dp"
android:background="@drawable/rounded_corners_black_more_transparent"
android:padding="3dp"
android:visibility="@{isFavorite ? View.VISIBLE : View.GONE}"
vlc:layout_constraintBottom_toTopOf="@+id/ml_item_progress"
vlc:layout_constraintStart_toStartOf="@+id/ml_item_thumbnail"
vlc:layout_goneMarginBottom="4dp"
vlc:srcCompat="@drawable/ic_emoji_favorite" />
<ImageView
android:id="@+id/network_media"
android:layout_width="wrap_content"
......@@ -178,7 +196,7 @@
android:padding="3dp"
android:visibility="@{isNetwork &amp;&amp; isPresent ? View.VISIBLE : View.GONE}"
vlc:layout_constraintBottom_toTopOf="@+id/ml_item_progress"
vlc:layout_constraintStart_toStartOf="@+id/ml_item_thumbnail"
vlc:layout_constraintStart_toEndOf="@+id/media_favorite"
vlc:layout_goneMarginBottom="4dp"
vlc:srcCompat="@drawable/ic_emoji_network" />
......@@ -193,7 +211,7 @@
android:padding="3dp"
android:visibility="@{isOTG &amp;&amp; isPresent ? View.VISIBLE : View.GONE}"
vlc:layout_constraintBottom_toTopOf="@+id/ml_item_progress"
vlc:layout_constraintStart_toStartOf="@+id/ml_item_thumbnail"
vlc:layout_constraintStart_toEndOf="@+id/media_favorite"
vlc:layout_goneMarginBottom="4dp"
vlc:srcCompat="@drawable/ic_emoji_otg" />
......@@ -207,7 +225,7 @@
android:padding="3dp"
android:visibility="@{isSD &amp;&amp; isPresent ? View.VISIBLE : View.GONE}"
vlc:layout_constraintBottom_toTopOf="@+id/ml_item_progress"
vlc:layout_constraintStart_toStartOf="@+id/ml_item_thumbnail"
vlc:layout_constraintStart_toEndOf="@+id/media_favorite"
vlc:layout_goneMarginBottom="4dp"
vlc:srcCompat="@drawable/ic_emoji_sd" />
......@@ -221,7 +239,7 @@
android:padding="3dp"
android:visibility="@{!isPresent ? View.VISIBLE : View.GONE}"
vlc:layout_constraintBottom_toTopOf="@+id/ml_item_progress"
vlc:layout_constraintStart_toStartOf="@+id/ml_item_thumbnail"
vlc:layout_constraintStart_toEndOf="@+id/media_favorite"
vlc:layout_goneMarginBottom="4dp"
vlc:srcCompat="@drawable/ic_emoji_absent" />
......
......@@ -29,6 +29,10 @@
name="isPresent"
type="boolean" />
<variable
name="isFavorite"
type="boolean" />
<variable
name="inSelection"
type="boolean" />
......@@ -222,24 +226,35 @@
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/ml_item_title"
style="@style/VLC.TextViewTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="4dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:lineSpacingMultiplier="1"
android:text="@{media.title}"
android:enabled="@{isPresent}"
android:textSize="16sp"
tools:text="Star wars Episode 1"
vlc:layout_constraintBottom_toTopOf="@+id/ml_item_time"
vlc:layout_constraintEnd_toStartOf="@+id/item_more"
vlc:layout_constraintStart_toEndOf="@+id/container"
vlc:layout_constraintTop_toTopOf="parent"
vlc:layout_constraintVertical_chainStyle="packed" />
android:id="@+id/ml_item_title"
style="@style/VLC.TextViewTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="4dp"
android:ellipsize="end"
android:enabled="@{isPresent}"
android:gravity="center_vertical"
android:lineSpacingMultiplier="1"
android:text="@{media.title}"
android:textSize="16sp"
tools:text="Star wars Episode 1"
vlc:layout_constraintBottom_toTopOf="@+id/ml_item_time"
vlc:layout_constraintEnd_toStartOf="@+id/media_favorite"
vlc:layout_constraintStart_toEndOf="@+id/container"
vlc:layout_constraintTop_toTopOf="parent"
vlc:layout_constraintVertical_chainStyle="packed" />
<ImageView
android:id="@+id/media_favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp"
android:visibility="@{isFavorite ? View.VISIBLE : View.GONE}"
vlc:layout_constraintBottom_toBottomOf="parent"
vlc:layout_constraintEnd_toStartOf="@+id/item_more"
vlc:layout_constraintTop_toTopOf="parent"
vlc:srcCompat="@drawable/ic_emoji_favorite" />
<ImageView
android:id="@+id/item_more"
......@@ -259,23 +274,23 @@
vlc:srcCompat="@drawable/ic_more" />
<TextView
android:id="@+id/ml_item_time"
style="@style/VLC.TextViewDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignWithParentIfMissing="true"
android:layout_marginStart="16dp"
android:layout_marginEnd="4dp"
android:gravity="start"
vlc:presenceDescription="@{time}"
android:textSize="12sp"
android:enabled="@{!isNetwork || isPresent}"
android:visibility="@{TextUtils.isEmpty(time) ? View.GONE : View.VISIBLE}"
tools:text="32:55"
vlc:layout_constraintBottom_toBottomOf="parent"
vlc:layout_constraintEnd_toStartOf="@+id/item_more"
vlc:layout_constraintStart_toEndOf="@+id/container"
vlc:layout_constraintTop_toBottomOf="@+id/ml_item_title" />
android:id="@+id/ml_item_time"
style="@style/VLC.TextViewDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignWithParentIfMissing="true"
android:layout_marginStart="16dp"
android:layout_marginEnd="4dp"
android:enabled="@{!isNetwork || isPresent}"
android:gravity="start"
android:textSize="12sp"
android:visibility="@{TextUtils.isEmpty(time) ? View.GONE : View.VISIBLE}"
tools:text="32:55"
vlc:layout_constraintBottom_toBottomOf="parent"
vlc:layout_constraintEnd_toStartOf="@+id/media_favorite"
vlc:layout_constraintStart_toEndOf="@+id/container"
vlc:layout_constraintTop_toBottomOf="@+id/ml_item_title"
vlc:presenceDescription="@{time}" />
<ImageView
android:id="@+id/selected_check"
......
......@@ -509,6 +509,9 @@ class VideoGridFragment : MediaBrowserFragment<VideosViewModel>(), SwipeRefreshL
CTX_GROUP_SIMILAR -> lifecycleScope.launch { viewModel.groupSimilar(media) }
CTX_MARK_AS_PLAYED -> lifecycleScope.launch { viewModel.markAsPlayed(media) }
CTX_MARK_AS_UNPLAYED -> lifecycleScope.launch { viewModel.markAsUnplayed(media) }
CTX_FAV_ADD, CTX_FAV_REMOVE -> lifecycleScope.launch(Dispatchers.IO) {
media.isFavorite = option == CTX_FAV_ADD
}
CTX_GO_TO_FOLDER -> showParentFolder(media)
CTX_ADD_SHORTCUT -> lifecycleScope.launch { requireActivity().createShortcut(media)}
}
......@@ -517,6 +520,9 @@ class VideoGridFragment : MediaBrowserFragment<VideosViewModel>(), SwipeRefreshL
CTX_APPEND -> viewModel.append(position)
CTX_ADD_TO_PLAYLIST -> viewModel.addItemToPlaylist(requireActivity(), position)
CTX_MARK_ALL_AS_PLAYED -> lifecycleScope.launch { viewModel.markAsPlayed(media) }
CTX_FAV_ADD, CTX_FAV_REMOVE -> lifecycleScope.launch(Dispatchers.IO) {
media.isFavorite = option == CTX_FAV_ADD
}
}
is VideoGroup -> when (option) {
CTX_PLAY_ALL -> viewModel.play(position)
......@@ -527,6 +533,9 @@ class VideoGridFragment : MediaBrowserFragment<VideosViewModel>(), SwipeRefreshL
CTX_UNGROUP -> viewModel.ungroup(media)
CTX_MARK_ALL_AS_PLAYED -> lifecycleScope.launch { viewModel.markAsPlayed(media) }
CTX_ADD_GROUP -> requireActivity().addToGroup(listOf(media).getAll(), true) {}
CTX_FAV_ADD, CTX_FAV_REMOVE -> lifecycleScope.launch(Dispatchers.IO) {
media.isFavorite = option == CTX_FAV_ADD
}
}
}
}
......@@ -562,11 +571,12 @@ class VideoGridFragment : MediaBrowserFragment<VideosViewModel>(), SwipeRefreshL
}
is VideoCtxClick -> {
when (item) {
is Folder -> showContext(requireActivity(), this@VideoGridFragment, position, item, CTX_FOLDER_FLAGS)
is VideoGroup -> if (item.presentCount == 0) UiTools.snackerMissing(requireActivity()) else showContext(requireActivity(), this@VideoGridFragment, position, item, CTX_FOLDER_FLAGS or CTX_RENAME_GROUP or CTX_UNGROUP or CTX_PLAY_ALL and CTX_PLAY.inv() or CTX_ADD_GROUP)
is Folder -> showContext(requireActivity(), this@VideoGridFragment, position, item, CTX_FOLDER_FLAGS or if(item.isFavorite) CTX_FAV_REMOVE else CTX_FAV_ADD)
is VideoGroup -> if (item.presentCount == 0) UiTools.snackerMissing(requireActivity()) else showContext(requireActivity(), this@VideoGridFragment, position, item, CTX_FOLDER_FLAGS or CTX_RENAME_GROUP or CTX_UNGROUP or CTX_PLAY_ALL and CTX_PLAY.inv() or CTX_ADD_GROUP or if(item.isFavorite) CTX_FAV_REMOVE else CTX_FAV_ADD)
is MediaWrapper -> {
val group = item.type == MediaWrapper.TYPE_GROUP
var flags = if (group) CTX_VIDEO_GROUP_FLAGS else CTX_VIDEO_FLAGS
flags = flags or if(item.isFavorite) CTX_FAV_REMOVE else CTX_FAV_ADD
flags = if (item.seen > 0) flags or CTX_MARK_AS_UNPLAYED else flags or CTX_MARK_AS_PLAYED
if (item.time != 0L && !group) flags = flags or CTX_PLAY_FROM_START
if (viewModel.groupingType == VideoGroupingType.NAME || viewModel.group != null) flags = flags or if (viewModel.group != null) CTX_REMOVE_GROUP else flags or CTX_ADD_GROUP or CTX_GROUP_SIMILAR
......
......@@ -49,6 +49,7 @@ import org.videolan.tools.MultiSelectAdapter
import org.videolan.tools.MultiSelectHelper
import org.videolan.vlc.BR
import org.videolan.vlc.R
import org.videolan.vlc.gui.audio.AudioBrowserAdapter
import org.videolan.vlc.gui.helpers.*
import org.videolan.vlc.gui.view.FastScroller
import org.videolan.vlc.util.*
......@@ -101,6 +102,7 @@ class VideoListAdapter(private var isSeenMediaMarkerVisible: Boolean
fillView(holder, item)
holder.binding.setVariable(BR.media, item)
holder.selectView(multiSelectHelper.isSelected(position))
item.let { holder.binding.setVariable(BR.isFavorite, it.isFavorite) }
}
override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: List<Any>) {
......@@ -114,6 +116,7 @@ class VideoListAdapter(private var isSeenMediaMarkerVisible: Boolean
UPDATE_TIME, UPDATE_SEEN -> fillView(holder, media as MediaWrapper)
UPDATE_SELECTION -> holder.selectView(multiSelectHelper.isSelected(position))
UPDATE_VIDEO_GROUP -> fillView(holder, media!!)
UPDATE_FAVORITE_STATE -> getItem(position)?.let { holder.binding.setVariable(BR.isFavorite, it.isFavorite) }
}
}
}
......@@ -138,6 +141,7 @@ class VideoListAdapter(private var isSeenMediaMarkerVisible: Boolean
holder.binding.setVariable(BR.time, holder.itemView.context.resources.getQuantityString(R.plurals.videos_quantity, count, count))
holder.binding.setVariable(BR.isNetwork, false)
holder.binding.setVariable(BR.isPresent, true)
holder.binding.setVariable(BR.isFavorite, item.isFavorite)
}
is VideoGroup -> holder.itemView.scope.launch {
val count = item.mediaCount()
......@@ -148,6 +152,7 @@ class VideoListAdapter(private var isSeenMediaMarkerVisible: Boolean
holder.binding.setVariable(BR.seen, seen)
holder.binding.setVariable(BR.max, 0)
holder.binding.setVariable(BR.isPresent, item.presentCount > 0)
holder.binding.setVariable(BR.isFavorite, item.isFavorite)
}
is MediaWrapper -> {
holder.title.text = if (showFilename.get()) item.fileName else item.title
......@@ -181,6 +186,7 @@ class VideoListAdapter(private var isSeenMediaMarkerVisible: Boolean
holder.binding.setVariable(BR.max, max)
holder.binding.setVariable(BR.progress, progress)
holder.binding.setVariable(BR.seen, seen)
holder.binding.setVariable(BR.isFavorite, item.isFavorite)
if (!isListMode) holder.binding.setVariable(BR.resolution, resolution)
}
}
......@@ -250,19 +256,28 @@ class VideoListAdapter(private var isSeenMediaMarkerVisible: Boolean
oldItem === newItem || (oldItem.displayTime == newItem.displayTime
&& oldItem.artworkMrl == newItem.artworkMrl
&& oldItem.seen == newItem.seen
&& oldItem.isPresent == newItem.isPresent)
&& oldItem.isPresent == newItem.isPresent
&& oldItem.isFavorite == newItem.isFavorite)
} //else if (oldItem is FolderImpl && newItem is FolderImpl) return oldItem === newItem || (oldItem.title == newItem.title && oldItem.artworkMrl == newItem.artworkMrl)
else if (oldItem is VideoGroup && newItem is VideoGroup) {
oldItem === newItem || (oldItem.title == newItem.title
&& oldItem.tracksCount == newItem.tracksCount && oldItem.presentCount != newItem.presentCount)
&& oldItem.tracksCount == newItem.tracksCount && oldItem.presentCount != newItem.presentCount
&& oldItem.isFavorite == newItem.isFavorite)
}
else oldItem.itemType == MediaLibraryItem.TYPE_FOLDER || oldItem.itemType == MediaLibraryItem.TYPE_VIDEO_GROUP
else if (oldItem is Folder && newItem is Folder) {
oldItem === newItem || (oldItem.title == newItem.title
&& oldItem.tracksCount == newItem.tracksCount
&& oldItem.isFavorite == newItem.isFavorite)
}
else oldItem.itemType == MediaLibraryItem.TYPE_FOLDER || (oldItem.itemType == MediaLibraryItem.TYPE_VIDEO_GROUP
&& oldItem.isFavorite == newItem.isFavorite)
}
override fun getChangePayload(oldItem: MediaLibraryItem, newItem: MediaLibraryItem) = when {
(oldItem is MediaWrapper && newItem is MediaWrapper) && oldItem.displayTime != newItem.displayTime -> UPDATE_TIME
(oldItem is VideoGroup && newItem is VideoGroup) -> UPDATE_VIDEO_GROUP
oldItem.artworkMrl != newItem.artworkMrl -> UPDATE_THUMB
oldItem.isFavorite != newItem.isFavorite -> UPDATE_FAVORITE_STATE
else -> UPDATE_SEEN
}
}
......
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