mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-28 07:50:31 +05:30
migrate watch positions to room
This commit is contained in:
parent
17626419a2
commit
3eadc46780
@ -4,11 +4,11 @@ import android.view.LayoutInflater
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.github.libretube.database.DatabaseHelper
|
||||||
import com.github.libretube.databinding.WatchHistoryRowBinding
|
import com.github.libretube.databinding.WatchHistoryRowBinding
|
||||||
import com.github.libretube.dialogs.VideoOptionsDialog
|
import com.github.libretube.dialogs.VideoOptionsDialog
|
||||||
import com.github.libretube.extensions.setFormattedDuration
|
import com.github.libretube.extensions.setFormattedDuration
|
||||||
import com.github.libretube.obj.WatchHistoryItem
|
import com.github.libretube.obj.WatchHistoryItem
|
||||||
import com.github.libretube.preferences.PreferenceHelper
|
|
||||||
import com.github.libretube.util.ConnectionHelper
|
import com.github.libretube.util.ConnectionHelper
|
||||||
import com.github.libretube.util.NavigationHelper
|
import com.github.libretube.util.NavigationHelper
|
||||||
import com.github.libretube.util.setWatchProgressLength
|
import com.github.libretube.util.setWatchProgressLength
|
||||||
@ -21,7 +21,7 @@ class WatchHistoryAdapter(
|
|||||||
private val TAG = "WatchHistoryAdapter"
|
private val TAG = "WatchHistoryAdapter"
|
||||||
|
|
||||||
fun removeFromWatchHistory(position: Int) {
|
fun removeFromWatchHistory(position: Int) {
|
||||||
PreferenceHelper.removeFromWatchHistory(position)
|
DatabaseHelper.removeFromWatchHistory(position)
|
||||||
watchHistory.removeAt(position)
|
watchHistory.removeAt(position)
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
@ -54,12 +54,12 @@ class WatchHistoryAdapter(
|
|||||||
NavigationHelper.navigateVideo(root.context, video.videoId)
|
NavigationHelper.navigateVideo(root.context, video.videoId)
|
||||||
}
|
}
|
||||||
root.setOnLongClickListener {
|
root.setOnLongClickListener {
|
||||||
VideoOptionsDialog(video.videoId!!)
|
VideoOptionsDialog(video.videoId)
|
||||||
.show(childFragmentManager, VideoOptionsDialog::class.java.name)
|
.show(childFragmentManager, VideoOptionsDialog::class.java.name)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
watchProgress.setWatchProgressLength(video.videoId!!, video.duration)
|
watchProgress.setWatchProgressLength(video.videoId, video.duration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,23 @@ package com.github.libretube.database
|
|||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import com.github.libretube.obj.WatchHistoryItem
|
import com.github.libretube.obj.WatchHistoryItem
|
||||||
|
import com.github.libretube.obj.WatchPosition
|
||||||
|
|
||||||
@Database(entities = [WatchHistoryItem::class], version = 1)
|
@Database(
|
||||||
|
entities = [
|
||||||
|
WatchHistoryItem::class,
|
||||||
|
WatchPosition::class
|
||||||
|
],
|
||||||
|
version = 2
|
||||||
|
)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
/**
|
||||||
|
* Watch History
|
||||||
|
*/
|
||||||
abstract fun watchHistoryDao(): WatchHistoryDao
|
abstract fun watchHistoryDao(): WatchHistoryDao
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch Positions
|
||||||
|
*/
|
||||||
|
abstract fun watchPositionDao(): WatchPositionDao
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.github.libretube.database
|
|||||||
|
|
||||||
import com.github.libretube.obj.Streams
|
import com.github.libretube.obj.Streams
|
||||||
import com.github.libretube.obj.WatchHistoryItem
|
import com.github.libretube.obj.WatchHistoryItem
|
||||||
|
import com.github.libretube.obj.WatchPosition
|
||||||
import com.github.libretube.util.toID
|
import com.github.libretube.util.toID
|
||||||
|
|
||||||
object DatabaseHelper {
|
object DatabaseHelper {
|
||||||
@ -20,4 +21,30 @@ object DatabaseHelper {
|
|||||||
DatabaseHolder.database.watchHistoryDao().insertAll(watchHistoryItem)
|
DatabaseHolder.database.watchHistoryDao().insertAll(watchHistoryItem)
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeFromWatchHistory(index: Int) {
|
||||||
|
Thread {
|
||||||
|
DatabaseHolder.database.watchHistoryDao().delete(
|
||||||
|
DatabaseHolder.database.watchHistoryDao().getAll()[index]
|
||||||
|
)
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveWatchPosition(videoId: String, position: Long) {
|
||||||
|
val watchPosition = WatchPosition(
|
||||||
|
videoId,
|
||||||
|
position
|
||||||
|
)
|
||||||
|
Thread {
|
||||||
|
DatabaseHolder.database.watchPositionDao().insertAll(watchPosition)
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeWatchPosition(videoId: String) {
|
||||||
|
Thread {
|
||||||
|
DatabaseHolder.database.watchPositionDao().delete(
|
||||||
|
DatabaseHolder.database.watchPositionDao().findById(videoId)
|
||||||
|
)
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ object DatabaseHolder {
|
|||||||
context,
|
context,
|
||||||
AppDatabase::class.java,
|
AppDatabase::class.java,
|
||||||
DATABASE_NAME
|
DATABASE_NAME
|
||||||
).build()
|
)
|
||||||
|
.fallbackToDestructiveMigration()
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.github.libretube.database
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
import androidx.room.Delete
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.github.libretube.obj.WatchHistoryItem
|
import com.github.libretube.obj.WatchHistoryItem
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ interface WatchHistoryDao {
|
|||||||
@Query("SELECT * FROM watchHistoryItem WHERE videoId LIKE :videoId LIMIT 1")
|
@Query("SELECT * FROM watchHistoryItem WHERE videoId LIKE :videoId LIMIT 1")
|
||||||
fun findById(videoId: String): WatchHistoryItem
|
fun findById(videoId: String): WatchHistoryItem
|
||||||
|
|
||||||
@Insert
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insertAll(vararg watchHistoryItems: WatchHistoryItem)
|
fun insertAll(vararg watchHistoryItems: WatchHistoryItem)
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.github.libretube.database
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import com.github.libretube.obj.WatchPosition
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface WatchPositionDao {
|
||||||
|
@Query("SELECT * FROM watchPosition")
|
||||||
|
fun getAll(): List<WatchPosition>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM watchPosition WHERE videoId LIKE :videoId LIMIT 1")
|
||||||
|
fun findById(videoId: String): WatchPosition
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun insertAll(vararg watchPositions: WatchPosition)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(watchPosition: WatchPosition)
|
||||||
|
}
|
@ -3,15 +3,23 @@ package com.github.libretube.util
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import com.github.libretube.preferences.PreferenceHelper
|
import com.github.libretube.database.DatabaseHolder
|
||||||
|
import com.github.libretube.obj.WatchPosition
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shows the already watched time under the video
|
* shows the already watched time under the video
|
||||||
*/
|
*/
|
||||||
fun View?.setWatchProgressLength(videoId: String, duration: Long) {
|
fun View?.setWatchProgressLength(videoId: String, duration: Long) {
|
||||||
val view = this!!
|
val view = this!!
|
||||||
val positions = PreferenceHelper.getWatchPositions()
|
var positions = listOf<WatchPosition>()
|
||||||
var newWidth: Long? = null
|
var newWidth: Long? = null
|
||||||
|
|
||||||
|
val thread = Thread {
|
||||||
|
positions = DatabaseHolder.database.watchPositionDao().getAll()
|
||||||
|
}
|
||||||
|
thread.start()
|
||||||
|
thread.join()
|
||||||
|
|
||||||
view.getViewTreeObserver()
|
view.getViewTreeObserver()
|
||||||
.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
|
.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||||
override fun onGlobalLayout() {
|
override fun onGlobalLayout() {
|
||||||
|
@ -38,6 +38,7 @@ import com.github.libretube.adapters.ChaptersAdapter
|
|||||||
import com.github.libretube.adapters.CommentsAdapter
|
import com.github.libretube.adapters.CommentsAdapter
|
||||||
import com.github.libretube.adapters.TrendingAdapter
|
import com.github.libretube.adapters.TrendingAdapter
|
||||||
import com.github.libretube.database.DatabaseHelper
|
import com.github.libretube.database.DatabaseHelper
|
||||||
|
import com.github.libretube.database.DatabaseHolder
|
||||||
import com.github.libretube.databinding.DoubleTapOverlayBinding
|
import com.github.libretube.databinding.DoubleTapOverlayBinding
|
||||||
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
|
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
|
||||||
import com.github.libretube.databinding.FragmentPlayerBinding
|
import com.github.libretube.databinding.FragmentPlayerBinding
|
||||||
@ -51,6 +52,7 @@ import com.github.libretube.obj.ChapterSegment
|
|||||||
import com.github.libretube.obj.Segment
|
import com.github.libretube.obj.Segment
|
||||||
import com.github.libretube.obj.Segments
|
import com.github.libretube.obj.Segments
|
||||||
import com.github.libretube.obj.Streams
|
import com.github.libretube.obj.Streams
|
||||||
|
import com.github.libretube.obj.WatchPosition
|
||||||
import com.github.libretube.preferences.PreferenceHelper
|
import com.github.libretube.preferences.PreferenceHelper
|
||||||
import com.github.libretube.preferences.PreferenceKeys
|
import com.github.libretube.preferences.PreferenceKeys
|
||||||
import com.github.libretube.services.BackgroundMode
|
import com.github.libretube.services.BackgroundMode
|
||||||
@ -444,8 +446,7 @@ class PlayerFragment : BaseFragment() {
|
|||||||
val newParams = if (index != 0) {
|
val newParams = if (index != 0) {
|
||||||
// caption selected
|
// caption selected
|
||||||
|
|
||||||
// get the caption name and language
|
// get the caption language code
|
||||||
val captionLanguage = subtitlesNamesList[index]
|
|
||||||
val captionLanguageCode = subtitleCodesList[index]
|
val captionLanguageCode = subtitleCodesList[index]
|
||||||
|
|
||||||
// select the new caption preference
|
// select the new caption preference
|
||||||
@ -814,13 +815,13 @@ class PlayerFragment : BaseFragment() {
|
|||||||
// save the watch position if video isn't finished and option enabled
|
// save the watch position if video isn't finished and option enabled
|
||||||
private fun saveWatchPosition() {
|
private fun saveWatchPosition() {
|
||||||
if (watchPositionsEnabled && exoPlayer.currentPosition != exoPlayer.duration) {
|
if (watchPositionsEnabled && exoPlayer.currentPosition != exoPlayer.duration) {
|
||||||
PreferenceHelper.saveWatchPosition(
|
DatabaseHelper.saveWatchPosition(
|
||||||
videoId!!,
|
videoId!!,
|
||||||
exoPlayer.currentPosition
|
exoPlayer.currentPosition
|
||||||
)
|
)
|
||||||
} else if (watchPositionsEnabled) {
|
} else if (watchPositionsEnabled) {
|
||||||
// delete watch position if video has ended
|
// delete watch position if video has ended
|
||||||
PreferenceHelper.removeWatchPosition(videoId!!)
|
DatabaseHelper.removeWatchPosition(videoId!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -934,7 +935,12 @@ class PlayerFragment : BaseFragment() {
|
|||||||
|
|
||||||
private fun seekToWatchPosition() {
|
private fun seekToWatchPosition() {
|
||||||
// seek to saved watch position if available
|
// seek to saved watch position if available
|
||||||
val watchPositions = PreferenceHelper.getWatchPositions()
|
var watchPositions = listOf<WatchPosition>()
|
||||||
|
val thread = Thread {
|
||||||
|
watchPositions = DatabaseHolder.database.watchPositionDao().getAll()
|
||||||
|
}
|
||||||
|
thread.start()
|
||||||
|
thread.join()
|
||||||
var position: Long? = null
|
var position: Long? = null
|
||||||
watchPositions.forEach {
|
watchPositions.forEach {
|
||||||
if (it.videoId == videoId &&
|
if (it.videoId == videoId &&
|
||||||
|
@ -12,7 +12,6 @@ import com.github.libretube.database.DatabaseHolder
|
|||||||
import com.github.libretube.databinding.FragmentWatchHistoryBinding
|
import com.github.libretube.databinding.FragmentWatchHistoryBinding
|
||||||
import com.github.libretube.extensions.BaseFragment
|
import com.github.libretube.extensions.BaseFragment
|
||||||
import com.github.libretube.obj.WatchHistoryItem
|
import com.github.libretube.obj.WatchHistoryItem
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
|
|
||||||
class WatchHistoryFragment : BaseFragment() {
|
class WatchHistoryFragment : BaseFragment() {
|
||||||
private val TAG = "WatchHistoryFragment"
|
private val TAG = "WatchHistoryFragment"
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package com.github.libretube.obj
|
package com.github.libretube.obj
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
|
||||||
|
@Entity
|
||||||
class CustomInstance(
|
class CustomInstance(
|
||||||
var name: String = "",
|
@ColumnInfo var name: String = "",
|
||||||
var apiUrl: String = "",
|
var apiUrl: String = "",
|
||||||
var frontendUrl: String = ""
|
var frontendUrl: String = ""
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
package com.github.libretube.obj
|
package com.github.libretube.obj
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "watchPosition")
|
||||||
data class WatchPosition(
|
data class WatchPosition(
|
||||||
val videoId: String = "",
|
@PrimaryKey val videoId: String = "",
|
||||||
val position: Long = 0L
|
@ColumnInfo val position: Long = 0L
|
||||||
)
|
)
|
||||||
|
@ -6,10 +6,6 @@ import androidx.preference.PreferenceManager
|
|||||||
import com.fasterxml.jackson.core.type.TypeReference
|
import com.fasterxml.jackson.core.type.TypeReference
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import com.github.libretube.obj.CustomInstance
|
import com.github.libretube.obj.CustomInstance
|
||||||
import com.github.libretube.obj.Streams
|
|
||||||
import com.github.libretube.obj.WatchHistoryItem
|
|
||||||
import com.github.libretube.obj.WatchPosition
|
|
||||||
import com.github.libretube.util.toID
|
|
||||||
|
|
||||||
object PreferenceHelper {
|
object PreferenceHelper {
|
||||||
private val TAG = "PreferenceHelper"
|
private val TAG = "PreferenceHelper"
|
||||||
@ -135,114 +131,6 @@ object PreferenceHelper {
|
|||||||
editor.putString("search_history", json).apply()
|
editor.putString("search_history", json).apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addToWatchHistory(videoId: String, streams: Streams) {
|
|
||||||
removeFromWatchHistory(videoId)
|
|
||||||
|
|
||||||
val watchHistoryItem = WatchHistoryItem(
|
|
||||||
videoId,
|
|
||||||
streams.title,
|
|
||||||
streams.uploadDate,
|
|
||||||
streams.uploader,
|
|
||||||
streams.uploaderUrl.toID(),
|
|
||||||
streams.uploaderAvatar,
|
|
||||||
streams.thumbnailUrl,
|
|
||||||
streams.duration
|
|
||||||
)
|
|
||||||
|
|
||||||
val watchHistory = getWatchHistory()
|
|
||||||
|
|
||||||
watchHistory += watchHistoryItem
|
|
||||||
|
|
||||||
// remove oldest item when the watch history is longer than the pref
|
|
||||||
val maxWatchHistorySize = getString(PreferenceKeys.WATCH_HISTORY_SIZE, "unlimited")
|
|
||||||
if (maxWatchHistorySize != "unlimited" && watchHistory.size > maxWatchHistorySize.toInt()) {
|
|
||||||
watchHistory.removeAt(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
val json = mapper.writeValueAsString(watchHistory)
|
|
||||||
editor.putString("watch_history", json).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeFromWatchHistory(videoId: String) {
|
|
||||||
val watchHistory = getWatchHistory()
|
|
||||||
|
|
||||||
var indexToRemove: Int? = null
|
|
||||||
watchHistory.forEachIndexed { index, item ->
|
|
||||||
if (item.videoId == videoId) indexToRemove = index
|
|
||||||
}
|
|
||||||
if (indexToRemove == null) return
|
|
||||||
watchHistory.removeAt(indexToRemove!!)
|
|
||||||
val json = mapper.writeValueAsString(watchHistory)
|
|
||||||
editor.putString("watch_history", json).commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeFromWatchHistory(position: Int) {
|
|
||||||
val watchHistory = getWatchHistory()
|
|
||||||
watchHistory.removeAt(position)
|
|
||||||
|
|
||||||
val json = mapper.writeValueAsString(watchHistory)
|
|
||||||
editor.putString("watch_history", json).commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWatchHistory(): ArrayList<WatchHistoryItem> {
|
|
||||||
val json: String = settings.getString("watch_history", "")!!
|
|
||||||
val type = mapper.typeFactory.constructCollectionType(
|
|
||||||
List::class.java,
|
|
||||||
WatchHistoryItem::class.java
|
|
||||||
)
|
|
||||||
|
|
||||||
return try {
|
|
||||||
mapper.readValue(json, type)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
arrayListOf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveWatchPosition(videoId: String, position: Long) {
|
|
||||||
val watchPositions = getWatchPositions()
|
|
||||||
val watchPositionItem = WatchPosition(videoId, position)
|
|
||||||
|
|
||||||
var indexToRemove: Int? = null
|
|
||||||
watchPositions.forEachIndexed { index, item ->
|
|
||||||
if (item.videoId == videoId) indexToRemove = index
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indexToRemove != null) watchPositions.removeAt(indexToRemove!!)
|
|
||||||
|
|
||||||
watchPositions += watchPositionItem
|
|
||||||
|
|
||||||
val json = mapper.writeValueAsString(watchPositions)
|
|
||||||
editor.putString("watch_positions", json).commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeWatchPosition(videoId: String) {
|
|
||||||
val watchPositions = getWatchPositions()
|
|
||||||
|
|
||||||
var indexToRemove: Int? = null
|
|
||||||
watchPositions.forEachIndexed { index, item ->
|
|
||||||
if (item.videoId == videoId) indexToRemove = index
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indexToRemove != null) watchPositions.removeAt(indexToRemove!!)
|
|
||||||
|
|
||||||
val json = mapper.writeValueAsString(watchPositions)
|
|
||||||
editor.putString("watch_positions", json).commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWatchPositions(): ArrayList<WatchPosition> {
|
|
||||||
val json: String = settings.getString("watch_positions", "")!!
|
|
||||||
val type = mapper.typeFactory.constructCollectionType(
|
|
||||||
List::class.java,
|
|
||||||
WatchPosition::class.java
|
|
||||||
)
|
|
||||||
|
|
||||||
return try {
|
|
||||||
mapper.readValue(json, type)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
arrayListOf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setLatestVideoId(videoId: String) {
|
fun setLatestVideoId(videoId: String) {
|
||||||
editor.putString(PreferenceKeys.LAST_STREAM_VIDEO_ID, videoId)
|
editor.putString(PreferenceKeys.LAST_STREAM_VIDEO_ID, videoId)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user