diff --git a/app/src/main/java/com/futo/platformplayer/api/media/structures/DedupContentPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/structures/DedupContentPager.kt index da811750..9839141d 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/structures/DedupContentPager.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/structures/DedupContentPager.kt @@ -75,9 +75,12 @@ class DedupContentPager : IPager, IAsyncPager { constructor(pagers : Array>, allowFailure: Boolean = false, pageSize: Int = 9) : super(pagers.map { it }.toList(), allowFailure, pageSize) {} + constructor(pagers : List>, allowFailure: Boolean = false, pageSize: Int = 9) : super(pagers, allowFailure, pageSize) {} @Synchronized override fun selectItemIndex(options: Array>): Int { diff --git a/app/src/main/java/com/futo/platformplayer/api/media/structures/MultiChronoContentParallelPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/structures/MultiChronoContentParallelPager.kt new file mode 100644 index 00000000..af596d4f --- /dev/null +++ b/app/src/main/java/com/futo/platformplayer/api/media/structures/MultiChronoContentParallelPager.kt @@ -0,0 +1,33 @@ +package com.futo.platformplayer.api.media.structures + +import com.futo.platformplayer.api.media.models.contents.IPlatformContent +import kotlinx.coroutines.runBlocking +import java.util.stream.IntStream + + +/** + * A Content AsyncMultiPager that returns results based on a specified distribution + * Unlike its non-async counterpart, this one uses parallel nextPage requests + */ +class MultiChronoContentParallelPager : MultiParallelPager { + + constructor(pagers: List>) : super(pagers) + + @Synchronized + override fun selectItemIndex(options: Array>): Int { + if(options.size == 0) + return -1; + var bestIndex = 0; + + val allResults = runBlocking { options.map { Pair(it, it.item?.await()) } }; + for(i in IntStream.range(1, options.size)) { + val best = allResults[bestIndex].second; + val cur = allResults[i].second ?: continue; + if(best?.datetime == null || (cur.datetime != null && cur.datetime!! > best.datetime!!)) + bestIndex = i; + } + return bestIndex; + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/structures/RefreshChronoContentPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/structures/RefreshChronoContentPager.kt new file mode 100644 index 00000000..f44ca7f7 --- /dev/null +++ b/app/src/main/java/com/futo/platformplayer/api/media/structures/RefreshChronoContentPager.kt @@ -0,0 +1,19 @@ +package com.futo.platformplayer.api.media.structures + +import com.futo.platformplayer.api.media.models.contents.IPlatformContent +import kotlinx.coroutines.Deferred + +/** + * A RefreshMultiPager that simply returns all respective pagers in equal distribution, optionally inserting PlaceholderPager results as provided for their respective promised pagers + * (Eg. Pager A is completed, Pager [B,C,D] are promised/deferred. placeholderPagers [1,2,3] will map B=>1, C=>2, D=>3 until promised pagers are completed) + * Uses wrapped MultiDistributionContentAsyncPager for inidivual pagers. + */ +class RefreshChronoContentPager(pagers: List>, pendingPagers: List?>>, placeholderPagers: List>? = null) + : MultiRefreshPager(pagers, pendingPagers, placeholderPagers) { + + override fun recreatePager(pagers: List>): IPager { + return MultiChronoContentPager(pagers); + //return MultiChronoContentParallelPager(pagers); + //return MultiDistributionContentPager(pagers.associateWith { 1f }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/structures/SingleAsyncItemPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/structures/SingleAsyncItemPager.kt index 4c0bc621..beb841e8 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/structures/SingleAsyncItemPager.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/structures/SingleAsyncItemPager.kt @@ -43,6 +43,7 @@ class SingleAsyncItemPager { if (_currentResultPos >= _requestedPageItems.size) { val startPos = fillDeferredUntil(_currentResultPos); if(!_pager.hasMorePages()) { + Logger.i("SingleAsyncItemPager", "end of async page reached"); completeRemainder { it?.complete(null) }; } if(_isRequesting) diff --git a/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelContentsFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelContentsFragment.kt index fa49c67e..a956536d 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelContentsFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/channel/tab/ChannelContentsFragment.kt @@ -248,7 +248,6 @@ class ChannelContentsFragment : Fragment(), IChannelTabFragment { if(_pager is IReplacerPager<*>) (_pager as IReplacerPager<*>).onReplaced.remove(this); - if(pager is IReplacerPager<*>) { pager.onReplaced.subscribe(this) { oldItem, newItem -> if(_pager != pager) @@ -257,11 +256,14 @@ class ChannelContentsFragment : Fragment(), IChannelTabFragment { if(_pager !is IPager) return@subscribe; - val toReplaceIndex = _results.indexOfFirst { it == newItem }; - if(toReplaceIndex >= 0) { - _results[toReplaceIndex] = newItem as IPlatformContent; - _adapterResults?.let { - it.notifyItemChanged(it.childToParentPosition(toReplaceIndex)); + + lifecycleScope.launch(Dispatchers.Main) { + val toReplaceIndex = _results.indexOfFirst { it == oldItem }; + if (toReplaceIndex >= 0) { + _results[toReplaceIndex] = newItem as IPlatformContent; + _adapterResults?.let { + it.notifyItemChanged(it.childToParentPosition(toReplaceIndex)); + } } } } diff --git a/app/src/main/java/com/futo/platformplayer/states/StatePolycentric.kt b/app/src/main/java/com/futo/platformplayer/states/StatePolycentric.kt index b2721ab1..0602c82d 100644 --- a/app/src/main/java/com/futo/platformplayer/states/StatePolycentric.kt +++ b/app/src/main/java/com/futo/platformplayer/states/StatePolycentric.kt @@ -19,6 +19,7 @@ import com.futo.platformplayer.api.media.structures.IAsyncPager import com.futo.platformplayer.api.media.structures.IPager import com.futo.platformplayer.api.media.structures.MultiChronoContentPager import com.futo.platformplayer.api.media.structures.PlaceholderPager +import com.futo.platformplayer.api.media.structures.RefreshChronoContentPager import com.futo.platformplayer.api.media.structures.RefreshDedupContentPager import com.futo.platformplayer.api.media.structures.RefreshDistributionContentPager import com.futo.platformplayer.awaitFirstDeferred @@ -167,12 +168,21 @@ class StatePolycentric { }) ?: return null; val toAwait = deferred.filter { it.second != finishedPager.first }; + + //TODO: Get a Parallel pager to work here. + val innerPager = MultiChronoContentPager(listOf(finishedPager.second!!) + toAwait.mapNotNull { runBlocking { it.second.await(); } }); + innerPager.initialize(); + //return RefreshChronoContentPager(listOf(finishedPager.second!!), toAwait.map { it.second }, listOf()); + //return RefreshDedupContentPager(RefreshChronoContentPager(listOf(finishedPager.second!!), toAwait.map { it.second }, listOf()), StatePlatform.instance.getEnabledClients().map { it.id }); + return DedupContentPager(innerPager, StatePlatform.instance.getEnabledClients().map { it.id }); + + /* //Gives out-of-order results return RefreshDedupContentPager(RefreshDistributionContentPager( listOf(finishedPager.second!!), toAwait.map { it.second }, toAwait.map { PlaceholderPager(5) { PlatformContentPlaceholder(it.first.id) } }), StatePlatform.instance.getEnabledClients().map { it.id } - ); + );*/ } suspend fun getChannelContent(profile: PolycentricProfile): IPager { return withContext(Dispatchers.IO) {