diff --git a/app/src/main/java/com/github/libretube/db/obj/WatchPosition.kt b/app/src/main/java/com/github/libretube/db/obj/WatchPosition.kt
index 2f6f0e050..50d953899 100644
--- a/app/src/main/java/com/github/libretube/db/obj/WatchPosition.kt
+++ b/app/src/main/java/com/github/libretube/db/obj/WatchPosition.kt
@@ -5,6 +5,9 @@ import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.serialization.Serializable
+/**
+ * @param position: Position in milliseconds
+ */
@Serializable
@Entity(tableName = "watchPosition")
data class WatchPosition(
diff --git a/app/src/main/java/com/github/libretube/ui/sheets/ChannelOptionsBottomSheet.kt b/app/src/main/java/com/github/libretube/ui/sheets/ChannelOptionsBottomSheet.kt
index f9f8795f4..321b10415 100644
--- a/app/src/main/java/com/github/libretube/ui/sheets/ChannelOptionsBottomSheet.kt
+++ b/app/src/main/java/com/github/libretube/ui/sheets/ChannelOptionsBottomSheet.kt
@@ -17,7 +17,7 @@ import kotlinx.coroutines.withContext
/**
* Dialog with different options for a selected video.
*
- * Needs the [videoId] to load the content from the right video.
+ * Needs the [channelId] to load the content from the right video.
*/
class ChannelOptionsBottomSheet(
private val channelId: String,
diff --git a/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt b/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt
index 5464e78c1..9b4724c00 100644
--- a/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt
+++ b/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt
@@ -10,21 +10,30 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R
import com.github.libretube.databinding.QueueBottomSheetBinding
+import com.github.libretube.db.DatabaseHelper
+import com.github.libretube.db.DatabaseHolder
+import com.github.libretube.db.obj.WatchPosition
+import com.github.libretube.extensions.toID
import com.github.libretube.ui.adapters.PlayingQueueAdapter
import com.github.libretube.ui.dialogs.AddToPlaylistDialog
import com.github.libretube.util.PlayingQueue
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.lang.IllegalArgumentException
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
class PlayingQueueSheet : ExpandedBottomSheet() {
- private lateinit var binding: QueueBottomSheetBinding
+ private var _binding: QueueBottomSheetBinding? = null
+ private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
- binding = QueueBottomSheetBinding.inflate(layoutInflater)
+ _binding = QueueBottomSheetBinding.inflate(layoutInflater)
return binding.root
}
@@ -89,6 +98,10 @@ class PlayingQueueSheet : ExpandedBottomSheet() {
dialog?.dismiss()
}
+ binding.watchPositionsOptions.setOnClickListener {
+ showWatchPositionsOptions()
+ }
+
val callback = object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
ItemTouchHelper.LEFT
@@ -141,7 +154,60 @@ class PlayingQueueSheet : ExpandedBottomSheet() {
else -> throw IllegalArgumentException()
}
PlayingQueue.setStreams(newQueue)
- binding.optionsRecycler.adapter?.notifyDataSetChanged()
+ _binding?.optionsRecycler?.adapter?.notifyDataSetChanged()
+ }
+ .show()
+ }
+
+ @SuppressLint("NotifyDataSetChanged")
+ private fun showWatchPositionsOptions() {
+ val options = arrayOf(
+ getString(R.string.mark_as_watched),
+ getString(R.string.mark_as_unwatched),
+ getString(R.string.remove_watched_videos)
+ )
+ MaterialAlertDialogBuilder(requireContext())
+ .setTitle(R.string.watch_positions)
+ .setItems(options) { _, index ->
+ when (index) {
+ 0 -> {
+ CoroutineScope(Dispatchers.IO).launch {
+ PlayingQueue.getStreams().forEach {
+ val videoId = it.url.orEmpty().toID()
+ val duration = it.duration ?: 0
+ val watchPosition = WatchPosition(videoId, duration * 1000)
+ DatabaseHolder.Database.watchPositionDao().insert(watchPosition)
+ }
+ }
+ }
+
+ 1 -> {
+ CoroutineScope(Dispatchers.IO).launch {
+ PlayingQueue.getStreams().forEach {
+ DatabaseHolder.Database.watchPositionDao()
+ .deleteByVideoId(it.url.orEmpty().toID())
+ }
+ }
+ }
+
+ 2 -> {
+ CoroutineScope(Dispatchers.IO).launch {
+ val currentStream = PlayingQueue.getCurrent()
+ val streams = DatabaseHelper
+ .filterUnwatched(PlayingQueue.getStreams())
+ .toMutableList()
+ if (currentStream != null &&
+ streams.none { it.url?.toID() == currentStream.url?.toID() }
+ ) {
+ streams.add(0, currentStream)
+ }
+ PlayingQueue.setStreams(streams)
+ withContext(Dispatchers.Main) {
+ _binding?.optionsRecycler?.adapter?.notifyDataSetChanged()
+ }
+ }
+ }
+ }
}
.show()
}
diff --git a/app/src/main/res/drawable/ic_eye.xml b/app/src/main/res/drawable/ic_eye.xml
new file mode 100644
index 000000000..9cd541120
--- /dev/null
+++ b/app/src/main/res/drawable/ic_eye.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/layout/queue_bottom_sheet.xml b/app/src/main/res/layout/queue_bottom_sheet.xml
index 0d55de50f..63f94d7d0 100644
--- a/app/src/main/res/layout/queue_bottom_sheet.xml
+++ b/app/src/main/res/layout/queue_bottom_sheet.xml
@@ -39,64 +39,42 @@
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 53de2cd0a..a773f66a4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -439,6 +439,7 @@
Sort by
Uploader name
Duration: %1$s
+ Remove watched videos
Import subscriptions from
diff --git a/app/src/main/res/values/style.xml b/app/src/main/res/values/style.xml
index 7af5319f4..46f67d8b7 100644
--- a/app/src/main/res/values/style.xml
+++ b/app/src/main/res/values/style.xml
@@ -248,4 +248,13 @@
+
+
\ No newline at end of file