diff --git a/app/src/androidTest/java/com/lagradost/cloudstream3/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/lagradost/cloudstream3/ExampleInstrumentedTest.kt index 201ddea3..2a3e13e5 100644 --- a/app/src/androidTest/java/com/lagradost/cloudstream3/ExampleInstrumentedTest.kt +++ b/app/src/androidTest/java/com/lagradost/cloudstream3/ExampleInstrumentedTest.kt @@ -180,7 +180,7 @@ class ExampleInstrumentedTest { @Test fun providerCorrectHomepage() { runBlocking { - getAllProviders().apmap { api -> + getAllProviders().amap { api -> if (api.hasMainPage) { try { val homepage = api.getMainPage() @@ -217,7 +217,7 @@ class ExampleInstrumentedTest { runBlocking { val invalidProvider = ArrayList>() val providers = getAllProviders() - providers.apmap { api -> + providers.amap { api -> try { println("Trying $api") if (testSingleProviderApi(api)) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt index 940d3391..da257d69 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt @@ -1066,7 +1066,7 @@ interface LoadResponse { ) { if (!isTrailersEnabled || trailerUrls == null) return trailers.addAll(trailerUrls.map { TrailerData(it, referer, addRaw) }) - /*val trailers = trailerUrls.filter { it.isNotBlank() }.apmap { trailerUrl -> + /*val trailers = trailerUrls.filter { it.isNotBlank() }.amap { trailerUrl -> val links = arrayListOf() val subs = arrayListOf() if (!loadExtractor( diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 4c193f42..eb83b08a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -592,7 +592,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { api.init() } - inAppAuths.apmap { api -> + inAppAuths.amap { api -> try { api.initialize() } catch (e: Exception) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ParCollections.kt b/app/src/main/java/com/lagradost/cloudstream3/ParCollections.kt index badb6631..46955427 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ParCollections.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ParCollections.kt @@ -1,8 +1,7 @@ package com.lagradost.cloudstream3 import com.lagradost.cloudstream3.mvvm.logError -import kotlinx.coroutines.async -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.* //https://stackoverflow.com/questions/34697828/parallel-operations-on-kotlin-collections /* @@ -26,10 +25,25 @@ fun Iterable.pmap( return ArrayList(destination) }*/ + +@OptIn(DelicateCoroutinesApi::class) +suspend fun Map.amap(f: suspend (Map.Entry) -> R): List = + with(CoroutineScope(GlobalScope.coroutineContext)) { + map { async { f(it) } }.map { it.await() } + } + fun Map.apmap(f: suspend (Map.Entry) -> R): List = runBlocking { map { async { f(it) } }.map { it.await() } } + +@OptIn(DelicateCoroutinesApi::class) +suspend fun List.amap(f: suspend (A) -> B): List = + with(CoroutineScope(GlobalScope.coroutineContext)) { + map { async { f(it) } }.map { it.await() } + } + + fun List.apmap(f: suspend (A) -> B): List = runBlocking { map { async { f(it) } }.map { it.await() } } @@ -38,6 +52,12 @@ fun List.apmapIndexed(f: suspend (index: Int, A) -> B): List = runB mapIndexed { index, a -> async { f(index, a) } }.map { it.await() } } +@OptIn(DelicateCoroutinesApi::class) +suspend fun List.amapIndexed(f: suspend (index: Int, A) -> B): List = + with(CoroutineScope(GlobalScope.coroutineContext)) { + mapIndexed { index, a -> async { f(index, a) } }.map { it.await() } + } + // run code in parallel /*fun argpmap( vararg transforms: () -> R, diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Fastream.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Fastream.kt index 16b109be..0d5a5c78 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Fastream.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Fastream.kt @@ -1,6 +1,6 @@ package com.lagradost.cloudstream3.extractors -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink @@ -21,10 +21,10 @@ class Fastream: ExtractorApi() { Pair("file_code",id), Pair("auto","1") )).document - response.select("script").apmap { script -> + response.select("script").amap { script -> if (script.data().contains("sources")) { val m3u8regex = Regex("((https:|http:)\\/\\/.*\\.m3u8)") - val m3u8 = m3u8regex.find(script.data())?.value ?: return@apmap + val m3u8 = m3u8regex.find(script.data())?.value ?: return@amap generateM3u8( name, m3u8, diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Pelisplus.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Pelisplus.kt index cc743d5e..de469b22 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Pelisplus.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Pelisplus.kt @@ -1,7 +1,7 @@ package com.lagradost.cloudstream3.extractors import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.utils.ExtractorLink @@ -35,7 +35,7 @@ class Pelisplus(val mainUrl: String) { callback: (ExtractorLink) -> Unit ): Boolean { try { - normalApis.apmap { api -> + normalApis.amap { api -> val url = api.getExtractorUrl(id) api.getSafeUrl(url, subtitleCallback = subtitleCallback, callback = callback) } @@ -51,8 +51,8 @@ class Pelisplus(val mainUrl: String) { val qualityRegex = Regex("(\\d+)P") //a[download] - pageDoc.select(".dowload > a")?.apmap { element -> - val href = element.attr("href") ?: return@apmap + pageDoc.select(".dowload > a")?.amap { element -> + val href = element.attr("href") ?: return@amap val qual = if (element.text() .contains("HDP") ) "1080" else qualityRegex.find(element.text())?.destructured?.component1() @@ -84,7 +84,7 @@ class Pelisplus(val mainUrl: String) { //val name = element.text() // Matches vidstream links with extractors - extractorApis.filter { !it.requiresReferer || !isCasting }.apmap { api -> + extractorApis.filter { !it.requiresReferer || !isCasting }.amap { api -> if (link.startsWith(api.mainUrl)) { api.getSafeUrl(link, extractorUrl, subtitleCallback, callback) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/VidSrcExtractor.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/VidSrcExtractor.kt index 287fe4d4..b910f9dd 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/VidSrcExtractor.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/VidSrcExtractor.kt @@ -1,7 +1,7 @@ package com.lagradost.cloudstream3.extractors import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.utils.* import kotlinx.coroutines.delay @@ -69,12 +69,12 @@ open class VidSrcExtractor : ExtractorApi() { } else "" } - serverslist.apmap { server -> + serverslist.amap { server -> val linkfixed = server.replace("https://vidsrc.xyz/", "https://embedsito.com/") if (linkfixed.contains("/pro")) { val srcresponse = app.get(server, referer = absoluteUrl).text val m3u8Regex = Regex("((https:|http:)//.*\\.m3u8)") - val srcm3u8 = m3u8Regex.find(srcresponse)?.value ?: return@apmap + val srcm3u8 = m3u8Regex.find(srcresponse)?.value ?: return@amap val passRegex = Regex("""['"](.*set_pass[^"']*)""") val pass = passRegex.find(srcresponse)?.groupValues?.get(1)?.replace( Regex("""^//"""), "https://" diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidstream.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidstream.kt index 1d853b2d..7eb7fbac 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidstream.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidstream.kt @@ -1,7 +1,7 @@ package com.lagradost.cloudstream3.extractors import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.argamap import com.lagradost.cloudstream3.utils.ExtractorLink @@ -37,7 +37,7 @@ class Vidstream(val mainUrl: String) { val extractorUrl = getExtractorUrl(id) argamap( { - normalApis.apmap { api -> + normalApis.amap { api -> val url = api.getExtractorUrl(id) api.getSafeUrl( url, @@ -55,8 +55,8 @@ class Vidstream(val mainUrl: String) { val qualityRegex = Regex("(\\d+)P") //a[download] - pageDoc.select(".dowload > a")?.apmap { element -> - val href = element.attr("href") ?: return@apmap + pageDoc.select(".dowload > a")?.amap { element -> + val href = element.attr("href") ?: return@amap val qual = if (element.text() .contains("HDP") ) "1080" else qualityRegex.find(element.text())?.destructured?.component1() @@ -87,7 +87,7 @@ class Vidstream(val mainUrl: String) { //val name = element.text() // Matches vidstream links with extractors - extractorApis.filter { !it.requiresReferer || !isCasting }.apmap { api -> + extractorApis.filter { !it.requiresReferer || !isCasting }.amap { api -> if (link.startsWith(api.mainUrl)) { api.getSafeUrl(link, extractorUrl, subtitleCallback, callback) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Zplayer.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Zplayer.kt index 6108d2c5..d17b427d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Zplayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Zplayer.kt @@ -1,6 +1,6 @@ package com.lagradost.cloudstream3.extractors -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink @@ -36,7 +36,7 @@ open class ZplayerV2 : ExtractorApi() { val m3u8regex = Regex("((https:|http:)\\/\\/.*\\.m3u8)") m3u8regex.findAll(testdata).map { it.value - }.toList().apmap { urlm3u8 -> + }.toList().amap { urlm3u8 -> if (urlm3u8.contains("m3u8")) { val testurl = app.get(urlm3u8, headers = mapOf("Referer" to url)).text if (testurl.contains("EXTM3U")) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/helper/AsianEmbedHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/helper/AsianEmbedHelper.kt index e70a9474..0b401c06 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/helper/AsianEmbedHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/helper/AsianEmbedHelper.kt @@ -2,7 +2,7 @@ package com.lagradost.cloudstream3.extractors.helper import android.util.Log import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor @@ -18,7 +18,7 @@ class AsianEmbedHelper { val doc = app.get(url).document val links = doc.select("div#list-server-more > ul > li.linkserver") if (!links.isNullOrEmpty()) { - links.apmap { + links.amap { val datavid = it.attr("data-video") ?: "" //Log.i("AsianEmbed", "Result => (datavid) ${datavid}") if (datavid.isNotBlank()) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/metaproviders/CrossTmdbProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/metaproviders/CrossTmdbProvider.kt index b01d188c..07aa904e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/metaproviders/CrossTmdbProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/metaproviders/CrossTmdbProvider.kt @@ -39,7 +39,7 @@ class CrossTmdbProvider : TmdbProvider() { ): Boolean { tryParseJson(data)?.let { metaData -> if (!metaData.isSuccess) return false - metaData.movies?.apmap { (apiName, data) -> + metaData.movies?.amap { (apiName, data) -> getApiFromNameNull(apiName)?.let { try { it.loadLinks(data, isCasting, subtitleCallback, callback) @@ -64,10 +64,10 @@ class CrossTmdbProvider : TmdbProvider() { val matchName = filterName(this.name) when (this) { is MovieLoadResponse -> { - val data = validApis.apmap { api -> + val data = validApis.amap { api -> try { if (api.supportedTypes.contains(TvType.Movie)) { //|| api.supportedTypes.contains(TvType.AnimeMovie) - return@apmap api.search(this.name)?.first { + return@amap api.search(this.name)?.first { if (filterName(it.name).equals( matchName, ignoreCase = true diff --git a/app/src/main/java/com/lagradost/cloudstream3/metaproviders/MultiAnimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/metaproviders/MultiAnimeProvider.kt index 0ab44b68..e8ac1876 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/metaproviders/MultiAnimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/metaproviders/MultiAnimeProvider.kt @@ -45,7 +45,7 @@ class MultiAnimeProvider : MainAPI() { override suspend fun load(url: String): LoadResponse? { return syncApi.getResult(url)?.let { res -> - val data = SyncUtil.getUrlsFromId(res.id, syncUtilType).apmap { url -> + val data = SyncUtil.getUrlsFromId(res.id, syncUtilType).amap { url -> validApis.firstOrNull { api -> url.startsWith(api.mainUrl) }?.load(url) }.filterNotNull() diff --git a/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt b/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt index 35e041be..c0f35601 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt @@ -217,18 +217,17 @@ object PluginManager { * 3. If outdated download and load the plugin * 4. Else load the plugin normally **/ - fun updateAllOnlinePluginsAndLoadThem(activity: Activity) { + fun updateAllOnlinePluginsAndLoadThem(activity: Activity) = ioSafe { // Load all plugins as fast as possible! loadAllOnlinePlugins(activity) - ioSafe { afterPluginsLoadedEvent.invoke(true) - } + val urls = (getKey>(REPOSITORIES_KEY) ?: emptyArray()) + PREBUILT_REPOSITORIES - val onlinePlugins = urls.toList().apmap { + val onlinePlugins = urls.toList().amap { getRepoPlugins(it.url)?.toList() ?: emptyList() }.flatten().distinctBy { it.second.url } @@ -249,7 +248,7 @@ object PluginManager { val updatedPlugins = mutableListOf() - outdatedPlugins.apmap { pluginData -> + outdatedPlugins.amap { pluginData -> if (pluginData.isDisabled) { //updatedPlugins.add(activity.getString(R.string.single_plugin_disabled, pluginData.onlineData.second.name)) unloadPlugin(pluginData.savedData.filePath) @@ -270,9 +269,9 @@ object PluginManager { createNotification(activity, updatedPlugins) } - ioSafe { + // ioSafe { afterPluginsLoadedEvent.invoke(true) - } + // } Log.i(TAG, "Plugin update done!") } @@ -280,9 +279,9 @@ object PluginManager { /** * Use updateAllOnlinePluginsAndLoadThem * */ - fun loadAllOnlinePlugins(activity: Activity) { + fun loadAllOnlinePlugins(activity: Activity) = ioSafe { // Load all plugins as fast as possible! - (getPluginsOnline()).toList().apmap { pluginData -> + (getPluginsOnline()).toList().amap { pluginData -> loadPlugin( activity, File(pluginData.filePath), @@ -291,7 +290,7 @@ object PluginManager { } } - fun loadAllLocalPlugins(activity: Activity) { + fun loadAllLocalPlugins(activity: Activity) = ioSafe { val dir = File(LOCAL_PLUGINS_PATH) removeKey(PLUGINS_KEY_LOCAL) @@ -299,7 +298,7 @@ object PluginManager { val res = dir.mkdirs() if (!res) { Log.w(TAG, "Failed to create local directories") - return + return@ioSafe } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt b/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt index e3203787..2564abd0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt @@ -4,7 +4,7 @@ import android.content.Context import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall @@ -95,7 +95,7 @@ object RepositoryManager { * */ suspend fun getRepoPlugins(repositoryUrl: String): List>? { val repo = parseRepository(repositoryUrl) ?: return null - return repo.pluginLists.apmap { url -> + return repo.pluginLists.amap { url -> parsePlugins(url).map { repositoryUrl to it } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/APIRepository.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/APIRepository.kt index ce695873..ef50019c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/APIRepository.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/APIRepository.kt @@ -6,6 +6,10 @@ import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.utils.ExtractorLink +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.GlobalScope.coroutineContext +import kotlinx.coroutines.async import kotlinx.coroutines.delay class APIRepository(val api: MainAPI) { @@ -27,7 +31,7 @@ class APIRepository(val api: MainAPI) { return data.isEmpty() || data == "[]" || data == "about:blank" } - private val cacheHash: HashMap, LoadResponse> = hashMapOf() + private val cacheHash: HashMap, LoadResponse> = hashMapOf() } val hasMainPage = api.hasMainPage @@ -42,7 +46,7 @@ class APIRepository(val api: MainAPI) { return safeApiCall { if (isInvalidData(url)) throw ErrorLoadingException() val fixedUrl = api.fixUrl(url) - val key = Pair(api.name,url) + val key = Pair(api.name, url) cacheHash[key] ?: api.load(fixedUrl)?.also { // we cache 20 responses because ppl often go back to the same shit + 20 because I dont want to cause too much memory leak if (cacheHash.size > 20) cacheHash.remove(cacheHash.keys.random()) @@ -78,6 +82,7 @@ class APIRepository(val api: MainAPI) { delay(delta) } + @OptIn(DelicateCoroutinesApi::class) suspend fun getMainPage(page: Int, nameIndex: Int? = null): Resource> { return safeApiCall { api.lastHomepageRequest = unixTimeMS @@ -103,11 +108,15 @@ class APIRepository(val api: MainAPI) { ) } } else { - api.mainPage.apmap { data -> - api.getMainPage( - page, - MainPageRequest(data.name, data.data, data.horizontalImages) - ) + with(CoroutineScope(coroutineContext)) { + api.mainPage.map { data -> + async { + api.getMainPage( + page, + MainPageRequest(data.name, data.data, data.horizontalImages) + ) + } + }.map { it.await() } } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index e86a0742..9792fa43 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -547,51 +547,14 @@ class HomeFragment : Fragment() { when (preview) { is Resource.Success -> { home_preview?.isVisible = true - - preview.value.apply { - home_preview_tags?.text = tags?.joinToString(" • ") ?: "" - home_preview_tags?.isGone = tags.isNullOrEmpty() - home_preview_image?.setImage(posterUrl, posterHeaders) - home_preview_title?.text = name - home_preview_play?.setOnClickListener { - activity?.loadResult(url, apiName, START_ACTION_RESUME_LATEST) - //activity.loadSearchResult(url, START_ACTION_RESUME_LATEST) - } - home_preview_info?.setOnClickListener { - activity?.loadResult(url, apiName) - //activity.loadSearchResult(random) - } - // very ugly code, but I dont care - val watchType = DataStoreHelper.getResultWatchState(preview.value.getId()) - home_preview_bookmark?.setText(watchType.stringRes) - home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds( - null, - getDrawable(home_preview_bookmark.context, watchType.iconRes), - null, - null - ) - home_preview_bookmark?.setOnClickListener { fab -> - activity?.showBottomDialog( - WatchType.values().map { fab.context.getString(it.stringRes) } - .toList(), - DataStoreHelper.getResultWatchState(preview.value.getId()).ordinal, - fab.context.getString(R.string.action_add_to_bookmarks), - showApply = false, - {}) { - val newValue = WatchType.values()[it] - home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds( - null, - getDrawable(home_preview_bookmark.context, newValue.iconRes), - null, - null - ) - home_preview_bookmark?.setText(newValue.stringRes) - - updateWatchStatus(preview.value, newValue) - reloadStored() - } - } + (home_preview_viewpager?.adapter as? HomeScrollAdapter)?.apply { + setItems(preview.value) + // home_preview_viewpager?.setCurrentItem(1000, false) } + + //.also { + //home_preview_viewpager?.adapter = + //} } else -> { home_preview?.isVisible = false @@ -606,6 +569,58 @@ class HomeFragment : Fragment() { searchText.setTextColor(color) searchText.setHintTextColor(color) } + + home_preview_viewpager?.apply { + setPageTransformer(false, HomeScrollTransformer()) + adapter = HomeScrollAdapter { load -> + load.apply { + home_preview_tags?.text = tags?.joinToString(" • ") ?: "" + home_preview_tags?.isGone = tags.isNullOrEmpty() + home_preview_image?.setImage(posterUrl, posterHeaders) + home_preview_title?.text = name + home_preview_play?.setOnClickListener { + activity?.loadResult(url, apiName, START_ACTION_RESUME_LATEST) + //activity.loadSearchResult(url, START_ACTION_RESUME_LATEST) + } + home_preview_info?.setOnClickListener { + activity?.loadResult(url, apiName) + //activity.loadSearchResult(random) + } + // very ugly code, but I dont care + val watchType = DataStoreHelper.getResultWatchState(load.getId()) + home_preview_bookmark?.setText(watchType.stringRes) + home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds( + null, + getDrawable(home_preview_bookmark.context, watchType.iconRes), + null, + null + ) + home_preview_bookmark?.setOnClickListener { fab -> + activity?.showBottomDialog( + WatchType.values().map { fab.context.getString(it.stringRes) } + .toList(), + DataStoreHelper.getResultWatchState(load.getId()).ordinal, + fab.context.getString(R.string.action_add_to_bookmarks), + showApply = false, + {}) { + val newValue = WatchType.values()[it] + home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds( + null, + getDrawable(home_preview_bookmark.context, newValue.iconRes), + null, + null + ) + home_preview_bookmark?.setText(newValue.stringRes) + + updateWatchStatus(load, newValue) + reloadStored() + } + } + } + + } + } + observe(homeViewModel.apiName) { apiName -> currentApiName = apiName // setKey(USER_SELECTED_HOMEPAGE_API, apiName) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt new file mode 100644 index 00000000..b36d7582 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt @@ -0,0 +1,60 @@ +package com.lagradost.cloudstream3.ui.home + +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import androidx.viewpager.widget.PagerAdapter +import com.lagradost.cloudstream3.LoadResponse +import com.lagradost.cloudstream3.utils.UIHelper.setImage + + +class HomeScrollAdapter(private val onPrimaryCallback: (LoadResponse) -> Unit) : PagerAdapter() { + private var items: List = listOf() + + fun setItems(newItems: List) { + items = newItems + + notifyDataSetChanged() + } + + override fun getCount(): Int { + return Int.MAX_VALUE//items.size + } + + override fun getItemPosition(`object`: Any): Int { + return POSITION_NONE//super.getItemPosition(`object`) + } + + private fun getItemAtPosition(idx: Int): LoadResponse { + return items[idx % items.size] + } + + override fun setPrimaryItem(container: ViewGroup, position: Int, `object`: Any) { + super.setPrimaryItem(container, position, `object`) + onPrimaryCallback.invoke(getItemAtPosition(position)) + } + + override fun instantiateItem(container: ViewGroup, position: Int): Any { + val image = ImageView(container.context) + val item = getItemAtPosition(position) + image.scaleType = ImageView.ScaleType.CENTER_CROP + image.setImage(item.posterUrl ?: item.backgroundPosterUrl, item.posterHeaders) + + // val itemView: View = mLayoutInflater.inflate(R.layout.pager_item, container, false) + + // val imageView: ImageView = itemView.findViewById(R.id.imageView) as ImageView + // imageView.setImageResource(mResources.get(position)) + + container.addView(image) + + return image + } + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + container.removeView(`object` as View) + } + + override fun isViewFromObject(view: View, `object`: Any): Boolean { + return view === `object` + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollTransformer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollTransformer.kt new file mode 100644 index 00000000..04b6964b --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollTransformer.kt @@ -0,0 +1,13 @@ +package com.lagradost.cloudstream3.ui.home + +import android.view.View +import androidx.viewpager.widget.ViewPager + +class HomeScrollTransformer : ViewPager.PageTransformer { + override fun transformPage(page: View, position: Float) { + page.setPadding( + maxOf(0, (-position * page.width / 2).toInt()), 0, + maxOf(0, (position * page.width / 2).toInt()), 0 + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt index af24973d..43d849cf 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt @@ -21,6 +21,8 @@ import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi import com.lagradost.cloudstream3.ui.WatchType +import com.lagradost.cloudstream3.utils.Coroutines.ioSafe +import com.lagradost.cloudstream3.utils.Coroutines.ioWork import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE import com.lagradost.cloudstream3.utils.DataStoreHelper import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllResumeStateIds @@ -33,6 +35,7 @@ import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API import com.lagradost.cloudstream3.utils.VideoDownloadHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.async import kotlinx.coroutines.withContext import java.util.* import kotlin.collections.set @@ -58,9 +61,9 @@ class HomeViewModel : ViewModel() { val bookmarks: LiveData>> = _bookmarks private val _resumeWatching = MutableLiveData>() - private val _preview = MutableLiveData>() + private val _preview = MutableLiveData>>() val resumeWatching: LiveData> = _resumeWatching - val preview: LiveData> = _preview + val preview: LiveData>> = _preview fun loadResumeWatching() = viewModelScope.launchSafe { val resumeWatching = withContext(Dispatchers.IO) { @@ -210,7 +213,7 @@ class HomeViewModel : ViewModel() { } - private fun load(api: MainAPI?) = viewModelScope.launchSafe { + private fun load(api: MainAPI?) = ioSafe { repo = if (api != null) { APIRepository(api) } else { @@ -236,7 +239,35 @@ class HomeViewModel : ViewModel() { ExpandableHomepageList(filteredList, 1, home.hasNext) } } + val items = data.value.mapNotNull { it?.items }.flatten() + val responses = ioWork { + items.flatMap { it.list }.shuffled().take(6).map { searchResponse -> + async { repo?.load(searchResponse.url) } + }.map { it.await() }.mapNotNull { if (it != null && it is Resource.Success) it.value else null } } + //.amap { searchResponse -> + // repo?.load(searchResponse.url) + ///} + + //.map { searchResponse -> + // async { repo?.load(searchResponse.url) } + // }.map { it.await() } + + + if (responses.isEmpty()) { + _preview.postValue( + Resource.Failure( + false, + null, + null, + "No homepage responses" + ) + ) + } else { + _preview.postValue(Resource.Success(responses)) + } + + /* items.randomOrNull()?.list?.randomOrNull()?.url?.let { url -> // backup request in case first fails var first = repo?.load(url) @@ -264,7 +295,7 @@ class HomeViewModel : ViewModel() { "No homepage items" ) ) - } + }*/ _page.postValue(Resource.Success(expandable)) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt index e20a6c7b..816b1298 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt @@ -344,7 +344,7 @@ class GeneratorPlayer : FullScreenPlayer() { seasonNumber = currentTempMeta.season, lang = currentLanguageTwoLetters.ifBlank { null } ) - val results = providers.apmap { + val results = providers.amap { try { it.search(search) } catch (e: Exception) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt index 2c8a5372..1f242481 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt @@ -1,6 +1,6 @@ package com.lagradost.cloudstream3.ui.player -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.utils.* import java.net.URI @@ -46,7 +46,7 @@ class LinkGenerator( subtitleCallback: (SubtitleData) -> Unit, offset: Int ): Boolean { - links.apmap { link -> + links.amap { link -> if (!extract || !loadExtractor(link, referer, { subtitleCallback(PlayerSubtitleHelper.getSubtitleData(it)) }) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt index 7c099793..f424989e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt @@ -1972,7 +1972,7 @@ class ResultViewModel2 : ViewModel() { ): List = coroutineScope { var currentCount = 0 - return@coroutineScope loadResponse.trailers.apmap { trailerData -> + return@coroutineScope loadResponse.trailers.amap { trailerData -> try { val links = arrayListOf() val subs = arrayListOf() diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/SyncViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/SyncViewModel.kt index 513d68e8..91415d26 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/SyncViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/SyncViewModel.kt @@ -4,7 +4,7 @@ import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.SyncApis @@ -197,7 +197,7 @@ class SyncViewModel : ViewModel() { /// modifies the current sync data, return null if you don't want to change it private fun modifyData(update: ((SyncAPI.SyncStatus) -> (SyncAPI.SyncStatus?))) = ioSafe { - syncs.apmap { (prefix, id) -> + syncs.amap { (prefix, id) -> repos.firstOrNull { it.idPrefix == prefix }?.let { repo -> if (repo.hasAccount()) { val result = repo.getStatus(id) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt index b629b73f..aceda644 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt @@ -9,7 +9,7 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.getKeys import com.lagradost.cloudstream3.AcraApplication.Companion.setKey import com.lagradost.cloudstream3.SearchResponse -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.launchSafe import com.lagradost.cloudstream3.ui.APIRepository @@ -108,9 +108,9 @@ class SearchViewModel : ViewModel() { repos.filter { a -> (ignoreSettings || (providersActive.isEmpty() || providersActive.contains(a.name))) && (!isQuickSearch || a.hasQuickSearch) - }.apmap { a -> // Parallel + }.amap { a -> // Parallel val search = if (isQuickSearch) a.quickSearch(query) else a.search(query) - if (currentSearchIndex != currentIndex) return@apmap + if (currentSearchIndex != currentIndex) return@amap currentList.add(OnGoingSearch(a.name, search)) _currentSearch.postValue(currentList) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/ExtensionsViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/ExtensionsViewModel.kt index 897e7366..63ed5357 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/ExtensionsViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/ExtensionsViewModel.kt @@ -6,7 +6,7 @@ import androidx.lifecycle.ViewModel import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.R -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.mvvm.Some import com.lagradost.cloudstream3.mvvm.debugAssert import com.lagradost.cloudstream3.plugins.PluginManager @@ -49,7 +49,7 @@ class ExtensionsViewModel : ViewModel() { val urls = (getKey>(REPOSITORIES_KEY) ?: emptyArray()) + PREBUILT_REPOSITORIES - val onlinePlugins = urls.toList().apmap { + val onlinePlugins = urls.toList().amap { RepositoryManager.getRepoPlugins(it.url)?.toList() ?: emptyList() }.flatten().distinctBy { it.second.url } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt index 536dc33b..894a9331 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt @@ -10,7 +10,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.R -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.mvvm.launchSafe import com.lagradost.cloudstream3.plugins.PluginManager import com.lagradost.cloudstream3.plugins.PluginManager.getPluginPath @@ -101,7 +101,7 @@ class PluginsViewModel : ViewModel() { Toast.LENGTH_SHORT ) } - }.apmap { (repo, metadata) -> + }.amap { (repo, metadata) -> PluginManager.downloadAndLoadPlugin( activity, metadata.url, diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/BackupUtils.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/BackupUtils.kt index 08c03d6c..338b1ed2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/BackupUtils.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/BackupUtils.kt @@ -13,7 +13,6 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.module.kotlin.readValue import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.R -import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.plugins.PLUGINS_KEY import com.lagradost.cloudstream3.plugins.PLUGINS_KEY_LOCAL @@ -28,7 +27,6 @@ import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_S import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_TOKEN_KEY import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_UNIXTIME_KEY import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_USER_KEY -import com.lagradost.cloudstream3.syncproviders.providers.OpenSubtitlesApi import com.lagradost.cloudstream3.syncproviders.providers.OpenSubtitlesApi.Companion.OPEN_SUBTITLES_USER_KEY import com.lagradost.cloudstream3.utils.DataStore.getDefaultSharedPrefs import com.lagradost.cloudstream3.utils.DataStore.getSharedPrefs diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index bce49c22..3d7e3ba5 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -279,30 +279,40 @@ --> - + + android:layout_height="500dp" + android:visibility="gone" + tools:visibility="visible"> + + + + + + android:alpha="1" + android:background="@drawable/background_shadow" + android:rotation="180" + android:visibility="visible" /> + + android:layout_height="wrap_content" + android:orientation="vertical"> - + android:textSize="20dp" + android:layout_margin="20dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/search" + android:textColor="@color/white" + app:drawableLeftCompat="@drawable/search_icon" + app:tint="@color/white" /> + --> + + android:layout_gravity="center" + android:gravity="center" + android:orientation="horizontal" + android:padding="20dp"> + app:tint="?attr/white" /> + + + app:tint="?attr/white" /> @@ -522,15 +535,15 @@ + android:orientation="horizontal" + app:singleSelection="true"> diff --git a/app/src/test/java/com/lagradost/cloudstream3/ProviderTests.kt b/app/src/test/java/com/lagradost/cloudstream3/ProviderTests.kt index 34bd9f18..846dfdb5 100644 --- a/app/src/test/java/com/lagradost/cloudstream3/ProviderTests.kt +++ b/app/src/test/java/com/lagradost/cloudstream3/ProviderTests.kt @@ -162,7 +162,7 @@ class ProviderTests { // @Test // fun providerCorrectHomepage() { // runBlocking { -// getAllProviders().apmap { api -> +// getAllProviders().amap { api -> // if (api.hasMainPage) { // try { // val homepage = api.getMainPage() @@ -197,7 +197,7 @@ class ProviderTests { // suspend fun providerCorrect() { // val invalidProvider = ArrayList>() // val providers = getAllProviders() -// providers.apmap { api -> +// providers.amap { api -> // try { // println("Trying $api") // if (testSingleProviderApi(api)) {