migrate watch positions to room

This commit is contained in:
Bnyro 2022-08-13 22:03:11 +02:00
parent 17626419a2
commit 3eadc46780
12 changed files with 108 additions and 130 deletions

View File

@ -4,11 +4,11 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.database.DatabaseHelper
import com.github.libretube.databinding.WatchHistoryRowBinding
import com.github.libretube.dialogs.VideoOptionsDialog
import com.github.libretube.extensions.setFormattedDuration
import com.github.libretube.obj.WatchHistoryItem
import com.github.libretube.preferences.PreferenceHelper
import com.github.libretube.util.ConnectionHelper
import com.github.libretube.util.NavigationHelper
import com.github.libretube.util.setWatchProgressLength
@ -21,7 +21,7 @@ class WatchHistoryAdapter(
private val TAG = "WatchHistoryAdapter"
fun removeFromWatchHistory(position: Int) {
PreferenceHelper.removeFromWatchHistory(position)
DatabaseHelper.removeFromWatchHistory(position)
watchHistory.removeAt(position)
notifyDataSetChanged()
}
@ -54,12 +54,12 @@ class WatchHistoryAdapter(
NavigationHelper.navigateVideo(root.context, video.videoId)
}
root.setOnLongClickListener {
VideoOptionsDialog(video.videoId!!)
VideoOptionsDialog(video.videoId)
.show(childFragmentManager, VideoOptionsDialog::class.java.name)
true
}
watchProgress.setWatchProgressLength(video.videoId!!, video.duration)
watchProgress.setWatchProgressLength(video.videoId, video.duration)
}
}

View File

@ -3,8 +3,23 @@ package com.github.libretube.database
import androidx.room.Database
import androidx.room.RoomDatabase
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() {
/**
* Watch History
*/
abstract fun watchHistoryDao(): WatchHistoryDao
/**
* Watch Positions
*/
abstract fun watchPositionDao(): WatchPositionDao
}

View File

@ -2,6 +2,7 @@ package com.github.libretube.database
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 DatabaseHelper {
@ -20,4 +21,30 @@ object DatabaseHelper {
DatabaseHolder.database.watchHistoryDao().insertAll(watchHistoryItem)
}.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()
}
}

View File

@ -12,6 +12,8 @@ object DatabaseHolder {
context,
AppDatabase::class.java,
DATABASE_NAME
).build()
)
.fallbackToDestructiveMigration()
.build()
}
}

View File

@ -3,6 +3,7 @@ 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.WatchHistoryItem
@ -14,7 +15,7 @@ interface WatchHistoryDao {
@Query("SELECT * FROM watchHistoryItem WHERE videoId LIKE :videoId LIMIT 1")
fun findById(videoId: String): WatchHistoryItem
@Insert
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(vararg watchHistoryItems: WatchHistoryItem)
@Delete

View File

@ -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)
}

View File

@ -3,15 +3,23 @@ package com.github.libretube.util
import android.view.View
import android.view.ViewTreeObserver
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
*/
fun View?.setWatchProgressLength(videoId: String, duration: Long) {
val view = this!!
val positions = PreferenceHelper.getWatchPositions()
var positions = listOf<WatchPosition>()
var newWidth: Long? = null
val thread = Thread {
positions = DatabaseHolder.database.watchPositionDao().getAll()
}
thread.start()
thread.join()
view.getViewTreeObserver()
.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {

View File

@ -38,6 +38,7 @@ import com.github.libretube.adapters.ChaptersAdapter
import com.github.libretube.adapters.CommentsAdapter
import com.github.libretube.adapters.TrendingAdapter
import com.github.libretube.database.DatabaseHelper
import com.github.libretube.database.DatabaseHolder
import com.github.libretube.databinding.DoubleTapOverlayBinding
import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding
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.Segments
import com.github.libretube.obj.Streams
import com.github.libretube.obj.WatchPosition
import com.github.libretube.preferences.PreferenceHelper
import com.github.libretube.preferences.PreferenceKeys
import com.github.libretube.services.BackgroundMode
@ -444,8 +446,7 @@ class PlayerFragment : BaseFragment() {
val newParams = if (index != 0) {
// caption selected
// get the caption name and language
val captionLanguage = subtitlesNamesList[index]
// get the caption language code
val captionLanguageCode = subtitleCodesList[index]
// select the new caption preference
@ -814,13 +815,13 @@ class PlayerFragment : BaseFragment() {
// save the watch position if video isn't finished and option enabled
private fun saveWatchPosition() {
if (watchPositionsEnabled && exoPlayer.currentPosition != exoPlayer.duration) {
PreferenceHelper.saveWatchPosition(
DatabaseHelper.saveWatchPosition(
videoId!!,
exoPlayer.currentPosition
)
} else if (watchPositionsEnabled) {
// delete watch position if video has ended
PreferenceHelper.removeWatchPosition(videoId!!)
DatabaseHelper.removeWatchPosition(videoId!!)
}
}
@ -934,7 +935,12 @@ class PlayerFragment : BaseFragment() {
private fun seekToWatchPosition() {
// 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
watchPositions.forEach {
if (it.videoId == videoId &&

View File

@ -12,7 +12,6 @@ import com.github.libretube.database.DatabaseHolder
import com.github.libretube.databinding.FragmentWatchHistoryBinding
import com.github.libretube.extensions.BaseFragment
import com.github.libretube.obj.WatchHistoryItem
import kotlinx.coroutines.runBlocking
class WatchHistoryFragment : BaseFragment() {
private val TAG = "WatchHistoryFragment"

View File

@ -1,7 +1,11 @@
package com.github.libretube.obj
import androidx.room.ColumnInfo
import androidx.room.Entity
@Entity
class CustomInstance(
var name: String = "",
@ColumnInfo var name: String = "",
var apiUrl: String = "",
var frontendUrl: String = ""
)

View File

@ -1,6 +1,11 @@
package com.github.libretube.obj
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "watchPosition")
data class WatchPosition(
val videoId: String = "",
val position: Long = 0L
@PrimaryKey val videoId: String = "",
@ColumnInfo val position: Long = 0L
)

View File

@ -6,10 +6,6 @@ import androidx.preference.PreferenceManager
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.ObjectMapper
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 {
private val TAG = "PreferenceHelper"
@ -135,114 +131,6 @@ object PreferenceHelper {
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) {
editor.putString(PreferenceKeys.LAST_STREAM_VIDEO_ID, videoId)
}