mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	scroll
This commit is contained in:
		
							parent
							
								
									47b79550f1
								
							
						
					
					
						commit
						d349190238
					
				
					 29 changed files with 337 additions and 179 deletions
				
			
		|  | @ -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<Pair<MainAPI, Exception?>>() | ||||
|             val providers = getAllProviders() | ||||
|             providers.apmap { api -> | ||||
|             providers.amap { api -> | ||||
|                 try { | ||||
|                     println("Trying $api") | ||||
|                     if (testSingleProviderApi(api)) { | ||||
|  |  | |||
|  | @ -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<ExtractorLink>() | ||||
|                 val subs = arrayListOf<SubtitleFile>() | ||||
|                 if (!loadExtractor( | ||||
|  |  | |||
|  | @ -592,7 +592,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | |||
|                 api.init() | ||||
|             } | ||||
| 
 | ||||
|             inAppAuths.apmap { api -> | ||||
|             inAppAuths.amap { api -> | ||||
|                 try { | ||||
|                     api.initialize() | ||||
|                 } catch (e: Exception) { | ||||
|  |  | |||
|  | @ -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 <T, R> Iterable<T>.pmap( | |||
|     return ArrayList<R>(destination) | ||||
| }*/ | ||||
| 
 | ||||
| 
 | ||||
| @OptIn(DelicateCoroutinesApi::class) | ||||
| suspend fun <K, V, R> Map<out K, V>.amap(f: suspend (Map.Entry<K, V>) -> R): List<R> = | ||||
|     with(CoroutineScope(GlobalScope.coroutineContext)) { | ||||
|         map { async { f(it) } }.map { it.await() } | ||||
|     } | ||||
| 
 | ||||
| fun <K, V, R> Map<out K, V>.apmap(f: suspend (Map.Entry<K, V>) -> R): List<R> = runBlocking { | ||||
|     map { async { f(it) } }.map { it.await() } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @OptIn(DelicateCoroutinesApi::class) | ||||
| suspend fun <A, B> List<A>.amap(f: suspend (A) -> B): List<B> = | ||||
|     with(CoroutineScope(GlobalScope.coroutineContext)) { | ||||
|         map { async { f(it) } }.map { it.await() } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| fun <A, B> List<A>.apmap(f: suspend (A) -> B): List<B> = runBlocking { | ||||
|     map { async { f(it) } }.map { it.await() } | ||||
| } | ||||
|  | @ -38,6 +52,12 @@ fun <A, B> List<A>.apmapIndexed(f: suspend (index: Int, A) -> B): List<B> = runB | |||
|     mapIndexed { index, a -> async { f(index, a) } }.map { it.await() } | ||||
| } | ||||
| 
 | ||||
| @OptIn(DelicateCoroutinesApi::class) | ||||
| suspend fun <A, B> List<A>.amapIndexed(f: suspend (index: Int, A) -> B): List<B> = | ||||
|     with(CoroutineScope(GlobalScope.coroutineContext)) { | ||||
|         mapIndexed { index, a -> async { f(index, a) } }.map { it.await() } | ||||
|     } | ||||
| 
 | ||||
| // run code in parallel | ||||
| /*fun <R> argpmap( | ||||
|     vararg transforms: () -> R, | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
|  | @ -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) | ||||
|                         } | ||||
|  |  | |||
|  | @ -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://" | ||||
|  |  | |||
|  | @ -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) | ||||
|                             } | ||||
|  |  | |||
|  | @ -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")) { | ||||
|  |  | |||
|  | @ -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()) { | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ class CrossTmdbProvider : TmdbProvider() { | |||
|     ): Boolean { | ||||
|         tryParseJson<CrossMetaData>(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 | ||||
|  |  | |||
|  | @ -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() | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<Array<RepositoryData>>(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<String>() | ||||
| 
 | ||||
|         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 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<Pair<String, SitePlugin>>? { | ||||
|         val repo = parseRepository(repositoryUrl) ?: return null | ||||
|         return repo.pluginLists.apmap { url -> | ||||
|         return repo.pluginLists.amap { url -> | ||||
|             parsePlugins(url).map { | ||||
|                 repositoryUrl to it | ||||
|             } | ||||
|  |  | |||
|  | @ -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<Pair<String,String>, LoadResponse> = hashMapOf() | ||||
|         private val cacheHash: HashMap<Pair<String, String>, 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<List<HomePageResponse?>> { | ||||
|         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() } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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<LoadResponse> = listOf() | ||||
| 
 | ||||
|     fun setItems(newItems: List<LoadResponse>) { | ||||
|         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<View>(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` | ||||
|     } | ||||
| } | ||||
|  | @ -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 | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|  | @ -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<Pair<Boolean, List<SearchResponse>>> = _bookmarks | ||||
| 
 | ||||
|     private val _resumeWatching = MutableLiveData<List<SearchResponse>>() | ||||
|     private val _preview = MutableLiveData<Resource<LoadResponse>>() | ||||
|     private val _preview = MutableLiveData<Resource<List<LoadResponse>>>() | ||||
|     val resumeWatching: LiveData<List<SearchResponse>> = _resumeWatching | ||||
|     val preview: LiveData<Resource<LoadResponse>> = _preview | ||||
|     val preview: LiveData<Resource<List<LoadResponse>>> = _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)) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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)) | ||||
|                 }) { | ||||
|  |  | |||
|  | @ -1972,7 +1972,7 @@ class ResultViewModel2 : ViewModel() { | |||
|     ): List<ExtractedTrailerData> = | ||||
|         coroutineScope { | ||||
|             var currentCount = 0 | ||||
|             return@coroutineScope loadResponse.trailers.apmap { trailerData -> | ||||
|             return@coroutineScope loadResponse.trailers.amap { trailerData -> | ||||
|                 try { | ||||
|                     val links = arrayListOf<ExtractorLink>() | ||||
|                     val subs = arrayListOf<SubtitleFile>() | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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) | ||||
|                 } | ||||
|  |  | |||
|  | @ -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<Array<RepositoryData>>(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 } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -279,30 +279,40 @@ | |||
|                                     <requestFocus /> | ||||
|                                 </ImageView>--> | ||||
|             </FrameLayout> | ||||
| 
 | ||||
|             <!--https://www.digitalocean.com/community/tutorials/android-viewpager-example-tutorial--> | ||||
|             <FrameLayout | ||||
|                 tools:visibility="visible" | ||||
|                 android:visibility="gone" | ||||
|                 android:id="@+id/home_preview" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="500dp"> | ||||
|                 android:layout_height="500dp" | ||||
|                 android:visibility="gone" | ||||
|                 tools:visibility="visible"> | ||||
| 
 | ||||
|                 <androidx.viewpager.widget.ViewPager | ||||
|                     android:id="@+id/home_preview_viewpager" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="match_parent"> | ||||
| 
 | ||||
|                 </androidx.viewpager.widget.ViewPager> | ||||
| 
 | ||||
|                 <ImageView | ||||
|                     android:alpha="0.8" | ||||
|                     android:visibility="gone" | ||||
|                     android:id="@+id/home_preview_image" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="match_parent" | ||||
|                     android:alpha="0.8" | ||||
|                     android:scaleType="centerCrop" | ||||
|                     tools:src="@drawable/example_poster" /> | ||||
| 
 | ||||
|                 <View | ||||
|                     android:visibility="visible" | ||||
|                     android:id="@+id/title_shadow_top" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="150dp" | ||||
|                     android:alpha="1" | ||||
|                     android:rotation="180" | ||||
|                     android:layout_gravity="top" | ||||
|                     android:background="@drawable/background_shadow" /> | ||||
|                     android:alpha="1" | ||||
|                     android:background="@drawable/background_shadow" | ||||
|                     android:rotation="180" | ||||
|                     android:visibility="visible" /> | ||||
| 
 | ||||
|                 <View | ||||
|                     android:id="@+id/title_shadow" | ||||
|                     android:layout_width="match_parent" | ||||
|  | @ -312,62 +322,63 @@ | |||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:id="@+id/home_padding" | ||||
|                     android:orientation="vertical" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content"> | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:orientation="vertical"> | ||||
| 
 | ||||
|                     <androidx.appcompat.widget.SearchView | ||||
|                         android:id="@+id/home_search" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:gravity="start" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:layout_gravity="start" | ||||
|                         android:editTextColor="@color/white" | ||||
|                         android:gravity="start" | ||||
|                         android:iconifiedByDefault="true" | ||||
|                         android:textColor="@color/white" | ||||
|                         android:textColorHint="@color/white" | ||||
|                         app:iconifiedByDefault="true" | ||||
|                         app:queryBackground="@color/transparent" | ||||
|                         app:queryHint="@string/search" | ||||
|                         android:textColor="@color/white" | ||||
|                         android:textColorHint="@color/white" | ||||
|                         android:editTextColor="@color/white" | ||||
| 
 | ||||
|                         app:searchIcon="@drawable/search_icon" | ||||
|                         tools:ignore="RtlSymmetry" /> | ||||
|                 </LinearLayout> | ||||
| 
 | ||||
| <!-- | ||||
|                 <TextView | ||||
|                     android:visibility="gone" | ||||
|                     android:id="@+id/test_search" | ||||
|                     android:background="?android:attr/selectableItemBackgroundBorderless" | ||||
|                     android:layout_gravity="start" | ||||
|                     android:gravity="center" | ||||
|                 <!-- | ||||
|                                 <TextView | ||||
|                                     android:visibility="gone" | ||||
|                                     android:id="@+id/test_search" | ||||
|                                     android:background="?android:attr/selectableItemBackgroundBorderless" | ||||
|                                     android:layout_gravity="start" | ||||
|                                     android:gravity="center" | ||||
| 
 | ||||
|                     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: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" /> | ||||
|                 --> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_gravity="bottom" | ||||
|                     android:orientation="vertical"> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:paddingStart="30dp" | ||||
|                         android:paddingEnd="30dp" | ||||
|                         android:textStyle="bold" | ||||
|                         android:paddingBottom="10dp" | ||||
|                         android:id="@+id/home_preview_title" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingStart="30dp" | ||||
|                         android:paddingEnd="30dp" | ||||
|                         android:paddingBottom="10dp" | ||||
|                         android:textColor="?attr/white" | ||||
|                         android:textSize="17sp" | ||||
|                         android:textStyle="bold" | ||||
|                         tools:text="The Perfect Run" /> | ||||
|                     <!--<TextView | ||||
|                         android:paddingStart="30dp" | ||||
|  | @ -380,60 +391,62 @@ | |||
|                         android:textSize="14sp" | ||||
|                         tools:text="5 seasons 50 episodes" />--> | ||||
|                     <TextView | ||||
|                         android:paddingStart="30dp" | ||||
|                         android:paddingEnd="30dp" | ||||
|                         android:id="@+id/home_preview_tags" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingStart="30dp" | ||||
|                         android:paddingEnd="30dp" | ||||
|                         android:textColor="?attr/white" | ||||
|                         android:textSize="14sp" | ||||
|                         tools:text="Hello • World • Tags" /> | ||||
| 
 | ||||
|                     <LinearLayout | ||||
|                         android:padding="20dp" | ||||
|                         android:gravity="center" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:orientation="horizontal"> | ||||
|                         android:layout_gravity="center" | ||||
|                         android:gravity="center" | ||||
|                         android:orientation="horizontal" | ||||
|                         android:padding="20dp"> | ||||
| 
 | ||||
|                         <TextView | ||||
|                             android:id="@+id/home_preview_bookmark" | ||||
|                             android:background="?android:attr/selectableItemBackgroundBorderless" | ||||
|                             android:layout_gravity="center" | ||||
|                             android:gravity="center" | ||||
|                             android:layout_marginStart="25dp" | ||||
|                             android:layout_marginEnd="25dp" | ||||
|                             android:layout_width="70dp" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:layout_gravity="center" | ||||
|                             android:layout_marginStart="25dp" | ||||
|                             android:layout_marginEnd="25dp" | ||||
|                             android:background="?android:attr/selectableItemBackgroundBorderless" | ||||
|                             android:gravity="center" | ||||
|                             android:text="@string/none" | ||||
|                             android:textColor="?attr/white" | ||||
|                             app:drawableTint="?attr/white" | ||||
|                             app:drawableTopCompat="@drawable/ic_baseline_add_24" | ||||
|                             app:tint="?attr/white" | ||||
|                             app:drawableTint="?attr/white" /> | ||||
|                             app:tint="?attr/white" /> | ||||
| 
 | ||||
|                         <com.google.android.material.button.MaterialButton | ||||
|                             android:layout_gravity="center" | ||||
|                             style="@style/WhiteButton" | ||||
|                             android:id="@+id/home_preview_play" | ||||
|                             style="@style/WhiteButton" | ||||
|                             android:layout_width="wrap_content" | ||||
|                             android:layout_gravity="center" | ||||
| 
 | ||||
|                             android:text="@string/home_play" | ||||
|                             app:icon="@drawable/ic_baseline_play_arrow_24" /> | ||||
| 
 | ||||
|                         <TextView | ||||
|                             android:background="?android:attr/selectableItemBackgroundBorderless" | ||||
|                             android:id="@+id/home_preview_info" | ||||
|                             android:gravity="center" | ||||
|                             android:layout_width="70dp" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:layout_gravity="center" | ||||
|                             android:layout_marginStart="25dp" | ||||
|                             android:layout_marginEnd="25dp" | ||||
|                             android:layout_width="70dp" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:background="?android:attr/selectableItemBackgroundBorderless" | ||||
|                             android:gravity="center" | ||||
|                             android:text="@string/home_info" | ||||
|                             android:textColor="?attr/white" | ||||
|                             app:drawableTint="?attr/white" | ||||
|                             app:drawableTopCompat="@drawable/ic_outline_info_24" | ||||
|                             app:tint="?attr/white" | ||||
|                             app:drawableTint="?attr/white" /> | ||||
|                             app:tint="?attr/white" /> | ||||
|                     </LinearLayout> | ||||
|                 </LinearLayout> | ||||
|             </FrameLayout> | ||||
|  | @ -522,15 +535,15 @@ | |||
| 
 | ||||
|                         <com.google.android.material.chip.ChipGroup | ||||
|                             android:layout_width="wrap_content" | ||||
|                             app:singleSelection="true" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:orientation="horizontal"> | ||||
|                             android:orientation="horizontal" | ||||
|                             app:singleSelection="true"> | ||||
| 
 | ||||
|                             <com.google.android.material.chip.Chip | ||||
|                                 android:id="@+id/home_type_watching_btt" | ||||
|                                 style="@style/ChipFilled" | ||||
|                                 android:layout_height="wrap_content" | ||||
|                                 android:layout_width="wrap_content" | ||||
|                                 android:layout_height="wrap_content" | ||||
| 
 | ||||
|                                 android:nextFocusLeft="@id/nav_rail_view" | ||||
|                                 android:nextFocusRight="@id/home_plan_to_watch_btt" | ||||
|  | @ -539,8 +552,8 @@ | |||
|                             <com.google.android.material.chip.Chip | ||||
|                                 android:id="@+id/home_plan_to_watch_btt" | ||||
|                                 style="@style/ChipFilled" | ||||
|                                 android:layout_height="wrap_content" | ||||
|                                 android:layout_width="wrap_content" | ||||
|                                 android:layout_height="wrap_content" | ||||
| 
 | ||||
|                                 android:nextFocusLeft="@id/home_type_watching_btt" | ||||
|                                 android:nextFocusRight="@id/home_type_on_hold_btt" | ||||
|  | @ -549,8 +562,8 @@ | |||
|                             <com.google.android.material.chip.Chip | ||||
|                                 android:id="@+id/home_type_on_hold_btt" | ||||
|                                 style="@style/ChipFilled" | ||||
|                                 android:layout_height="wrap_content" | ||||
|                                 android:layout_width="wrap_content" | ||||
|                                 android:layout_height="wrap_content" | ||||
| 
 | ||||
|                                 android:nextFocusLeft="@id/home_plan_to_watch_btt" | ||||
|                                 android:nextFocusRight="@id/home_type_dropped_btt" | ||||
|  | @ -559,8 +572,8 @@ | |||
|                             <com.google.android.material.chip.Chip | ||||
|                                 android:id="@+id/home_type_dropped_btt" | ||||
|                                 style="@style/ChipFilled" | ||||
|                                 android:layout_height="wrap_content" | ||||
|                                 android:layout_width="wrap_content" | ||||
|                                 android:layout_height="wrap_content" | ||||
| 
 | ||||
|                                 android:nextFocusLeft="@id/home_type_on_hold_btt" | ||||
|                                 android:nextFocusRight="@id/home_type_completed_btt" | ||||
|  | @ -568,10 +581,10 @@ | |||
| 
 | ||||
|                             <com.google.android.material.chip.Chip | ||||
|                                 android:id="@+id/home_type_completed_btt" | ||||
|                                 android:layout_height="wrap_content" | ||||
|                                 style="@style/ChipFilled" | ||||
|                                 android:layout_width="wrap_content" | ||||
| 
 | ||||
|                                 style="@style/ChipFilled" | ||||
|                                 android:layout_height="wrap_content" | ||||
|                                 android:nextFocusLeft="@id/home_type_dropped_btt" | ||||
|                                 android:text="@string/type_completed" /> | ||||
|                         </com.google.android.material.chip.ChipGroup> | ||||
|  |  | |||
|  | @ -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<Pair<MainAPI, Exception?>>() | ||||
| //         val providers = getAllProviders() | ||||
| //         providers.apmap { api -> | ||||
| //         providers.amap { api -> | ||||
| //             try { | ||||
| //                 println("Trying $api") | ||||
| //                 if (testSingleProviderApi(api)) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue