mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-28 16:00:31 +05:30
refactor: improve proxy url rewriting, store only unproxied URLs in database
This commit is contained in:
parent
92dba354b6
commit
c15352a33d
@ -3,6 +3,7 @@ package com.github.libretube.api.obj
|
|||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import com.github.libretube.db.obj.DownloadItem
|
import com.github.libretube.db.obj.DownloadItem
|
||||||
import com.github.libretube.enums.FileType
|
import com.github.libretube.enums.FileType
|
||||||
|
import com.github.libretube.helpers.ProxyHelper
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlin.io.path.Path
|
import kotlin.io.path.Path
|
||||||
@ -40,7 +41,7 @@ data class PipedStream(
|
|||||||
videoId = videoId,
|
videoId = videoId,
|
||||||
fileName = getQualityString(fileName),
|
fileName = getQualityString(fileName),
|
||||||
path = Path(""),
|
path = Path(""),
|
||||||
url = url,
|
url = url?.let { ProxyHelper.unwrapUrl(it) },
|
||||||
format = format,
|
format = format,
|
||||||
quality = quality,
|
quality = quality,
|
||||||
language = audioTrackLocale,
|
language = audioTrackLocale,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.github.libretube.api.obj
|
package com.github.libretube.api.obj
|
||||||
|
|
||||||
import com.github.libretube.db.obj.PlaylistBookmark
|
import com.github.libretube.db.obj.PlaylistBookmark
|
||||||
|
import com.github.libretube.helpers.ProxyHelper
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -20,9 +21,9 @@ data class Playlist(
|
|||||||
return PlaylistBookmark(
|
return PlaylistBookmark(
|
||||||
playlistId = playlistId,
|
playlistId = playlistId,
|
||||||
playlistName = name,
|
playlistName = name,
|
||||||
thumbnailUrl = thumbnailUrl,
|
thumbnailUrl = thumbnailUrl?.let { ProxyHelper.unwrapUrl(it) },
|
||||||
uploader = uploader,
|
uploader = uploader,
|
||||||
uploaderAvatar = uploaderAvatar,
|
uploaderAvatar = uploaderAvatar?.let { ProxyHelper.unwrapUrl(it) },
|
||||||
uploaderUrl = uploaderUrl,
|
uploaderUrl = uploaderUrl,
|
||||||
videos = videos
|
videos = videos
|
||||||
)
|
)
|
||||||
|
@ -3,7 +3,10 @@ package com.github.libretube.api.obj
|
|||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import com.github.libretube.db.obj.LocalPlaylistItem
|
import com.github.libretube.db.obj.LocalPlaylistItem
|
||||||
import com.github.libretube.db.obj.SubscriptionsFeedItem
|
import com.github.libretube.db.obj.SubscriptionsFeedItem
|
||||||
|
import com.github.libretube.db.obj.WatchHistoryItem
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
|
import com.github.libretube.extensions.toLocalDate
|
||||||
|
import com.github.libretube.helpers.ProxyHelper
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@ -32,10 +35,10 @@ data class StreamItem(
|
|||||||
playlistId = playlistId.toInt(),
|
playlistId = playlistId.toInt(),
|
||||||
videoId = url!!.toID(),
|
videoId = url!!.toID(),
|
||||||
title = title,
|
title = title,
|
||||||
thumbnailUrl = thumbnail,
|
thumbnailUrl = thumbnail?.let { ProxyHelper.unwrapUrl(it) },
|
||||||
uploader = uploaderName,
|
uploader = uploaderName,
|
||||||
uploaderUrl = uploaderUrl,
|
uploaderUrl = uploaderUrl,
|
||||||
uploaderAvatar = uploaderAvatar,
|
uploaderAvatar = uploaderAvatar?.let { ProxyHelper.unwrapUrl(it) },
|
||||||
uploadDate = uploadedDate,
|
uploadDate = uploadedDate,
|
||||||
duration = duration
|
duration = duration
|
||||||
)
|
)
|
||||||
@ -56,6 +59,17 @@ data class StreamItem(
|
|||||||
isShort = isShort
|
isShort = isShort
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun toWatchHistoryItem(videoId: String) = WatchHistoryItem(
|
||||||
|
videoId = videoId,
|
||||||
|
title = title,
|
||||||
|
uploadDate = uploaded.toLocalDate(),
|
||||||
|
uploader = uploaderName,
|
||||||
|
uploaderUrl = uploaderUrl?.toID(),
|
||||||
|
uploaderAvatar = uploaderAvatar?.let { ProxyHelper.unwrapUrl(it) },
|
||||||
|
thumbnailUrl = thumbnail?.let { ProxyHelper.unwrapUrl(it) },
|
||||||
|
duration = duration
|
||||||
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TYPE_STREAM = "stream"
|
const val TYPE_STREAM = "stream"
|
||||||
const val TYPE_CHANNEL = "channel"
|
const val TYPE_CHANNEL = "channel"
|
||||||
|
@ -4,7 +4,6 @@ import android.os.Parcelable
|
|||||||
import com.github.libretube.db.obj.DownloadItem
|
import com.github.libretube.db.obj.DownloadItem
|
||||||
import com.github.libretube.enums.FileType
|
import com.github.libretube.enums.FileType
|
||||||
import com.github.libretube.extensions.toLocalDate
|
import com.github.libretube.extensions.toLocalDate
|
||||||
import com.github.libretube.helpers.ProxyHelper
|
|
||||||
import com.github.libretube.json.SafeInstantSerializer
|
import com.github.libretube.json.SafeInstantSerializer
|
||||||
import com.github.libretube.parcelable.DownloadData
|
import com.github.libretube.parcelable.DownloadData
|
||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
@ -12,7 +11,6 @@ import kotlinx.parcelize.IgnoredOnParcel
|
|||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlin.io.path.Path
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@ -75,17 +73,8 @@ data class Streams(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!subCode.isNullOrEmpty()) {
|
if (!subCode.isNullOrEmpty()) {
|
||||||
items.add(
|
val subtitle = subtitles.find { it.code == subCode }
|
||||||
DownloadItem(
|
subtitle?.toDownloadItem(id)?.let { items.add(it) }
|
||||||
type = FileType.SUBTITLE,
|
|
||||||
videoId = id,
|
|
||||||
fileName = "${name}_$subCode.srt",
|
|
||||||
path = Path(""),
|
|
||||||
url = subtitles.find {
|
|
||||||
it.code == subCode
|
|
||||||
}?.url?.let { ProxyHelper.unwrapUrl(it) }
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return items
|
return items
|
||||||
|
@ -3,8 +3,12 @@ package com.github.libretube.api.obj
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.db.obj.DownloadItem
|
||||||
|
import com.github.libretube.enums.FileType
|
||||||
|
import com.github.libretube.helpers.ProxyHelper
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlin.io.path.Path
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@ -20,4 +24,12 @@ data class Subtitle(
|
|||||||
} else {
|
} else {
|
||||||
"$name (${context.getString(R.string.auto_generated)})"
|
"$name (${context.getString(R.string.auto_generated)})"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun toDownloadItem(videoId: String) = DownloadItem(
|
||||||
|
type = FileType.SUBTITLE,
|
||||||
|
videoId = videoId,
|
||||||
|
fileName = "${name}_${code}.srt",
|
||||||
|
path = Path(""),
|
||||||
|
url = url?.let { ProxyHelper.unwrapUrl(it) }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
package com.github.libretube.db
|
package com.github.libretube.db
|
||||||
|
|
||||||
import com.github.libretube.api.obj.StreamItem
|
import com.github.libretube.api.obj.StreamItem
|
||||||
import com.github.libretube.api.obj.Streams
|
|
||||||
import com.github.libretube.constants.PreferenceKeys
|
import com.github.libretube.constants.PreferenceKeys
|
||||||
import com.github.libretube.db.DatabaseHolder.Database
|
import com.github.libretube.db.DatabaseHolder.Database
|
||||||
import com.github.libretube.db.obj.SearchHistoryItem
|
import com.github.libretube.db.obj.SearchHistoryItem
|
||||||
import com.github.libretube.db.obj.WatchHistoryItem
|
import com.github.libretube.db.obj.WatchHistoryItem
|
||||||
import com.github.libretube.enums.ContentFilter
|
import com.github.libretube.enums.ContentFilter
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
import com.github.libretube.extensions.toLocalDate
|
|
||||||
import com.github.libretube.helpers.PreferenceHelper
|
import com.github.libretube.helpers.PreferenceHelper
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
@ -17,26 +15,6 @@ import kotlinx.coroutines.withContext
|
|||||||
object DatabaseHelper {
|
object DatabaseHelper {
|
||||||
private const val MAX_SEARCH_HISTORY_SIZE = 20
|
private const val MAX_SEARCH_HISTORY_SIZE = 20
|
||||||
|
|
||||||
suspend fun addToWatchHistory(videoId: String, streams: Streams) = addToWatchHistory(
|
|
||||||
videoId,
|
|
||||||
streams.toStreamItem(videoId)
|
|
||||||
)
|
|
||||||
|
|
||||||
suspend fun addToWatchHistory(videoId: String, stream: StreamItem) {
|
|
||||||
val watchHistoryItem = WatchHistoryItem(
|
|
||||||
videoId,
|
|
||||||
stream.title,
|
|
||||||
stream.uploaded.toLocalDate(),
|
|
||||||
stream.uploaderName,
|
|
||||||
stream.uploaderUrl?.toID(),
|
|
||||||
stream.uploaderAvatar,
|
|
||||||
stream.thumbnail,
|
|
||||||
stream.duration
|
|
||||||
)
|
|
||||||
|
|
||||||
addToWatchHistory(watchHistoryItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun addToWatchHistory(watchHistoryItem: WatchHistoryItem) =
|
suspend fun addToWatchHistory(watchHistoryItem: WatchHistoryItem) =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
Database.watchHistoryDao().insert(watchHistoryItem)
|
Database.watchHistoryDao().insert(watchHistoryItem)
|
||||||
|
@ -4,7 +4,6 @@ import androidx.room.ColumnInfo
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import com.github.libretube.api.obj.StreamItem
|
import com.github.libretube.api.obj.StreamItem
|
||||||
import com.github.libretube.helpers.ProxyHelper
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -25,10 +24,10 @@ data class LocalPlaylistItem(
|
|||||||
return StreamItem(
|
return StreamItem(
|
||||||
url = videoId,
|
url = videoId,
|
||||||
title = title,
|
title = title,
|
||||||
thumbnail = ProxyHelper.rewriteUrl(thumbnailUrl),
|
thumbnail = thumbnailUrl,
|
||||||
uploaderName = uploader,
|
uploaderName = uploader,
|
||||||
uploaderUrl = uploaderUrl,
|
uploaderUrl = uploaderUrl,
|
||||||
uploaderAvatar = ProxyHelper.rewriteUrl(uploaderAvatar),
|
uploaderAvatar = uploaderAvatar,
|
||||||
uploadedDate = uploadDate,
|
uploadedDate = uploadDate,
|
||||||
duration = duration
|
duration = duration
|
||||||
)
|
)
|
||||||
|
@ -57,7 +57,7 @@ object DashHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// only unwraps the url if the preference is set in the settings
|
// only unwraps the url if the preference is set in the settings
|
||||||
stream.url = ProxyHelper.unwrapStreamUrl(stream.url.orEmpty())
|
stream.url = ProxyHelper.rewriteUrlUsingProxyPreference(stream.url.orEmpty())
|
||||||
|
|
||||||
val adapSetInfo = adapSetInfos.find { it.mimeType == stream.mimeType }
|
val adapSetInfo = adapSetInfos.find { it.mimeType == stream.mimeType }
|
||||||
if (adapSetInfo != null) {
|
if (adapSetInfo != null) {
|
||||||
@ -83,7 +83,7 @@ object DashHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// only unwraps the url if the preference is set in the settings
|
// only unwraps the url if the preference is set in the settings
|
||||||
stream.url = ProxyHelper.unwrapStreamUrl(stream.url.orEmpty())
|
stream.url = ProxyHelper.rewriteUrlUsingProxyPreference(stream.url.orEmpty())
|
||||||
|
|
||||||
adapSetInfos.add(
|
adapSetInfos.add(
|
||||||
AdapSetInfo(
|
AdapSetInfo(
|
||||||
|
@ -87,7 +87,7 @@ object ImageHelper {
|
|||||||
|
|
||||||
// only load the image if the data saver mode is disabled
|
// only load the image if the data saver mode is disabled
|
||||||
if (DataSaverMode.isEnabled(target.context) || url.isNullOrEmpty()) return
|
if (DataSaverMode.isEnabled(target.context) || url.isNullOrEmpty()) return
|
||||||
val urlToLoad = ProxyHelper.unwrapImageUrl(url)
|
val urlToLoad = ProxyHelper.rewriteUrlUsingProxyPreference(url)
|
||||||
|
|
||||||
getImageWithCallback(target.context, urlToLoad) { result ->
|
getImageWithCallback(target.context, urlToLoad) { result ->
|
||||||
// set the background to white for transparent images
|
// set the background to white for transparent images
|
||||||
|
@ -18,14 +18,31 @@ object ProxyHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rewriteUrl(url: String?): String? {
|
/**
|
||||||
|
* Decide whether the proxy should be used or not for a given stream URL based on user preferences
|
||||||
|
*/
|
||||||
|
fun rewriteUrlUsingProxyPreference(url: String): String {
|
||||||
|
if (PlayerHelper.disablePipedProxy) {
|
||||||
|
return unwrapUrl(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxyRewriteUrl(url) ?: url
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rewrite the URL to use the stored image proxy url of the selected instance.
|
||||||
|
* Can handle both Piped links and normal YouTube links.
|
||||||
|
*/
|
||||||
|
private fun proxyRewriteUrl(url: String?): String? {
|
||||||
if (url == null) return null
|
if (url == null) return null
|
||||||
|
|
||||||
val proxyUrl = PreferenceHelper.getString(PreferenceKeys.IMAGE_PROXY_URL, "")
|
val proxyUrl = PreferenceHelper.getString(PreferenceKeys.IMAGE_PROXY_URL, "")
|
||||||
.toHttpUrlOrNull() ?: return url
|
.toHttpUrlOrNull()
|
||||||
|
|
||||||
|
// parsedUrl should now be a plain YouTube URL without using any proxy
|
||||||
|
val parsedUrl = unwrapUrl(url).toHttpUrlOrNull()
|
||||||
|
if (proxyUrl == null || parsedUrl == null) return null
|
||||||
|
|
||||||
val parsedUrl = url.toHttpUrlOrNull() ?: return url
|
|
||||||
if (parsedUrl.queryParameter("host").isNullOrEmpty()) {
|
|
||||||
return parsedUrl.newBuilder()
|
return parsedUrl.newBuilder()
|
||||||
.host(proxyUrl.host)
|
.host(proxyUrl.host)
|
||||||
.port(proxyUrl.port)
|
.port(proxyUrl.port)
|
||||||
@ -34,42 +51,17 @@ object ProxyHelper {
|
|||||||
.toString()
|
.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsedUrl.newBuilder()
|
|
||||||
.host(proxyUrl.host)
|
|
||||||
.port(proxyUrl.port)
|
|
||||||
.build()
|
|
||||||
.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect whether the proxy should be used or not for a given stream URL based on user preferences
|
|
||||||
*/
|
|
||||||
fun unwrapStreamUrl(url: String): String {
|
|
||||||
return if (PlayerHelper.disablePipedProxy && !PlayerHelper.localStreamExtraction) {
|
|
||||||
unwrapUrl(url)
|
|
||||||
} else {
|
|
||||||
url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun unwrapImageUrl(url: String): String {
|
|
||||||
return if (PlayerHelper.disablePipedProxy) {
|
|
||||||
unwrapUrl(url)
|
|
||||||
} else {
|
|
||||||
url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a proxied Piped url to a YouTube url that's not proxied
|
* Convert a proxied Piped url to a YouTube url that's not proxied
|
||||||
|
*
|
||||||
|
* Should not be called directly in most cases, use [rewriteUrlUsingProxyPreference] instead
|
||||||
*/
|
*/
|
||||||
fun unwrapUrl(url: String, unwrap: Boolean = true): String {
|
fun unwrapUrl(url: String): String {
|
||||||
val parsedUrl = url.toHttpUrlOrNull()
|
val parsedUrl = url.toHttpUrlOrNull() ?: return url
|
||||||
|
|
||||||
val host = parsedUrl?.queryParameter("host")
|
val host = parsedUrl.queryParameter("host")
|
||||||
// if there's no host parameter specified, there's no way to unwrap the URL
|
// If the host is not set, the URL is probably already unwrapped
|
||||||
// and the proxied one must be used. That's the case if using LBRY.
|
if (host.isNullOrEmpty()) {
|
||||||
if (!unwrap || parsedUrl == null || host.isNullOrEmpty()) {
|
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import com.github.libretube.api.obj.StreamItem
|
|||||||
import com.github.libretube.db.DatabaseHolder
|
import com.github.libretube.db.DatabaseHolder
|
||||||
import com.github.libretube.db.obj.LocalPlaylist
|
import com.github.libretube.db.obj.LocalPlaylist
|
||||||
import com.github.libretube.extensions.parallelMap
|
import com.github.libretube.extensions.parallelMap
|
||||||
import com.github.libretube.helpers.ProxyHelper
|
|
||||||
import com.github.libretube.obj.PipedImportPlaylist
|
import com.github.libretube.obj.PipedImportPlaylist
|
||||||
|
|
||||||
class LocalPlaylistsRepository: PlaylistRepository {
|
class LocalPlaylistsRepository: PlaylistRepository {
|
||||||
@ -21,7 +20,7 @@ class LocalPlaylistsRepository: PlaylistRepository {
|
|||||||
return Playlist(
|
return Playlist(
|
||||||
name = relation.playlist.name,
|
name = relation.playlist.name,
|
||||||
description = relation.playlist.description,
|
description = relation.playlist.description,
|
||||||
thumbnailUrl = ProxyHelper.rewriteUrl(relation.playlist.thumbnailUrl),
|
thumbnailUrl = relation.playlist.thumbnailUrl,
|
||||||
videos = relation.videos.size,
|
videos = relation.videos.size,
|
||||||
relatedStreams = relation.videos.map { it.toStreamItem() }
|
relatedStreams = relation.videos.map { it.toStreamItem() }
|
||||||
)
|
)
|
||||||
@ -34,7 +33,7 @@ class LocalPlaylistsRepository: PlaylistRepository {
|
|||||||
id = it.playlist.id.toString(),
|
id = it.playlist.id.toString(),
|
||||||
name = it.playlist.name,
|
name = it.playlist.name,
|
||||||
shortDescription = it.playlist.description,
|
shortDescription = it.playlist.description,
|
||||||
thumbnail = ProxyHelper.rewriteUrl(it.playlist.thumbnailUrl),
|
thumbnail = it.playlist.thumbnailUrl,
|
||||||
videos = it.videos.size.toLong()
|
videos = it.videos.size.toLong()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ class DownloadService : LifecycleService() {
|
|||||||
setResumeNotification(notificationBuilder, item)
|
setResumeNotification(notificationBuilder, item)
|
||||||
|
|
||||||
var totalRead = item.path.fileSize()
|
var totalRead = item.path.fileSize()
|
||||||
val url = URL(ProxyHelper.unwrapStreamUrl(item.url ?: return))
|
val url = URL(ProxyHelper.rewriteUrlUsingProxyPreference(item.url ?: return))
|
||||||
|
|
||||||
// only fetch the content length if it's not been returned by the API
|
// only fetch the content length if it's not been returned by the API
|
||||||
if (item.downloadSize <= 0L) {
|
if (item.downloadSize <= 0L) {
|
||||||
|
@ -90,7 +90,11 @@ open class OnlinePlayerService : AbstractPlayerService() {
|
|||||||
// waiting for the player to be ready since the video can't be claimed to be watched
|
// waiting for the player to be ready since the video can't be claimed to be watched
|
||||||
// while it did not yet start actually, but did buffer only so far
|
// while it did not yet start actually, but did buffer only so far
|
||||||
scope.launch(Dispatchers.IO) {
|
scope.launch(Dispatchers.IO) {
|
||||||
streams?.let { DatabaseHelper.addToWatchHistory(videoId, it) }
|
streams?.let { streams ->
|
||||||
|
val watchHistoryItem =
|
||||||
|
streams.toStreamItem(videoId).toWatchHistoryItem(videoId)
|
||||||
|
DatabaseHelper.addToWatchHistory(watchHistoryItem)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,7 +245,8 @@ open class OnlinePlayerService : AbstractPlayerService() {
|
|||||||
if (args.containsKey(PlayerCommand.SET_SB_AUTO_SKIP_ENABLED.name)) {
|
if (args.containsKey(PlayerCommand.SET_SB_AUTO_SKIP_ENABLED.name)) {
|
||||||
sponsorBlockAutoSkip = args.getBoolean(PlayerCommand.SET_SB_AUTO_SKIP_ENABLED.name)
|
sponsorBlockAutoSkip = args.getBoolean(PlayerCommand.SET_SB_AUTO_SKIP_ENABLED.name)
|
||||||
} else if (args.containsKey(PlayerCommand.SET_AUTOPLAY_COUNTDOWN_ENABLED.name)) {
|
} else if (args.containsKey(PlayerCommand.SET_AUTOPLAY_COUNTDOWN_ENABLED.name)) {
|
||||||
autoPlayCountdownEnabled = args.getBoolean(PlayerCommand.SET_AUTOPLAY_COUNTDOWN_ENABLED.name)
|
autoPlayCountdownEnabled =
|
||||||
|
args.getBoolean(PlayerCommand.SET_AUTOPLAY_COUNTDOWN_ENABLED.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +277,7 @@ open class OnlinePlayerService : AbstractPlayerService() {
|
|||||||
// only use the dash manifest generated by YT if either it's a livestream or no other source is available
|
// only use the dash manifest generated by YT if either it's a livestream or no other source is available
|
||||||
val dashUri =
|
val dashUri =
|
||||||
if (streams.isLive && streams.dash != null) {
|
if (streams.isLive && streams.dash != null) {
|
||||||
ProxyHelper.unwrapStreamUrl(
|
ProxyHelper.rewriteUrlUsingProxyPreference(
|
||||||
streams.dash
|
streams.dash
|
||||||
).toUri()
|
).toUri()
|
||||||
} else {
|
} else {
|
||||||
@ -289,7 +294,7 @@ open class OnlinePlayerService : AbstractPlayerService() {
|
|||||||
.setPlaylistParserFactory(YoutubeHlsPlaylistParser.Factory())
|
.setPlaylistParserFactory(YoutubeHlsPlaylistParser.Factory())
|
||||||
|
|
||||||
val mediaItem = createMediaItem(
|
val mediaItem = createMediaItem(
|
||||||
ProxyHelper.unwrapStreamUrl(streams.hls).toUri(),
|
ProxyHelper.rewriteUrlUsingProxyPreference(streams.hls).toUri(),
|
||||||
MimeTypes.APPLICATION_M3U8,
|
MimeTypes.APPLICATION_M3U8,
|
||||||
streams
|
streams
|
||||||
)
|
)
|
||||||
|
@ -29,7 +29,6 @@ import com.github.libretube.extensions.ceilHalf
|
|||||||
import com.github.libretube.extensions.dpToPx
|
import com.github.libretube.extensions.dpToPx
|
||||||
import com.github.libretube.helpers.NavBarHelper
|
import com.github.libretube.helpers.NavBarHelper
|
||||||
import com.github.libretube.helpers.PreferenceHelper
|
import com.github.libretube.helpers.PreferenceHelper
|
||||||
import com.github.libretube.helpers.ProxyHelper
|
|
||||||
import com.github.libretube.ui.adapters.PlaylistBookmarkAdapter
|
import com.github.libretube.ui.adapters.PlaylistBookmarkAdapter
|
||||||
import com.github.libretube.ui.adapters.PlaylistsAdapter
|
import com.github.libretube.ui.adapters.PlaylistsAdapter
|
||||||
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
||||||
@ -146,9 +145,7 @@ class LibraryFragment : DynamicLayoutManagerFragment() {
|
|||||||
private fun initBookmarks() {
|
private fun initBookmarks() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val bookmarks = withContext(Dispatchers.IO) {
|
val bookmarks = withContext(Dispatchers.IO) {
|
||||||
DatabaseHolder.Database.playlistBookmarkDao().getAll().map {
|
DatabaseHolder.Database.playlistBookmarkDao().getAll()
|
||||||
it.copy(thumbnailUrl = ProxyHelper.rewriteUrl(it.thumbnailUrl))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val binding = _binding ?: return@launch
|
val binding = _binding ?: return@launch
|
||||||
|
@ -683,7 +683,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
val context = requireContext()
|
val context = requireContext()
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val hlsStream = withContext(Dispatchers.IO) {
|
val hlsStream = withContext(Dispatchers.IO) {
|
||||||
ProxyHelper.unwrapStreamUrl(streams.hls!!).toUri()
|
ProxyHelper.rewriteUrlUsingProxyPreference(streams.hls!!).toUri()
|
||||||
}
|
}
|
||||||
IntentHelper.openWithExternalPlayer(
|
IntentHelper.openWithExternalPlayer(
|
||||||
context,
|
context,
|
||||||
|
@ -29,7 +29,6 @@ import com.github.libretube.extensions.setOnDismissListener
|
|||||||
import com.github.libretube.helpers.NavBarHelper
|
import com.github.libretube.helpers.NavBarHelper
|
||||||
import com.github.libretube.helpers.NavigationHelper
|
import com.github.libretube.helpers.NavigationHelper
|
||||||
import com.github.libretube.helpers.PreferenceHelper
|
import com.github.libretube.helpers.PreferenceHelper
|
||||||
import com.github.libretube.helpers.ProxyHelper
|
|
||||||
import com.github.libretube.ui.adapters.WatchHistoryAdapter
|
import com.github.libretube.ui.adapters.WatchHistoryAdapter
|
||||||
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
||||||
import com.github.libretube.ui.extensions.addOnBottomReachedListener
|
import com.github.libretube.ui.extensions.addOnBottomReachedListener
|
||||||
@ -168,12 +167,6 @@ class WatchHistoryFragment : DynamicLayoutManagerFragment() {
|
|||||||
|
|
||||||
private fun showWatchHistory(history: List<WatchHistoryItem>) {
|
private fun showWatchHistory(history: List<WatchHistoryItem>) {
|
||||||
val watchHistory = history.filterByStatusAndWatchPosition()
|
val watchHistory = history.filterByStatusAndWatchPosition()
|
||||||
|
|
||||||
watchHistory.forEach {
|
|
||||||
it.thumbnailUrl = ProxyHelper.rewriteUrl(it.thumbnailUrl)
|
|
||||||
it.uploaderAvatar = ProxyHelper.rewriteUrl(it.uploaderAvatar)
|
|
||||||
}
|
|
||||||
|
|
||||||
val watchHistoryAdapter = WatchHistoryAdapter(watchHistory.toMutableList())
|
val watchHistoryAdapter = WatchHistoryAdapter(watchHistory.toMutableList())
|
||||||
|
|
||||||
binding.playAll.setOnClickListener {
|
binding.playAll.setOnClickListener {
|
||||||
|
@ -103,7 +103,7 @@ class VideoOptionsBottomSheet : BaseBottomSheet() {
|
|||||||
DatabaseHolder.Database.watchPositionDao().insert(watchPosition)
|
DatabaseHolder.Database.watchPositionDao().insert(watchPosition)
|
||||||
if (!PlayerHelper.watchHistoryEnabled) return@withContext
|
if (!PlayerHelper.watchHistoryEnabled) return@withContext
|
||||||
// add video to watch history
|
// add video to watch history
|
||||||
DatabaseHelper.addToWatchHistory(videoId, streamItem)
|
DatabaseHelper.addToWatchHistory(streamItem.toWatchHistoryItem(videoId))
|
||||||
}
|
}
|
||||||
if (PreferenceHelper.getBoolean(PreferenceKeys.HIDE_WATCHED_FROM_FEED, false)) {
|
if (PreferenceHelper.getBoolean(PreferenceKeys.HIDE_WATCHED_FROM_FEED, false)) {
|
||||||
// get the host fragment containing the current fragment
|
// get the host fragment containing the current fragment
|
||||||
|
Loading…
x
Reference in New Issue
Block a user