mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2026-05-16 04:52:39 +02:00
Fixed thumbnail to consider max size 1920 and fitcenter and implemented fixes for pagination of library.
This commit is contained in:
@@ -43,6 +43,8 @@ import java.util.concurrent.ThreadLocalRandom
|
|||||||
import java.util.zip.GZIPInputStream
|
import java.util.zip.GZIPInputStream
|
||||||
import java.util.zip.GZIPOutputStream
|
import java.util.zip.GZIPOutputStream
|
||||||
import androidx.core.graphics.scale
|
import androidx.core.graphics.scale
|
||||||
|
import com.bumptech.glide.RequestBuilder
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
|
||||||
|
|
||||||
private val _allowedCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ";
|
private val _allowedCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ";
|
||||||
fun getRandomString(sizeOfRandomString: Int): String {
|
fun getRandomString(sizeOfRandomString: Int): String {
|
||||||
@@ -440,4 +442,17 @@ fun addressScore(addr: InetAddress): Int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> Enumeration<T>.toList(): List<T> = Collections.list(this)
|
fun <T> Enumeration<T>.toList(): List<T> = Collections.list(this)
|
||||||
|
|
||||||
|
fun <T> RequestBuilder<T>.withMaxSizePx(maxSizePx: Int = 1920, useCenterCrop: Boolean = false): RequestBuilder<T> {
|
||||||
|
var builder = this
|
||||||
|
.downsample(DownsampleStrategy.AT_MOST)
|
||||||
|
.override(maxSizePx, maxSizePx)
|
||||||
|
builder = if (useCenterCrop) {
|
||||||
|
builder.centerCrop()
|
||||||
|
} else {
|
||||||
|
builder.fitCenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder
|
||||||
|
}
|
||||||
@@ -55,7 +55,7 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
|||||||
protected val _toolbarContentView: LinearLayout;
|
protected val _toolbarContentView: LinearLayout;
|
||||||
protected val _bottomContentView: LinearLayout;
|
protected val _bottomContentView: LinearLayout;
|
||||||
|
|
||||||
private var _loading: Boolean = true;
|
private var _loading: Boolean = false;
|
||||||
|
|
||||||
private val _pagerLock = Object();
|
private val _pagerLock = Object();
|
||||||
private var _cache: ItemCache<TResult>? = null;
|
private var _cache: ItemCache<TResult>? = null;
|
||||||
@@ -180,10 +180,9 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
|||||||
|
|
||||||
val visibleItemCount = _recyclerResults.childCount;
|
val visibleItemCount = _recyclerResults.childCount;
|
||||||
val firstVisibleItem = recyclerData.layoutManager.findFirstVisibleItemPosition()
|
val firstVisibleItem = recyclerData.layoutManager.findFirstVisibleItemPosition()
|
||||||
//Logger.i(TAG, "onScrolled loadNextPage visibleItemCount=$visibleItemCount firstVisibleItem=$visibleItemCount")
|
//Logger.i(TAG, "onScrolled loadNextPage(): firstVisibleItem=$firstVisibleItem visibleItemCount=$visibleItemCount visibleThreshold=$visibleThreshold recyclerData.results.size=${recyclerData.results.size}")
|
||||||
|
|
||||||
if (!_loading && firstVisibleItem + visibleItemCount + visibleThreshold >= recyclerData.results.size && firstVisibleItem > 0) {
|
if (!_loading && firstVisibleItem + visibleItemCount + visibleThreshold >= recyclerData.results.size) {
|
||||||
//Logger.i(TAG, "onScrolled loadNextPage(): firstVisibleItem=$firstVisibleItem visibleItemCount=$visibleItemCount visibleThreshold=$visibleThreshold recyclerData.results.size=${recyclerData.results.size}")
|
|
||||||
loadNextPage();
|
loadNextPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,57 +196,44 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun ensureEnoughContentVisible(filteredResults: List<TConverted>) {
|
private fun ensureEnoughContentVisible(filteredResults: List<TConverted>) {
|
||||||
val canScroll = if (recyclerData.results.isEmpty()) false else {
|
_recyclerResults.post {
|
||||||
val height = resources.displayMetrics.heightPixels;
|
val canScroll = _recyclerResults.canScrollVertically(1)
|
||||||
|
Logger.i(
|
||||||
|
TAG,
|
||||||
|
"ensureEnoughContentVisible loadNextPage canScroll=$canScroll _automaticNextPageCounter=$_automaticNextPageCounter"
|
||||||
|
)
|
||||||
|
if (!canScroll || filteredResults.isEmpty()) {
|
||||||
|
_automaticNextPageCounter++
|
||||||
|
if (_automaticNextPageCounter < _automaticBackoff.size) {
|
||||||
|
if (_automaticNextPageCounter > 0) {
|
||||||
|
val automaticNextPageCounterSaved = _automaticNextPageCounter;
|
||||||
|
fragment.lifecycleScope.launch(Dispatchers.Default) {
|
||||||
|
val backoff = _automaticBackoff[Math.min(
|
||||||
|
_automaticBackoff.size - 1,
|
||||||
|
_automaticNextPageCounter
|
||||||
|
)];
|
||||||
|
|
||||||
val layoutManager = recyclerData.layoutManager
|
|
||||||
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
|
|
||||||
val firstVisibleItemView = if(firstVisibleItemPosition != RecyclerView.NO_POSITION) layoutManager.findViewByPosition(firstVisibleItemPosition) else null;
|
|
||||||
val lastVisibleItemPosition = layoutManager.findLastCompletelyVisibleItemPosition();
|
|
||||||
val lastVisibleItemView = if(lastVisibleItemPosition != RecyclerView.NO_POSITION) layoutManager.findViewByPosition(lastVisibleItemPosition) else null;
|
|
||||||
val rows = if(recyclerData.layoutManager is GridLayoutManager) Math.max(1, recyclerData.results.size / recyclerData.layoutManager.spanCount) else 1;
|
|
||||||
val rowsHeight = (firstVisibleItemView?.height ?: 0) * rows;
|
|
||||||
if(lastVisibleItemView != null && lastVisibleItemPosition == (recyclerData.results.size - 1)) {
|
|
||||||
false;
|
|
||||||
}
|
|
||||||
else if (firstVisibleItemView != null && height != null && rowsHeight < height) {
|
|
||||||
false;
|
|
||||||
} else {
|
|
||||||
true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.i(TAG, "ensureEnoughContentVisible loadNextPage canScroll=$canScroll _automaticNextPageCounter=$_automaticNextPageCounter")
|
|
||||||
if (!canScroll || filteredResults.isEmpty()) {
|
|
||||||
_automaticNextPageCounter++
|
|
||||||
if(_automaticNextPageCounter < _automaticBackoff.size) {
|
|
||||||
if(_automaticNextPageCounter > 0) {
|
|
||||||
val automaticNextPageCounterSaved = _automaticNextPageCounter;
|
|
||||||
fragment.lifecycleScope.launch(Dispatchers.Default) {
|
|
||||||
val backoff = _automaticBackoff[Math.min(_automaticBackoff.size - 1, _automaticNextPageCounter)];
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
setLoading(true);
|
|
||||||
}
|
|
||||||
delay(backoff.toLong());
|
|
||||||
if(automaticNextPageCounterSaved == _automaticNextPageCounter) {
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
loadNextPage();
|
setLoading(true);
|
||||||
|
}
|
||||||
|
delay(backoff.toLong());
|
||||||
|
if (automaticNextPageCounterSaved == _automaticNextPageCounter) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
loadNextPage();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
} else
|
||||||
withContext(Dispatchers.Main) {
|
loadNextPage();
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
loadNextPage();
|
Logger.i(TAG, "ensureEnoughContentVisible automaticNextPageCounter reset");
|
||||||
|
_automaticNextPageCounter = 0;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Logger.i(TAG, "ensureEnoughContentVisible automaticNextPageCounter reset");
|
|
||||||
_automaticNextPageCounter = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun resetAutomaticNextPageCounter(){
|
fun resetAutomaticNextPageCounter(){
|
||||||
@@ -484,6 +470,7 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
|||||||
recyclerData.resultsUnfiltered.addAll(toAdd);
|
recyclerData.resultsUnfiltered.addAll(toAdd);
|
||||||
recyclerData.adapter.notifyDataSetChanged();
|
recyclerData.adapter.notifyDataSetChanged();
|
||||||
recyclerData.loadedFeedStyle = feedStyle;
|
recyclerData.loadedFeedStyle = feedStyle;
|
||||||
|
setLoading(false)
|
||||||
if(pager.hasMorePages())
|
if(pager.hasMorePages())
|
||||||
ensureEnoughContentVisible(filteredResults)
|
ensureEnoughContentVisible(filteredResults)
|
||||||
}
|
}
|
||||||
@@ -519,7 +506,7 @@ abstract class FeedView<TFragment, TResult, TConverted, TPager, TViewHolder> : L
|
|||||||
synchronized(_pagerLock) {
|
synchronized(_pagerLock) {
|
||||||
val pager: TPager = recyclerData.pager ?: return;
|
val pager: TPager = recyclerData.pager ?: return;
|
||||||
val hasMorePages = pager.hasMorePages();
|
val hasMorePages = pager.hasMorePages();
|
||||||
Logger.i(TAG, "loadNextPage() hasMorePages=$hasMorePages, page size=${pager.getResults().size}");
|
//Logger.i(TAG, "loadNextPage() hasMorePages=$hasMorePages, page size=${pager.getResults().size}");
|
||||||
|
|
||||||
//loadCachedPage();
|
//loadCachedPage();
|
||||||
if (pager.hasMorePages()) {
|
if (pager.hasMorePages()) {
|
||||||
|
|||||||
-1
@@ -96,7 +96,6 @@ class LibraryVideosFragment : MainFragment() {
|
|||||||
fun onShown() {
|
fun onShown() {
|
||||||
val initialAlbums = StateLibrary.instance.getAlbums();
|
val initialAlbums = StateLibrary.instance.getAlbums();
|
||||||
Logger.i(TAG, "Initial album count: " + initialAlbums.size);
|
Logger.i(TAG, "Initial album count: " + initialAlbums.size);
|
||||||
val buckets = StateLibrary.instance.getVideoBucketNames();
|
|
||||||
setPager(StateLibrary.instance.getVideos(fragment._toggleBuckets));
|
setPager(StateLibrary.instance.getVideos(fragment._toggleBuckets));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -364,7 +364,7 @@ class RemotePlaylistFragment : MainFragment() {
|
|||||||
_imagePlaylistThumbnail.let {
|
_imagePlaylistThumbnail.let {
|
||||||
Glide.with(it)
|
Glide.with(it)
|
||||||
.load(video.thumbnails.getHQThumbnail())
|
.load(video.thumbnails.getHQThumbnail())
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
.withMaxSizePx()
|
||||||
.placeholder(R.drawable.placeholder_video_thumbnail)
|
.placeholder(R.drawable.placeholder_video_thumbnail)
|
||||||
.crossfade()
|
.crossfade()
|
||||||
.into(it);
|
.into(it);
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ import com.futo.platformplayer.views.video.FutoShortPlayer
|
|||||||
import com.futo.platformplayer.views.video.FutoVideoPlayerBase
|
import com.futo.platformplayer.views.video.FutoVideoPlayerBase
|
||||||
import com.futo.platformplayer.views.video.FutoVideoPlayerBase.Companion.PREFERED_AUDIO_CONTAINERS
|
import com.futo.platformplayer.views.video.FutoVideoPlayerBase.Companion.PREFERED_AUDIO_CONTAINERS
|
||||||
import com.futo.platformplayer.views.video.FutoVideoPlayerBase.Companion.PREFERED_VIDEO_CONTAINERS
|
import com.futo.platformplayer.views.video.FutoVideoPlayerBase.Companion.PREFERED_VIDEO_CONTAINERS
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
import com.futo.polycentric.core.ApiMethods
|
import com.futo.polycentric.core.ApiMethods
|
||||||
import com.futo.polycentric.core.ContentType
|
import com.futo.polycentric.core.ContentType
|
||||||
import com.futo.polycentric.core.Models
|
import com.futo.polycentric.core.Models
|
||||||
@@ -859,7 +860,7 @@ class ShortView : FrameLayout {
|
|||||||
|
|
||||||
val thumbnail = videoDetails.thumbnails.getHQThumbnail()
|
val thumbnail = videoDetails.thumbnails.getHQThumbnail()
|
||||||
if (videoSource == null && !thumbnail.isNullOrBlank()) Glide.with(context).asBitmap()
|
if (videoSource == null && !thumbnail.isNullOrBlank()) Glide.with(context).asBitmap()
|
||||||
.load(thumbnail).downsample(DownsampleStrategy.AT_MOST).override(1080, 1080).into(object : CustomTarget<Bitmap>() {
|
.load(thumbnail).withMaxSizePx().into(object : CustomTarget<Bitmap>() {
|
||||||
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||||||
player.setArtwork(resource.toDrawable(resources))
|
player.setArtwork(resource.toDrawable(resources))
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -162,6 +162,7 @@ import com.futo.platformplayer.views.subscriptions.SubscribeButton
|
|||||||
import com.futo.platformplayer.views.video.FutoVideoPlayer
|
import com.futo.platformplayer.views.video.FutoVideoPlayer
|
||||||
import com.futo.platformplayer.views.video.FutoVideoPlayerBase
|
import com.futo.platformplayer.views.video.FutoVideoPlayerBase
|
||||||
import com.futo.platformplayer.views.videometa.UpNextView
|
import com.futo.platformplayer.views.videometa.UpNextView
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
import com.futo.polycentric.core.ApiMethods
|
import com.futo.polycentric.core.ApiMethods
|
||||||
import com.futo.polycentric.core.ContentType
|
import com.futo.polycentric.core.ContentType
|
||||||
import com.futo.polycentric.core.Models
|
import com.futo.polycentric.core.Models
|
||||||
@@ -2050,7 +2051,7 @@ class VideoDetailView : ConstraintLayout {
|
|||||||
} else {
|
} else {
|
||||||
val thumbnail = video.thumbnails.getHQThumbnail();
|
val thumbnail = video.thumbnails.getHQThumbnail();
|
||||||
if ((videoSource == null) && !thumbnail.isNullOrBlank()) // || _player.isAudioMode
|
if ((videoSource == null) && !thumbnail.isNullOrBlank()) // || _player.isAudioMode
|
||||||
Glide.with(context).asBitmap().load(thumbnail).downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
Glide.with(context).asBitmap().load(thumbnail).withMaxSizePx()
|
||||||
.into(object: CustomTarget<Bitmap>() {
|
.into(object: CustomTarget<Bitmap>() {
|
||||||
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||||||
_player.setArtwork(BitmapDrawable(resources, resource));
|
_player.setArtwork(BitmapDrawable(resources, resource));
|
||||||
|
|||||||
+2
-1
@@ -29,6 +29,7 @@ import com.futo.platformplayer.toHumanDuration
|
|||||||
import com.futo.platformplayer.toHumanTime
|
import com.futo.platformplayer.toHumanTime
|
||||||
import com.futo.platformplayer.views.SearchView
|
import com.futo.platformplayer.views.SearchView
|
||||||
import com.futo.platformplayer.views.lists.VideoListEditorView
|
import com.futo.platformplayer.views.lists.VideoListEditorView
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
|
|
||||||
abstract class VideoListEditorView : LinearLayout {
|
abstract class VideoListEditorView : LinearLayout {
|
||||||
private var _videoListEditorView: VideoListEditorView;
|
private var _videoListEditorView: VideoListEditorView;
|
||||||
@@ -212,7 +213,7 @@ abstract class VideoListEditorView : LinearLayout {
|
|||||||
_imagePlaylistThumbnail.let {
|
_imagePlaylistThumbnail.let {
|
||||||
Glide.with(it)
|
Glide.with(it)
|
||||||
.load(video.thumbnails.getHQThumbnail())
|
.load(video.thumbnails.getHQThumbnail())
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
.withMaxSizePx()
|
||||||
.placeholder(R.drawable.placeholder_video_thumbnail)
|
.placeholder(R.drawable.placeholder_video_thumbnail)
|
||||||
.crossfade()
|
.crossfade()
|
||||||
.into(it);
|
.into(it);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.bumptech.glide.RequestBuilder
|
|||||||
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
|
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
|
||||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
|
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
|
||||||
import com.futo.platformplayer.api.media.models.Thumbnails
|
import com.futo.platformplayer.api.media.models.Thumbnails
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
|
|
||||||
class GlideHelper {
|
class GlideHelper {
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ class GlideHelper {
|
|||||||
fun ImageView.loadThumbnails(thumbnails: Thumbnails, isHQ: Boolean = true, continuation: ((RequestBuilder<Drawable>) -> Unit)? = null) {
|
fun ImageView.loadThumbnails(thumbnails: Thumbnails, isHQ: Boolean = true, continuation: ((RequestBuilder<Drawable>) -> Unit)? = null) {
|
||||||
val url = if(isHQ) thumbnails.getHQThumbnail() ?: thumbnails.getLQThumbnail() else thumbnails.getLQThumbnail();
|
val url = if(isHQ) thumbnails.getHQThumbnail() ?: thumbnails.getLQThumbnail() else thumbnails.getLQThumbnail();
|
||||||
|
|
||||||
val req = Glide.with(this).load(url).downsample(DownsampleStrategy.AT_MOST).override(1080, 1080);
|
val req = Glide.with(this).load(url).withMaxSizePx()
|
||||||
|
|
||||||
if (thumbnails.hasMultiple() && false) { //TODO: Resolve issue where fallback triggered on second loads?
|
if (thumbnails.hasMultiple() && false) { //TODO: Resolve issue where fallback triggered on second loads?
|
||||||
val fallbackUrl = if (isHQ) thumbnails.getLQThumbnail() else thumbnails.getHQThumbnail();
|
val fallbackUrl = if (isHQ) thumbnails.getLQThumbnail() else thumbnails.getHQThumbnail();
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import com.futo.platformplayer.receivers.MediaControlReceiver
|
|||||||
import com.futo.platformplayer.states.StatePlatform
|
import com.futo.platformplayer.states.StatePlatform
|
||||||
import com.futo.platformplayer.states.StatePlayer
|
import com.futo.platformplayer.states.StatePlayer
|
||||||
import com.futo.platformplayer.stores.FragmentedStorage
|
import com.futo.platformplayer.stores.FragmentedStorage
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
|
|
||||||
class MediaPlaybackService : Service() {
|
class MediaPlaybackService : Service() {
|
||||||
private val TAG = "MediaPlaybackService";
|
private val TAG = "MediaPlaybackService";
|
||||||
@@ -225,7 +226,7 @@ class MediaPlaybackService : Service() {
|
|||||||
val tag = video;
|
val tag = video;
|
||||||
Glide.with(this).asBitmap()
|
Glide.with(this).asBitmap()
|
||||||
.load(thumbnail)
|
.load(thumbnail)
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
.withMaxSizePx()
|
||||||
.into(object: CustomTarget<Bitmap>() {
|
.into(object: CustomTarget<Bitmap>() {
|
||||||
override fun onResourceReady(resource: Bitmap,transition: Transition<in Bitmap>?) {
|
override fun onResourceReady(resource: Bitmap,transition: Transition<in Bitmap>?) {
|
||||||
if (tag != _notif_last_video) return
|
if (tag != _notif_last_video) return
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package com.futo.platformplayer.states
|
package com.futo.platformplayer.states
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
import android.content.ContentUris
|
import android.content.ContentUris
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.provider.MediaStore.Audio.Artists
|
import android.provider.MediaStore.Audio.Artists
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
@@ -154,34 +156,101 @@ class StateLibrary {
|
|||||||
fun getArtist(id: Long): Artist? {
|
fun getArtist(id: Long): Artist? {
|
||||||
return Artist.getArtist(id);
|
return Artist.getArtist(id);
|
||||||
}
|
}
|
||||||
|
fun getVideos(
|
||||||
|
buckets: List<String>? = null,
|
||||||
|
pageSize: Int = 20
|
||||||
|
): IPager<IPlatformContent> {
|
||||||
|
val resolver = StateApp.instance.contextOrNull?.contentResolver ?: return EmptyPager()
|
||||||
|
val selection: String?
|
||||||
|
val selectionArgs: Array<String>?
|
||||||
|
|
||||||
fun getVideos(buckets: List<String>? = null): IPager<IPlatformContent> {
|
if (!buckets.isNullOrEmpty()) {
|
||||||
var query = if(buckets != null) "${MediaStore.Video.Media.BUCKET_DISPLAY_NAME} IN " + "(" + buckets.map { "'${it}'" }.joinToString(",") + ")" else null;
|
val placeholders = buckets.joinToString(",") { "?" }
|
||||||
val cursor = StateApp.instance.contextOrNull?.contentResolver?.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, PROJECTION_VIDEO,
|
selection = "${MediaStore.Video.Media.BUCKET_DISPLAY_NAME} IN ($placeholders)"
|
||||||
query,
|
selectionArgs = buckets.toTypedArray()
|
||||||
null,
|
} else {
|
||||||
MediaStore.Video.Media.DATE_ADDED + " DESC") ?: return EmptyPager();
|
selection = null
|
||||||
|
selectionArgs = null
|
||||||
|
}
|
||||||
|
|
||||||
//Ongoing usage of cursor..todo disposal
|
val collectionUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
//return cursor.use {
|
MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
||||||
cursor.moveToFirst();
|
} else {
|
||||||
val list = mutableListOf<IPlatformVideo>()
|
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||||
while(!cursor.isAfterLast && list.size < 10) {
|
}
|
||||||
list.add(videoFromCursor(cursor));
|
|
||||||
cursor.moveToNext();
|
var nextPageIndex = 0
|
||||||
|
fun loadPage(pageIndex: Int): List<IPlatformContent> {
|
||||||
|
Logger.i(TAG, "loadPage $pageIndex")
|
||||||
|
val offset = pageIndex * pageSize
|
||||||
|
|
||||||
|
val queryArgs = Bundle().apply {
|
||||||
|
selection?.let {
|
||||||
|
putString(ContentResolver.QUERY_ARG_SQL_SELECTION, it)
|
||||||
|
}
|
||||||
|
selectionArgs?.let {
|
||||||
|
putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
putStringArray(
|
||||||
|
ContentResolver.QUERY_ARG_SORT_COLUMNS,
|
||||||
|
arrayOf(
|
||||||
|
MediaStore.Video.Media.DATE_ADDED,
|
||||||
|
MediaStore.Video.Media._ID
|
||||||
|
)
|
||||||
|
)
|
||||||
|
putInt(
|
||||||
|
ContentResolver.QUERY_ARG_SORT_DIRECTION,
|
||||||
|
ContentResolver.QUERY_SORT_DIRECTION_DESCENDING
|
||||||
|
)
|
||||||
|
|
||||||
|
putInt(ContentResolver.QUERY_ARG_LIMIT, pageSize)
|
||||||
|
putInt(ContentResolver.QUERY_ARG_OFFSET, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
return AdhocPager<IPlatformContent>({
|
val cursor = resolver.query(
|
||||||
val list = mutableListOf<IPlatformContent>()
|
collectionUri,
|
||||||
while(!cursor.isAfterLast && list.size < 10) {
|
PROJECTION_VIDEO,
|
||||||
list.add(videoFromCursor(cursor));
|
queryArgs,
|
||||||
cursor.moveToNext();
|
null
|
||||||
|
)
|
||||||
|
|
||||||
|
if (cursor == null) {
|
||||||
|
Logger.i(TAG, "loadPage $pageIndex null, returning empty list")
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.use { c ->
|
||||||
|
if (!c.moveToFirst()) {
|
||||||
|
Logger.i(TAG, "loadPage $pageIndex moveToFirst failed, returning empty list")
|
||||||
|
return emptyList()
|
||||||
}
|
}
|
||||||
Logger.i(TAG, "Videos nextPage: ${list.size}")
|
|
||||||
return@AdhocPager list;
|
val list = ArrayList<IPlatformContent>(pageSize)
|
||||||
}, list);
|
do {
|
||||||
//}
|
list.add(videoFromCursor(c))
|
||||||
|
} while (c.moveToNext() && list.size < pageSize)
|
||||||
|
|
||||||
|
Logger.i(TAG, "loadPage $pageIndex found ${list.size} items")
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val firstPage = loadPage(0)
|
||||||
|
if (firstPage.isEmpty()) {
|
||||||
|
return EmptyPager()
|
||||||
|
}
|
||||||
|
nextPageIndex = 1
|
||||||
|
|
||||||
|
return AdhocPager<IPlatformContent>({
|
||||||
|
val page = loadPage(nextPageIndex)
|
||||||
|
nextPageIndex++
|
||||||
|
|
||||||
|
Logger.i(TAG, "loadPage nextPage: ${page.size}")
|
||||||
|
page
|
||||||
|
}, firstPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRecentVideos(buckets: List<String>? = null, count: Int = 20): List<IPlatformVideo> {
|
fun getRecentVideos(buckets: List<String>? = null, count: Int = 20): List<IPlatformVideo> {
|
||||||
val videoPager = getVideos(buckets);
|
val videoPager = getVideos(buckets);
|
||||||
val items = mutableListOf<IPlatformVideo>();
|
val items = mutableListOf<IPlatformVideo>();
|
||||||
@@ -193,48 +262,80 @@ class StateLibrary {
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private var _cacheBucketNames: List<Bucket>? = null;
|
@Volatile
|
||||||
fun getVideoBucketNames(): List<Bucket> {
|
private var _cachedVideoBuckets: List<Bucket>? = null
|
||||||
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
|
private val _bucketCacheLock = Any()
|
||||||
return listOf();
|
|
||||||
if(_cacheBucketNames != null)
|
|
||||||
return _cacheBucketNames ?: listOf();
|
|
||||||
try {
|
|
||||||
val cur: Cursor = StateApp.instance.contextOrNull?.contentResolver?.query(
|
|
||||||
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, arrayOf(
|
|
||||||
MediaStore.Video.Media.BUCKET_ID,
|
|
||||||
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
|
|
||||||
), null, null, null
|
|
||||||
) ?: return listOf();
|
|
||||||
|
|
||||||
return cur.use {
|
fun getVideoBucketNames(forceRefresh: Boolean = false): List<Bucket> {
|
||||||
val buckets = mutableListOf<Bucket>();
|
if (!forceRefresh) {
|
||||||
val list = HashSet<Long>();
|
_cachedVideoBuckets?.let { return it }
|
||||||
if (cur.moveToFirst()) {
|
}
|
||||||
var id: Long;
|
|
||||||
var bucket: String
|
val resolver = StateApp.instance.contextOrNull?.contentResolver
|
||||||
do {
|
?: return emptyList()
|
||||||
try {
|
|
||||||
id = cur.getLong(0);
|
val projection = arrayOf(
|
||||||
bucket = cur.getStringOrNull(1) ?: continue;
|
MediaStore.Video.VideoColumns.BUCKET_ID,
|
||||||
if (!list.contains(id)) {
|
MediaStore.Video.VideoColumns.BUCKET_DISPLAY_NAME
|
||||||
list.add(id);
|
)
|
||||||
buckets.add(Bucket(id, bucket));
|
|
||||||
}
|
val sortOrder = "${MediaStore.Video.VideoColumns.BUCKET_DISPLAY_NAME} COLLATE NOCASE ASC"
|
||||||
} catch (ex: Throwable) {
|
val loadedBuckets: List<Bucket> = try {
|
||||||
Logger.e(TAG, "Failed to parse bucket due to ${ex.message}", ex);
|
resolver.query(
|
||||||
}
|
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
|
||||||
} while (cur.moveToNext())
|
projection,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
sortOrder
|
||||||
|
)?.use { cursor ->
|
||||||
|
if (!cursor.moveToFirst()) {
|
||||||
|
return@use emptyList<Bucket>()
|
||||||
}
|
}
|
||||||
_cacheBucketNames = buckets.toList()
|
|
||||||
return@use _cacheBucketNames ?: listOf();
|
val idxId = cursor.getColumnIndexOrThrow(MediaStore.Video.VideoColumns.BUCKET_ID)
|
||||||
|
val idxName = cursor.getColumnIndexOrThrow(MediaStore.Video.VideoColumns.BUCKET_DISPLAY_NAME)
|
||||||
|
val seenIds = HashSet<Long>()
|
||||||
|
val buckets = ArrayList<Bucket>()
|
||||||
|
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
val id = cursor.getLong(idxId)
|
||||||
|
if (!seenIds.add(id)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val name = cursor.getStringOrNull(idxName) ?: continue
|
||||||
|
buckets.add(Bucket(id, name))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.e(TAG, "Failed to parse video bucket row: ${e.message}", e)
|
||||||
|
}
|
||||||
|
} while (cursor.moveToNext())
|
||||||
|
|
||||||
|
buckets
|
||||||
|
} ?: emptyList()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.e(TAG, "Buckets loading failed, returning empty: ${e.message}", e)
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadedBuckets.isEmpty()) {
|
||||||
|
if (!forceRefresh) {
|
||||||
|
_cachedVideoBuckets?.let { return it }
|
||||||
}
|
}
|
||||||
|
return emptyList()
|
||||||
}
|
}
|
||||||
catch(ex: Throwable) {
|
|
||||||
Logger.e(TAG, "Buckets loading failed, returning empty");
|
synchronized(_bucketCacheLock) {
|
||||||
return listOf();
|
if (!forceRefresh) {
|
||||||
|
_cachedVideoBuckets?.let { return it }
|
||||||
|
}
|
||||||
|
_cachedVideoBuckets = loadedBuckets
|
||||||
|
return loadedBuckets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun invalidateVideoBucketNamesCache() {
|
||||||
|
_cachedVideoBuckets = null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.futo.platformplayer.serializers.PlatformContentSerializer
|
|||||||
import com.futo.platformplayer.stores.FragmentedStorage
|
import com.futo.platformplayer.stores.FragmentedStorage
|
||||||
import com.futo.platformplayer.toHumanNowDiffString
|
import com.futo.platformplayer.toHumanNowDiffString
|
||||||
import com.futo.platformplayer.toHumanNowDiffStringMinDay
|
import com.futo.platformplayer.toHumanNowDiffStringMinDay
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
|
|
||||||
class StateNotifications {
|
class StateNotifications {
|
||||||
@@ -97,7 +98,7 @@ class StateNotifications {
|
|||||||
if(thumbnail != null)
|
if(thumbnail != null)
|
||||||
Glide.with(context).asBitmap()
|
Glide.with(context).asBitmap()
|
||||||
.load(thumbnail)
|
.load(thumbnail)
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
.withMaxSizePx()
|
||||||
.into(object: CustomTarget<Bitmap>() {
|
.into(object: CustomTarget<Bitmap>() {
|
||||||
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||||||
notifyNewContent(context, manager, notificationChannel, id, content, resource);
|
notifyNewContent(context, manager, notificationChannel, id, content, resource);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import com.futo.platformplayer.R
|
|||||||
import com.futo.platformplayer.constructs.Event0
|
import com.futo.platformplayer.constructs.Event0
|
||||||
import com.futo.platformplayer.images.GlideHelper.Companion.crossfade
|
import com.futo.platformplayer.images.GlideHelper.Companion.crossfade
|
||||||
import com.futo.platformplayer.models.Playlist
|
import com.futo.platformplayer.models.Playlist
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
|
|
||||||
class PlaylistsViewHolder : ViewHolder {
|
class PlaylistsViewHolder : ViewHolder {
|
||||||
private val _root: ConstraintLayout;
|
private val _root: ConstraintLayout;
|
||||||
@@ -45,7 +46,7 @@ class PlaylistsViewHolder : ViewHolder {
|
|||||||
if (p.videos.isNotEmpty()) {
|
if (p.videos.isNotEmpty()) {
|
||||||
Glide.with(_imageThumbnail)
|
Glide.with(_imageThumbnail)
|
||||||
.load(p.videos[0].thumbnails.getMinimumThumbnail(380))
|
.load(p.videos[0].thumbnails.getMinimumThumbnail(380))
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
.withMaxSizePx()
|
||||||
.placeholder(R.drawable.placeholder_video_thumbnail)
|
.placeholder(R.drawable.placeholder_video_thumbnail)
|
||||||
.crossfade()
|
.crossfade()
|
||||||
.into(_imageThumbnail);
|
.into(_imageThumbnail);
|
||||||
|
|||||||
+2
-1
@@ -24,6 +24,7 @@ import com.futo.platformplayer.toHumanNumber
|
|||||||
import com.futo.platformplayer.toHumanTime
|
import com.futo.platformplayer.toHumanTime
|
||||||
import com.futo.platformplayer.views.others.ProgressBar
|
import com.futo.platformplayer.views.others.ProgressBar
|
||||||
import com.futo.platformplayer.views.platform.PlatformIndicator
|
import com.futo.platformplayer.views.platform.PlatformIndicator
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
|
|
||||||
class VideoListEditorViewHolder : ViewHolder {
|
class VideoListEditorViewHolder : ViewHolder {
|
||||||
private val _root: ConstraintLayout;
|
private val _root: ConstraintLayout;
|
||||||
@@ -90,7 +91,7 @@ class VideoListEditorViewHolder : ViewHolder {
|
|||||||
fun bind(v: IPlatformVideo, canEdit: Boolean) {
|
fun bind(v: IPlatformVideo, canEdit: Boolean) {
|
||||||
Glide.with(_imageThumbnail)
|
Glide.with(_imageThumbnail)
|
||||||
.load(v.thumbnails.getHQThumbnail())
|
.load(v.thumbnails.getHQThumbnail())
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
.withMaxSizePx()
|
||||||
.placeholder(R.drawable.placeholder_video_thumbnail)
|
.placeholder(R.drawable.placeholder_video_thumbnail)
|
||||||
.crossfade()
|
.crossfade()
|
||||||
.into(_imageThumbnail);
|
.into(_imageThumbnail);
|
||||||
|
|||||||
+2
-1
@@ -17,6 +17,7 @@ import com.futo.platformplayer.states.Artist
|
|||||||
import com.futo.platformplayer.toHumanNowDiffString
|
import com.futo.platformplayer.toHumanNowDiffString
|
||||||
import com.futo.platformplayer.toHumanTime
|
import com.futo.platformplayer.toHumanTime
|
||||||
import com.futo.platformplayer.views.adapters.AnyAdapter
|
import com.futo.platformplayer.views.adapters.AnyAdapter
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
import com.google.android.material.imageview.ShapeableImageView
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
|
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ class LocalVideoTileViewHolder(val _viewGroup: ViewGroup) : AnyAdapter.AnyViewHo
|
|||||||
Glide.with(it)
|
Glide.with(it)
|
||||||
.load(content.thumbnails.getHQThumbnail())
|
.load(content.thumbnails.getHQThumbnail())
|
||||||
.placeholder(R.drawable.unknown_music)
|
.placeholder(R.drawable.unknown_music)
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
.withMaxSizePx()
|
||||||
.into(it)
|
.into(it)
|
||||||
else
|
else
|
||||||
Glide.with(it).load(R.drawable.unknown_music).into(it);
|
Glide.with(it).load(R.drawable.unknown_music).into(it);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.futo.platformplayer.logging.Logger
|
|||||||
import com.futo.platformplayer.states.StatePlayer
|
import com.futo.platformplayer.states.StatePlayer
|
||||||
import com.futo.platformplayer.views.TargetTapLoaderView
|
import com.futo.platformplayer.views.TargetTapLoaderView
|
||||||
import com.futo.platformplayer.views.behavior.GestureControlView
|
import com.futo.platformplayer.views.behavior.GestureControlView
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
@@ -307,7 +308,7 @@ class CastView : ConstraintLayout {
|
|||||||
Glide.with(_thumbnail)
|
Glide.with(_thumbnail)
|
||||||
.load(video.thumbnails.getHQThumbnail())
|
.load(video.thumbnails.getHQThumbnail())
|
||||||
.placeholder(R.drawable.placeholder_video_thumbnail)
|
.placeholder(R.drawable.placeholder_video_thumbnail)
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
.withMaxSizePx()
|
||||||
.into(_thumbnail);
|
.into(_thumbnail);
|
||||||
_textPosition.text = (position * 1000).formatDuration();
|
_textPosition.text = (position * 1000).formatDuration();
|
||||||
_textDuration.text = (video.duration * 1000).formatDuration();
|
_textDuration.text = (video.duration * 1000).formatDuration();
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ class ActiveDownloadItem: LinearLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Glide.with(_videoImage)
|
Glide.with(_videoImage)
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
|
||||||
.load(download.thumbnail)
|
.load(download.thumbnail)
|
||||||
|
.withMaxSizePx()
|
||||||
.crossfade()
|
.crossfade()
|
||||||
.into(_videoImage);
|
.into(_videoImage);
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
|
|||||||
import com.futo.platformplayer.R
|
import com.futo.platformplayer.R
|
||||||
import com.futo.platformplayer.images.GlideHelper.Companion.crossfade
|
import com.futo.platformplayer.images.GlideHelper.Companion.crossfade
|
||||||
import com.futo.platformplayer.models.PlaylistDownloaded
|
import com.futo.platformplayer.models.PlaylistDownloaded
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
|
|
||||||
class PlaylistDownloadItem(context: Context, playlistName: String, playlistThumbnail: String?, val obj: Any): LinearLayout(context) {
|
class PlaylistDownloadItem(context: Context, playlistName: String, playlistThumbnail: String?, val obj: Any): LinearLayout(context) {
|
||||||
init { inflate(context, R.layout.list_downloaded_playlist, this) }
|
init { inflate(context, R.layout.list_downloaded_playlist, this) }
|
||||||
@@ -20,7 +21,7 @@ class PlaylistDownloadItem(context: Context, playlistName: String, playlistThumb
|
|||||||
imageText.text = playlistName;
|
imageText.text = playlistName;
|
||||||
Glide.with(imageView)
|
Glide.with(imageView)
|
||||||
.load(playlistThumbnail)
|
.load(playlistThumbnail)
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
.withMaxSizePx()
|
||||||
.crossfade()
|
.crossfade()
|
||||||
.into(imageView);
|
.into(imageView);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails
|
|||||||
import com.futo.platformplayer.helpers.VideoHelper
|
import com.futo.platformplayer.helpers.VideoHelper
|
||||||
import com.futo.platformplayer.toHumanTime
|
import com.futo.platformplayer.toHumanTime
|
||||||
import com.futo.platformplayer.video.PlayerManager
|
import com.futo.platformplayer.video.PlayerManager
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
|
|
||||||
|
|
||||||
class FutoThumbnailPlayer : FutoVideoPlayerBase {
|
class FutoThumbnailPlayer : FutoVideoPlayerBase {
|
||||||
@@ -136,7 +137,7 @@ class FutoThumbnailPlayer : FutoVideoPlayerBase {
|
|||||||
if (videoSource == null && audioSource != null) {
|
if (videoSource == null && audioSource != null) {
|
||||||
val thumbnail = video.thumbnails.getHQThumbnail();
|
val thumbnail = video.thumbnails.getHQThumbnail();
|
||||||
if (!thumbnail.isNullOrBlank()) {
|
if (!thumbnail.isNullOrBlank()) {
|
||||||
Glide.with(videoView).asBitmap().load(thumbnail).downsample(DownsampleStrategy.AT_MOST).override(1080, 1080).into(_loadArtwork);
|
Glide.with(videoView).asBitmap().load(thumbnail).withMaxSizePx().into(_loadArtwork);
|
||||||
} else {
|
} else {
|
||||||
Glide.with(videoView).clear(_loadArtwork);
|
Glide.with(videoView).clear(_loadArtwork);
|
||||||
setArtwork(null);
|
setArtwork(null);
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ import com.futo.platformplayer.states.StatePlayer
|
|||||||
import com.futo.platformplayer.views.TargetTapLoaderView
|
import com.futo.platformplayer.views.TargetTapLoaderView
|
||||||
import com.futo.platformplayer.views.behavior.GestureControlView
|
import com.futo.platformplayer.views.behavior.GestureControlView
|
||||||
import com.futo.platformplayer.views.others.ProgressBar
|
import com.futo.platformplayer.views.others.ProgressBar
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
@@ -928,11 +929,9 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
|
|||||||
override fun switchToAudioMode(video: IPlatformVideoDetails?) {
|
override fun switchToAudioMode(video: IPlatformVideoDetails?) {
|
||||||
super.switchToAudioMode(video)
|
super.switchToAudioMode(video)
|
||||||
|
|
||||||
//This causes issues, and is in general confusing, needs improvements
|
|
||||||
/*
|
|
||||||
val thumbnail = video?.thumbnails?.getHQThumbnail()
|
val thumbnail = video?.thumbnails?.getHQThumbnail()
|
||||||
if (!thumbnail.isNullOrBlank()) {
|
if (!thumbnail.isNullOrBlank()) {
|
||||||
Glide.with(context).asBitmap().load(thumbnail)
|
Glide.with(context).asBitmap().load(thumbnail).withMaxSizePx()
|
||||||
.into(object : CustomTarget<Bitmap>() {
|
.into(object : CustomTarget<Bitmap>() {
|
||||||
override fun onResourceReady(
|
override fun onResourceReady(
|
||||||
resource: Bitmap,
|
resource: Bitmap,
|
||||||
@@ -946,6 +945,5 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,7 @@ import com.futo.platformplayer.R
|
|||||||
import com.futo.platformplayer.constructs.Event0
|
import com.futo.platformplayer.constructs.Event0
|
||||||
import com.futo.platformplayer.toHumanNowDiffString
|
import com.futo.platformplayer.toHumanNowDiffString
|
||||||
import com.futo.platformplayer.toHumanNumber
|
import com.futo.platformplayer.toHumanNumber
|
||||||
|
import com.futo.platformplayer.withMaxSizePx
|
||||||
|
|
||||||
class UpNextView : LinearLayout {
|
class UpNextView : LinearLayout {
|
||||||
private val _layoutContainer: LinearLayout;
|
private val _layoutContainer: LinearLayout;
|
||||||
@@ -161,7 +162,7 @@ class UpNextView : LinearLayout {
|
|||||||
_textChannelName.text = nextItem.author.name;
|
_textChannelName.text = nextItem.author.name;
|
||||||
Glide.with(_imageThumbnail)
|
Glide.with(_imageThumbnail)
|
||||||
.load(nextItem.thumbnails.getHQThumbnail())
|
.load(nextItem.thumbnails.getHQThumbnail())
|
||||||
.downsample(DownsampleStrategy.AT_MOST).override(1080, 1080)
|
.withMaxSizePx()
|
||||||
.placeholder(R.drawable.placeholder_video_thumbnail)
|
.placeholder(R.drawable.placeholder_video_thumbnail)
|
||||||
.into(_imageThumbnail);
|
.into(_imageThumbnail);
|
||||||
Glide.with(_imageChannelThumbnail)
|
Glide.with(_imageChannelThumbnail)
|
||||||
|
|||||||
Reference in New Issue
Block a user