mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-28 07:50:31 +05:30
feat: add badge for downloaded videos
This commit is contained in:
parent
0115e4c070
commit
8a3ea3b695
@ -23,6 +23,9 @@ interface DownloadDao {
|
|||||||
@Query("SELECT * FROM download WHERE videoId = :videoId")
|
@Query("SELECT * FROM download WHERE videoId = :videoId")
|
||||||
suspend fun findById(videoId: String): DownloadWithItems?
|
suspend fun findById(videoId: String): DownloadWithItems?
|
||||||
|
|
||||||
|
@Query("SELECT EXISTS (SELECT * FROM download WHERE videoId = :videoId)")
|
||||||
|
suspend fun exists(videoId: String): Boolean
|
||||||
|
|
||||||
@Query("SELECT videoId FROM downloadItem WHERE type = :fileType ORDER BY RANDOM() LIMIT 1")
|
@Query("SELECT videoId FROM downloadItem WHERE type = :fileType ORDER BY RANDOM() LIMIT 1")
|
||||||
suspend fun getRandomVideoIdByFileType(fileType: FileType): String?
|
suspend fun getRandomVideoIdByFileType(fileType: FileType): String?
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
@ -15,6 +16,7 @@ import com.github.libretube.api.PlaylistsHelper
|
|||||||
import com.github.libretube.api.obj.StreamItem
|
import com.github.libretube.api.obj.StreamItem
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.databinding.VideoRowBinding
|
import com.github.libretube.databinding.VideoRowBinding
|
||||||
|
import com.github.libretube.db.DatabaseHolder
|
||||||
import com.github.libretube.enums.PlaylistType
|
import com.github.libretube.enums.PlaylistType
|
||||||
import com.github.libretube.extensions.TAG
|
import com.github.libretube.extensions.TAG
|
||||||
import com.github.libretube.extensions.dpToPx
|
import com.github.libretube.extensions.dpToPx
|
||||||
@ -118,6 +120,15 @@ class PlaylistAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
streamItem.duration?.let { watchProgress.setWatchProgressLength(videoId, it) }
|
streamItem.duration?.let { watchProgress.setWatchProgressLength(videoId, it) }
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
val isDownloaded =
|
||||||
|
DatabaseHolder.Database.downloadDao().exists(videoId)
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
downloadBadge.isVisible = isDownloaded
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package com.github.libretube.ui.adapters
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.paging.PagingDataAdapter
|
import androidx.paging.PagingDataAdapter
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.api.JsonHelper
|
import com.github.libretube.api.JsonHelper
|
||||||
@ -12,6 +13,7 @@ import com.github.libretube.constants.IntentData
|
|||||||
import com.github.libretube.databinding.ChannelRowBinding
|
import com.github.libretube.databinding.ChannelRowBinding
|
||||||
import com.github.libretube.databinding.PlaylistsRowBinding
|
import com.github.libretube.databinding.PlaylistsRowBinding
|
||||||
import com.github.libretube.databinding.VideoRowBinding
|
import com.github.libretube.databinding.VideoRowBinding
|
||||||
|
import com.github.libretube.db.DatabaseHolder
|
||||||
import com.github.libretube.enums.PlaylistType
|
import com.github.libretube.enums.PlaylistType
|
||||||
import com.github.libretube.extensions.formatShort
|
import com.github.libretube.extensions.formatShort
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
@ -27,6 +29,10 @@ import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
|||||||
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
|
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
|
||||||
import com.github.libretube.ui.viewholders.SearchViewHolder
|
import com.github.libretube.ui.viewholders.SearchViewHolder
|
||||||
import com.github.libretube.util.TextUtils
|
import com.github.libretube.util.TextUtils
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
|
|
||||||
class SearchResultsAdapter(
|
class SearchResultsAdapter(
|
||||||
@ -112,6 +118,15 @@ class SearchResultsAdapter(
|
|||||||
NavigationHelper.navigateChannel(root.context, item.uploaderUrl)
|
NavigationHelper.navigateChannel(root.context, item.uploaderUrl)
|
||||||
}
|
}
|
||||||
watchProgress.setWatchProgressLength(videoId, item.duration)
|
watchProgress.setWatchProgressLength(videoId, item.duration)
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
val isDownloaded =
|
||||||
|
DatabaseHolder.Database.downloadDao().exists(videoId)
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
downloadBadge.isVisible = isDownloaded
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@ package com.github.libretube.ui.adapters
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.format.DateUtils
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@ -17,6 +17,7 @@ import com.github.libretube.constants.PreferenceKeys
|
|||||||
import com.github.libretube.databinding.AllCaughtUpRowBinding
|
import com.github.libretube.databinding.AllCaughtUpRowBinding
|
||||||
import com.github.libretube.databinding.TrendingRowBinding
|
import com.github.libretube.databinding.TrendingRowBinding
|
||||||
import com.github.libretube.databinding.VideoRowBinding
|
import com.github.libretube.databinding.VideoRowBinding
|
||||||
|
import com.github.libretube.db.DatabaseHolder
|
||||||
import com.github.libretube.extensions.ceilHalf
|
import com.github.libretube.extensions.ceilHalf
|
||||||
import com.github.libretube.extensions.dpToPx
|
import com.github.libretube.extensions.dpToPx
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
@ -29,6 +30,10 @@ import com.github.libretube.ui.extensions.setWatchProgressLength
|
|||||||
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
|
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
|
||||||
import com.github.libretube.ui.viewholders.VideosViewHolder
|
import com.github.libretube.ui.viewholders.VideosViewHolder
|
||||||
import com.github.libretube.util.TextUtils
|
import com.github.libretube.util.TextUtils
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class VideosAdapter(
|
class VideosAdapter(
|
||||||
private val streamItems: MutableList<StreamItem>,
|
private val streamItems: MutableList<StreamItem>,
|
||||||
@ -86,12 +91,10 @@ class VideosAdapter(
|
|||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onBindViewHolder(holder: VideosViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: VideosViewHolder, position: Int) {
|
||||||
val video = streamItems[position]
|
val video = streamItems[position]
|
||||||
val videoId = video.url?.toID()
|
val videoId = video.url.orEmpty().toID()
|
||||||
|
|
||||||
videoId?.let {
|
(holder.trendingRowBinding?.watchProgress ?: holder.videoRowBinding!!.watchProgress)
|
||||||
(holder.trendingRowBinding?.watchProgress ?: holder.videoRowBinding!!.watchProgress)
|
.setWatchProgressLength(videoId, video.duration ?: 0L)
|
||||||
.setWatchProgressLength(it, video.duration ?: 0L)
|
|
||||||
}
|
|
||||||
|
|
||||||
val context = (
|
val context = (
|
||||||
holder.videoRowBinding ?: holder.trendingRowBinding
|
holder.videoRowBinding ?: holder.trendingRowBinding
|
||||||
@ -119,7 +122,7 @@ class VideosAdapter(
|
|||||||
ImageHelper.loadImage(video.thumbnail, thumbnail)
|
ImageHelper.loadImage(video.thumbnail, thumbnail)
|
||||||
ImageHelper.loadImage(video.uploaderAvatar, channelImage, true)
|
ImageHelper.loadImage(video.uploaderAvatar, channelImage, true)
|
||||||
root.setOnClickListener {
|
root.setOnClickListener {
|
||||||
NavigationHelper.navigateVideo(root.context, video.url)
|
NavigationHelper.navigateVideo(root.context, videoId)
|
||||||
}
|
}
|
||||||
|
|
||||||
root.setOnLongClickListener {
|
root.setOnLongClickListener {
|
||||||
@ -156,7 +159,7 @@ class VideosAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
root.setOnClickListener {
|
root.setOnClickListener {
|
||||||
NavigationHelper.navigateVideo(root.context, video.url)
|
NavigationHelper.navigateVideo(root.context, videoId)
|
||||||
}
|
}
|
||||||
|
|
||||||
root.setOnLongClickListener {
|
root.setOnLongClickListener {
|
||||||
@ -171,6 +174,15 @@ class VideosAdapter(
|
|||||||
sheet.show(fragmentManager, VideosAdapter::class.java.name)
|
sheet.show(fragmentManager, VideosAdapter::class.java.name)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
val isDownloaded =
|
||||||
|
DatabaseHolder.Database.downloadDao().exists(videoId)
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
downloadBadge.isVisible = isDownloaded
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.databinding.VideoRowBinding
|
import com.github.libretube.databinding.VideoRowBinding
|
||||||
@ -17,8 +18,11 @@ import com.github.libretube.ui.extensions.setWatchProgressLength
|
|||||||
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
|
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
|
||||||
import com.github.libretube.ui.viewholders.WatchHistoryViewHolder
|
import com.github.libretube.ui.viewholders.WatchHistoryViewHolder
|
||||||
import com.github.libretube.util.TextUtils
|
import com.github.libretube.util.TextUtils
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class WatchHistoryAdapter(
|
class WatchHistoryAdapter(
|
||||||
private val watchHistory: MutableList<WatchHistoryItem>
|
private val watchHistory: MutableList<WatchHistoryItem>
|
||||||
@ -98,6 +102,15 @@ class WatchHistoryAdapter(
|
|||||||
video.videoId,
|
video.videoId,
|
||||||
video.duration
|
video.duration
|
||||||
)
|
)
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
val isDownloaded =
|
||||||
|
DatabaseHolder.Database.downloadDao().exists(video.videoId)
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
downloadBadge.isVisible = isDownloaded
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
app/src/main/res/drawable/ic_download_folder.xml
Normal file
10
app/src/main/res/drawable/ic_download_folder.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?colorControlNormal"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="m434,663 l226,-227 -56,-56 -170,170 -85,-85 -57,57 142,141ZM160,800q-33,0 -56.5,-23.5T80,720v-480q0,-33 23.5,-56.5T160,160h240l80,80h320q33,0 56.5,23.5T880,320v400q0,33 -23.5,56.5T800,800L160,800ZM160,720h640v-400L447,320l-80,-80L160,240v480ZM160,720v-480,480Z" />
|
||||||
|
</vector>
|
@ -107,7 +107,7 @@
|
|||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toStartOf="@id/download_badge"
|
||||||
app:layout_constraintStart_toEndOf="@id/thumbnail_card"
|
app:layout_constraintStart_toEndOf="@id/thumbnail_card"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
@ -119,10 +119,22 @@
|
|||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toStartOf="@id/download_badge"
|
||||||
app:layout_constraintStart_toEndOf="@id/thumbnail_card"
|
app:layout_constraintStart_toEndOf="@id/thumbnail_card"
|
||||||
app:layout_constraintTop_toBottomOf="@id/video_title" />
|
app:layout_constraintTop_toBottomOf="@id/video_title" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/download_badge"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_download_folder"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:paddingStart="6dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:ignore="RtlSymmetry"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/channel_container"
|
android:id="@+id/channel_container"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user