This commit is contained in:
reduplicated 2022-10-31 01:16:15 +01:00
parent 47b79550f1
commit d349190238
29 changed files with 337 additions and 179 deletions

View File

@ -180,7 +180,7 @@ class ExampleInstrumentedTest {
@Test @Test
fun providerCorrectHomepage() { fun providerCorrectHomepage() {
runBlocking { runBlocking {
getAllProviders().apmap { api -> getAllProviders().amap { api ->
if (api.hasMainPage) { if (api.hasMainPage) {
try { try {
val homepage = api.getMainPage() val homepage = api.getMainPage()
@ -217,7 +217,7 @@ class ExampleInstrumentedTest {
runBlocking { runBlocking {
val invalidProvider = ArrayList<Pair<MainAPI, Exception?>>() val invalidProvider = ArrayList<Pair<MainAPI, Exception?>>()
val providers = getAllProviders() val providers = getAllProviders()
providers.apmap { api -> providers.amap { api ->
try { try {
println("Trying $api") println("Trying $api")
if (testSingleProviderApi(api)) { if (testSingleProviderApi(api)) {

View File

@ -1066,7 +1066,7 @@ interface LoadResponse {
) { ) {
if (!isTrailersEnabled || trailerUrls == null) return if (!isTrailersEnabled || trailerUrls == null) return
trailers.addAll(trailerUrls.map { TrailerData(it, referer, addRaw) }) 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 links = arrayListOf<ExtractorLink>()
val subs = arrayListOf<SubtitleFile>() val subs = arrayListOf<SubtitleFile>()
if (!loadExtractor( if (!loadExtractor(

View File

@ -592,7 +592,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
api.init() api.init()
} }
inAppAuths.apmap { api -> inAppAuths.amap { api ->
try { try {
api.initialize() api.initialize()
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -1,8 +1,7 @@
package com.lagradost.cloudstream3 package com.lagradost.cloudstream3
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import kotlinx.coroutines.async import kotlinx.coroutines.*
import kotlinx.coroutines.runBlocking
//https://stackoverflow.com/questions/34697828/parallel-operations-on-kotlin-collections //https://stackoverflow.com/questions/34697828/parallel-operations-on-kotlin-collections
/* /*
@ -26,10 +25,25 @@ fun <T, R> Iterable<T>.pmap(
return ArrayList<R>(destination) 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 { 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() } 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 { fun <A, B> List<A>.apmap(f: suspend (A) -> B): List<B> = runBlocking {
map { async { f(it) } }.map { it.await() } 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() } 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 // run code in parallel
/*fun <R> argpmap( /*fun <R> argpmap(
vararg transforms: () -> R, vararg transforms: () -> R,

View File

@ -1,6 +1,6 @@
package com.lagradost.cloudstream3.extractors package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.amap
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
@ -21,10 +21,10 @@ class Fastream: ExtractorApi() {
Pair("file_code",id), Pair("file_code",id),
Pair("auto","1") Pair("auto","1")
)).document )).document
response.select("script").apmap { script -> response.select("script").amap { script ->
if (script.data().contains("sources")) { if (script.data().contains("sources")) {
val m3u8regex = Regex("((https:|http:)\\/\\/.*\\.m3u8)") 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( generateM3u8(
name, name,
m3u8, m3u8,

View File

@ -1,7 +1,7 @@
package com.lagradost.cloudstream3.extractors package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.amap
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
@ -35,7 +35,7 @@ class Pelisplus(val mainUrl: String) {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
try { try {
normalApis.apmap { api -> normalApis.amap { api ->
val url = api.getExtractorUrl(id) val url = api.getExtractorUrl(id)
api.getSafeUrl(url, subtitleCallback = subtitleCallback, callback = callback) api.getSafeUrl(url, subtitleCallback = subtitleCallback, callback = callback)
} }
@ -51,8 +51,8 @@ class Pelisplus(val mainUrl: String) {
val qualityRegex = Regex("(\\d+)P") val qualityRegex = Regex("(\\d+)P")
//a[download] //a[download]
pageDoc.select(".dowload > a")?.apmap { element -> pageDoc.select(".dowload > a")?.amap { element ->
val href = element.attr("href") ?: return@apmap val href = element.attr("href") ?: return@amap
val qual = if (element.text() val qual = if (element.text()
.contains("HDP") .contains("HDP")
) "1080" else qualityRegex.find(element.text())?.destructured?.component1() ) "1080" else qualityRegex.find(element.text())?.destructured?.component1()
@ -84,7 +84,7 @@ class Pelisplus(val mainUrl: String) {
//val name = element.text() //val name = element.text()
// Matches vidstream links with extractors // Matches vidstream links with extractors
extractorApis.filter { !it.requiresReferer || !isCasting }.apmap { api -> extractorApis.filter { !it.requiresReferer || !isCasting }.amap { api ->
if (link.startsWith(api.mainUrl)) { if (link.startsWith(api.mainUrl)) {
api.getSafeUrl(link, extractorUrl, subtitleCallback, callback) api.getSafeUrl(link, extractorUrl, subtitleCallback, callback)
} }

View File

@ -1,7 +1,7 @@
package com.lagradost.cloudstream3.extractors package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.amap
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -69,12 +69,12 @@ open class VidSrcExtractor : ExtractorApi() {
} else "" } else ""
} }
serverslist.apmap { server -> serverslist.amap { server ->
val linkfixed = server.replace("https://vidsrc.xyz/", "https://embedsito.com/") val linkfixed = server.replace("https://vidsrc.xyz/", "https://embedsito.com/")
if (linkfixed.contains("/pro")) { if (linkfixed.contains("/pro")) {
val srcresponse = app.get(server, referer = absoluteUrl).text val srcresponse = app.get(server, referer = absoluteUrl).text
val m3u8Regex = Regex("((https:|http:)//.*\\.m3u8)") 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 passRegex = Regex("""['"](.*set_pass[^"']*)""")
val pass = passRegex.find(srcresponse)?.groupValues?.get(1)?.replace( val pass = passRegex.find(srcresponse)?.groupValues?.get(1)?.replace(
Regex("""^//"""), "https://" Regex("""^//"""), "https://"

View File

@ -1,7 +1,7 @@
package com.lagradost.cloudstream3.extractors package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.amap
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.argamap import com.lagradost.cloudstream3.argamap
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
@ -37,7 +37,7 @@ class Vidstream(val mainUrl: String) {
val extractorUrl = getExtractorUrl(id) val extractorUrl = getExtractorUrl(id)
argamap( argamap(
{ {
normalApis.apmap { api -> normalApis.amap { api ->
val url = api.getExtractorUrl(id) val url = api.getExtractorUrl(id)
api.getSafeUrl( api.getSafeUrl(
url, url,
@ -55,8 +55,8 @@ class Vidstream(val mainUrl: String) {
val qualityRegex = Regex("(\\d+)P") val qualityRegex = Regex("(\\d+)P")
//a[download] //a[download]
pageDoc.select(".dowload > a")?.apmap { element -> pageDoc.select(".dowload > a")?.amap { element ->
val href = element.attr("href") ?: return@apmap val href = element.attr("href") ?: return@amap
val qual = if (element.text() val qual = if (element.text()
.contains("HDP") .contains("HDP")
) "1080" else qualityRegex.find(element.text())?.destructured?.component1() ) "1080" else qualityRegex.find(element.text())?.destructured?.component1()
@ -87,7 +87,7 @@ class Vidstream(val mainUrl: String) {
//val name = element.text() //val name = element.text()
// Matches vidstream links with extractors // Matches vidstream links with extractors
extractorApis.filter { !it.requiresReferer || !isCasting }.apmap { api -> extractorApis.filter { !it.requiresReferer || !isCasting }.amap { api ->
if (link.startsWith(api.mainUrl)) { if (link.startsWith(api.mainUrl)) {
api.getSafeUrl(link, extractorUrl, subtitleCallback, callback) api.getSafeUrl(link, extractorUrl, subtitleCallback, callback)
} }

View File

@ -1,6 +1,6 @@
package com.lagradost.cloudstream3.extractors package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.amap
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
@ -36,7 +36,7 @@ open class ZplayerV2 : ExtractorApi() {
val m3u8regex = Regex("((https:|http:)\\/\\/.*\\.m3u8)") val m3u8regex = Regex("((https:|http:)\\/\\/.*\\.m3u8)")
m3u8regex.findAll(testdata).map { m3u8regex.findAll(testdata).map {
it.value it.value
}.toList().apmap { urlm3u8 -> }.toList().amap { urlm3u8 ->
if (urlm3u8.contains("m3u8")) { if (urlm3u8.contains("m3u8")) {
val testurl = app.get(urlm3u8, headers = mapOf("Referer" to url)).text val testurl = app.get(urlm3u8, headers = mapOf("Referer" to url)).text
if (testurl.contains("EXTM3U")) { if (testurl.contains("EXTM3U")) {

View File

@ -2,7 +2,7 @@ package com.lagradost.cloudstream3.extractors.helper
import android.util.Log import android.util.Log
import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.amap
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
@ -18,7 +18,7 @@ class AsianEmbedHelper {
val doc = app.get(url).document val doc = app.get(url).document
val links = doc.select("div#list-server-more > ul > li.linkserver") val links = doc.select("div#list-server-more > ul > li.linkserver")
if (!links.isNullOrEmpty()) { if (!links.isNullOrEmpty()) {
links.apmap { links.amap {
val datavid = it.attr("data-video") ?: "" val datavid = it.attr("data-video") ?: ""
//Log.i("AsianEmbed", "Result => (datavid) ${datavid}") //Log.i("AsianEmbed", "Result => (datavid) ${datavid}")
if (datavid.isNotBlank()) { if (datavid.isNotBlank()) {

View File

@ -39,7 +39,7 @@ class CrossTmdbProvider : TmdbProvider() {
): Boolean { ): Boolean {
tryParseJson<CrossMetaData>(data)?.let { metaData -> tryParseJson<CrossMetaData>(data)?.let { metaData ->
if (!metaData.isSuccess) return false if (!metaData.isSuccess) return false
metaData.movies?.apmap { (apiName, data) -> metaData.movies?.amap { (apiName, data) ->
getApiFromNameNull(apiName)?.let { getApiFromNameNull(apiName)?.let {
try { try {
it.loadLinks(data, isCasting, subtitleCallback, callback) it.loadLinks(data, isCasting, subtitleCallback, callback)
@ -64,10 +64,10 @@ class CrossTmdbProvider : TmdbProvider() {
val matchName = filterName(this.name) val matchName = filterName(this.name)
when (this) { when (this) {
is MovieLoadResponse -> { is MovieLoadResponse -> {
val data = validApis.apmap { api -> val data = validApis.amap { api ->
try { try {
if (api.supportedTypes.contains(TvType.Movie)) { //|| api.supportedTypes.contains(TvType.AnimeMovie) 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( if (filterName(it.name).equals(
matchName, matchName,
ignoreCase = true ignoreCase = true

View File

@ -45,7 +45,7 @@ class MultiAnimeProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
return syncApi.getResult(url)?.let { res -> 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) validApis.firstOrNull { api -> url.startsWith(api.mainUrl) }?.load(url)
}.filterNotNull() }.filterNotNull()

View File

@ -217,18 +217,17 @@ object PluginManager {
* 3. If outdated download and load the plugin * 3. If outdated download and load the plugin
* 4. Else load the plugin normally * 4. Else load the plugin normally
**/ **/
fun updateAllOnlinePluginsAndLoadThem(activity: Activity) { fun updateAllOnlinePluginsAndLoadThem(activity: Activity) = ioSafe {
// Load all plugins as fast as possible! // Load all plugins as fast as possible!
loadAllOnlinePlugins(activity) loadAllOnlinePlugins(activity)
ioSafe {
afterPluginsLoadedEvent.invoke(true) afterPluginsLoadedEvent.invoke(true)
}
val urls = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY) val urls = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY)
?: emptyArray()) + PREBUILT_REPOSITORIES ?: emptyArray()) + PREBUILT_REPOSITORIES
val onlinePlugins = urls.toList().apmap { val onlinePlugins = urls.toList().amap {
getRepoPlugins(it.url)?.toList() ?: emptyList() getRepoPlugins(it.url)?.toList() ?: emptyList()
}.flatten().distinctBy { it.second.url } }.flatten().distinctBy { it.second.url }
@ -249,7 +248,7 @@ object PluginManager {
val updatedPlugins = mutableListOf<String>() val updatedPlugins = mutableListOf<String>()
outdatedPlugins.apmap { pluginData -> outdatedPlugins.amap { pluginData ->
if (pluginData.isDisabled) { if (pluginData.isDisabled) {
//updatedPlugins.add(activity.getString(R.string.single_plugin_disabled, pluginData.onlineData.second.name)) //updatedPlugins.add(activity.getString(R.string.single_plugin_disabled, pluginData.onlineData.second.name))
unloadPlugin(pluginData.savedData.filePath) unloadPlugin(pluginData.savedData.filePath)
@ -270,9 +269,9 @@ object PluginManager {
createNotification(activity, updatedPlugins) createNotification(activity, updatedPlugins)
} }
ioSafe { // ioSafe {
afterPluginsLoadedEvent.invoke(true) afterPluginsLoadedEvent.invoke(true)
} // }
Log.i(TAG, "Plugin update done!") Log.i(TAG, "Plugin update done!")
} }
@ -280,9 +279,9 @@ object PluginManager {
/** /**
* Use updateAllOnlinePluginsAndLoadThem * Use updateAllOnlinePluginsAndLoadThem
* */ * */
fun loadAllOnlinePlugins(activity: Activity) { fun loadAllOnlinePlugins(activity: Activity) = ioSafe {
// Load all plugins as fast as possible! // Load all plugins as fast as possible!
(getPluginsOnline()).toList().apmap { pluginData -> (getPluginsOnline()).toList().amap { pluginData ->
loadPlugin( loadPlugin(
activity, activity,
File(pluginData.filePath), File(pluginData.filePath),
@ -291,7 +290,7 @@ object PluginManager {
} }
} }
fun loadAllLocalPlugins(activity: Activity) { fun loadAllLocalPlugins(activity: Activity) = ioSafe {
val dir = File(LOCAL_PLUGINS_PATH) val dir = File(LOCAL_PLUGINS_PATH)
removeKey(PLUGINS_KEY_LOCAL) removeKey(PLUGINS_KEY_LOCAL)
@ -299,7 +298,7 @@ object PluginManager {
val res = dir.mkdirs() val res = dir.mkdirs()
if (!res) { if (!res) {
Log.w(TAG, "Failed to create local directories") Log.w(TAG, "Failed to create local directories")
return return@ioSafe
} }
} }

View File

@ -4,7 +4,7 @@ import android.content.Context
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey 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.app
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
@ -95,7 +95,7 @@ object RepositoryManager {
* */ * */
suspend fun getRepoPlugins(repositoryUrl: String): List<Pair<String, SitePlugin>>? { suspend fun getRepoPlugins(repositoryUrl: String): List<Pair<String, SitePlugin>>? {
val repo = parseRepository(repositoryUrl) ?: return null val repo = parseRepository(repositoryUrl) ?: return null
return repo.pluginLists.apmap { url -> return repo.pluginLists.amap { url ->
parsePlugins(url).map { parsePlugins(url).map {
repositoryUrl to it repositoryUrl to it
} }

View File

@ -6,6 +6,10 @@ import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.utils.ExtractorLink 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 import kotlinx.coroutines.delay
class APIRepository(val api: MainAPI) { class APIRepository(val api: MainAPI) {
@ -27,7 +31,7 @@ class APIRepository(val api: MainAPI) {
return data.isEmpty() || data == "[]" || data == "about:blank" 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 val hasMainPage = api.hasMainPage
@ -42,7 +46,7 @@ class APIRepository(val api: MainAPI) {
return safeApiCall { return safeApiCall {
if (isInvalidData(url)) throw ErrorLoadingException() if (isInvalidData(url)) throw ErrorLoadingException()
val fixedUrl = api.fixUrl(url) val fixedUrl = api.fixUrl(url)
val key = Pair(api.name,url) val key = Pair(api.name, url)
cacheHash[key] ?: api.load(fixedUrl)?.also { 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 // 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()) if (cacheHash.size > 20) cacheHash.remove(cacheHash.keys.random())
@ -78,6 +82,7 @@ class APIRepository(val api: MainAPI) {
delay(delta) delay(delta)
} }
@OptIn(DelicateCoroutinesApi::class)
suspend fun getMainPage(page: Int, nameIndex: Int? = null): Resource<List<HomePageResponse?>> { suspend fun getMainPage(page: Int, nameIndex: Int? = null): Resource<List<HomePageResponse?>> {
return safeApiCall { return safeApiCall {
api.lastHomepageRequest = unixTimeMS api.lastHomepageRequest = unixTimeMS
@ -103,11 +108,15 @@ class APIRepository(val api: MainAPI) {
) )
} }
} else { } else {
api.mainPage.apmap { data -> with(CoroutineScope(coroutineContext)) {
api.getMainPage( api.mainPage.map { data ->
page, async {
MainPageRequest(data.name, data.data, data.horizontalImages) api.getMainPage(
) page,
MainPageRequest(data.name, data.data, data.horizontalImages)
)
}
}.map { it.await() }
} }
} }
} }

View File

@ -547,51 +547,14 @@ class HomeFragment : Fragment() {
when (preview) { when (preview) {
is Resource.Success -> { is Resource.Success -> {
home_preview?.isVisible = true home_preview?.isVisible = true
(home_preview_viewpager?.adapter as? HomeScrollAdapter)?.apply {
preview.value.apply { setItems(preview.value)
home_preview_tags?.text = tags?.joinToString("") ?: "" // home_preview_viewpager?.setCurrentItem(1000, false)
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()
}
}
} }
//.also {
//home_preview_viewpager?.adapter =
//}
} }
else -> { else -> {
home_preview?.isVisible = false home_preview?.isVisible = false
@ -606,6 +569,58 @@ class HomeFragment : Fragment() {
searchText.setTextColor(color) searchText.setTextColor(color)
searchText.setHintTextColor(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 -> observe(homeViewModel.apiName) { apiName ->
currentApiName = apiName currentApiName = apiName
// setKey(USER_SELECTED_HOMEPAGE_API, apiName) // setKey(USER_SELECTED_HOMEPAGE_API, apiName)

View File

@ -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`
}
}

View File

@ -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
)
}
}

View File

@ -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.noneApi
import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi
import com.lagradost.cloudstream3.ui.WatchType 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.DOWNLOAD_HEADER_CACHE
import com.lagradost.cloudstream3.utils.DataStoreHelper import com.lagradost.cloudstream3.utils.DataStoreHelper
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllResumeStateIds 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 com.lagradost.cloudstream3.utils.VideoDownloadHelper
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.* import java.util.*
import kotlin.collections.set import kotlin.collections.set
@ -58,9 +61,9 @@ class HomeViewModel : ViewModel() {
val bookmarks: LiveData<Pair<Boolean, List<SearchResponse>>> = _bookmarks val bookmarks: LiveData<Pair<Boolean, List<SearchResponse>>> = _bookmarks
private val _resumeWatching = MutableLiveData<List<SearchResponse>>() 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 resumeWatching: LiveData<List<SearchResponse>> = _resumeWatching
val preview: LiveData<Resource<LoadResponse>> = _preview val preview: LiveData<Resource<List<LoadResponse>>> = _preview
fun loadResumeWatching() = viewModelScope.launchSafe { fun loadResumeWatching() = viewModelScope.launchSafe {
val resumeWatching = withContext(Dispatchers.IO) { 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) { repo = if (api != null) {
APIRepository(api) APIRepository(api)
} else { } else {
@ -236,7 +239,35 @@ class HomeViewModel : ViewModel() {
ExpandableHomepageList(filteredList, 1, home.hasNext) ExpandableHomepageList(filteredList, 1, home.hasNext)
} }
} }
val items = data.value.mapNotNull { it?.items }.flatten() 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 -> items.randomOrNull()?.list?.randomOrNull()?.url?.let { url ->
// backup request in case first fails // backup request in case first fails
var first = repo?.load(url) var first = repo?.load(url)
@ -264,7 +295,7 @@ class HomeViewModel : ViewModel() {
"No homepage items" "No homepage items"
) )
) )
} }*/
_page.postValue(Resource.Success(expandable)) _page.postValue(Resource.Success(expandable))

View File

@ -344,7 +344,7 @@ class GeneratorPlayer : FullScreenPlayer() {
seasonNumber = currentTempMeta.season, seasonNumber = currentTempMeta.season,
lang = currentLanguageTwoLetters.ifBlank { null } lang = currentLanguageTwoLetters.ifBlank { null }
) )
val results = providers.apmap { val results = providers.amap {
try { try {
it.search(search) it.search(search)
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -1,6 +1,6 @@
package com.lagradost.cloudstream3.ui.player 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.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import java.net.URI import java.net.URI
@ -46,7 +46,7 @@ class LinkGenerator(
subtitleCallback: (SubtitleData) -> Unit, subtitleCallback: (SubtitleData) -> Unit,
offset: Int offset: Int
): Boolean { ): Boolean {
links.apmap { link -> links.amap { link ->
if (!extract || !loadExtractor(link, referer, { if (!extract || !loadExtractor(link, referer, {
subtitleCallback(PlayerSubtitleHelper.getSubtitleData(it)) subtitleCallback(PlayerSubtitleHelper.getSubtitleData(it))
}) { }) {

View File

@ -1972,7 +1972,7 @@ class ResultViewModel2 : ViewModel() {
): List<ExtractedTrailerData> = ): List<ExtractedTrailerData> =
coroutineScope { coroutineScope {
var currentCount = 0 var currentCount = 0
return@coroutineScope loadResponse.trailers.apmap { trailerData -> return@coroutineScope loadResponse.trailers.amap { trailerData ->
try { try {
val links = arrayListOf<ExtractorLink>() val links = arrayListOf<ExtractorLink>()
val subs = arrayListOf<SubtitleFile>() val subs = arrayListOf<SubtitleFile>()

View File

@ -4,7 +4,7 @@ import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel 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.Resource
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.SyncApis 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 /// modifies the current sync data, return null if you don't want to change it
private fun modifyData(update: ((SyncAPI.SyncStatus) -> (SyncAPI.SyncStatus?))) = private fun modifyData(update: ((SyncAPI.SyncStatus) -> (SyncAPI.SyncStatus?))) =
ioSafe { ioSafe {
syncs.apmap { (prefix, id) -> syncs.amap { (prefix, id) ->
repos.firstOrNull { it.idPrefix == prefix }?.let { repo -> repos.firstOrNull { it.idPrefix == prefix }?.let { repo ->
if (repo.hasAccount()) { if (repo.hasAccount()) {
val result = repo.getStatus(id) val result = repo.getStatus(id)

View File

@ -9,7 +9,7 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
import com.lagradost.cloudstream3.AcraApplication.Companion.getKeys import com.lagradost.cloudstream3.AcraApplication.Companion.getKeys
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
import com.lagradost.cloudstream3.SearchResponse 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.Resource
import com.lagradost.cloudstream3.mvvm.launchSafe import com.lagradost.cloudstream3.mvvm.launchSafe
import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.APIRepository
@ -108,9 +108,9 @@ class SearchViewModel : ViewModel() {
repos.filter { a -> repos.filter { a ->
(ignoreSettings || (providersActive.isEmpty() || providersActive.contains(a.name))) && (!isQuickSearch || a.hasQuickSearch) (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) 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)) currentList.add(OnGoingSearch(a.name, search))
_currentSearch.postValue(currentList) _currentSearch.postValue(currentList)
} }

View File

@ -6,7 +6,7 @@ import androidx.lifecycle.ViewModel
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
import com.lagradost.cloudstream3.R 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.Some
import com.lagradost.cloudstream3.mvvm.debugAssert import com.lagradost.cloudstream3.mvvm.debugAssert
import com.lagradost.cloudstream3.plugins.PluginManager import com.lagradost.cloudstream3.plugins.PluginManager
@ -49,7 +49,7 @@ class ExtensionsViewModel : ViewModel() {
val urls = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY) val urls = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY)
?: emptyArray()) + PREBUILT_REPOSITORIES ?: emptyArray()) + PREBUILT_REPOSITORIES
val onlinePlugins = urls.toList().apmap { val onlinePlugins = urls.toList().amap {
RepositoryManager.getRepoPlugins(it.url)?.toList() ?: emptyList() RepositoryManager.getRepoPlugins(it.url)?.toList() ?: emptyList()
}.flatten().distinctBy { it.second.url } }.flatten().distinctBy { it.second.url }

View File

@ -10,7 +10,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.CommonActivity.showToast
import com.lagradost.cloudstream3.R 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.mvvm.launchSafe
import com.lagradost.cloudstream3.plugins.PluginManager import com.lagradost.cloudstream3.plugins.PluginManager
import com.lagradost.cloudstream3.plugins.PluginManager.getPluginPath import com.lagradost.cloudstream3.plugins.PluginManager.getPluginPath
@ -101,7 +101,7 @@ class PluginsViewModel : ViewModel() {
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
) )
} }
}.apmap { (repo, metadata) -> }.amap { (repo, metadata) ->
PluginManager.downloadAndLoadPlugin( PluginManager.downloadAndLoadPlugin(
activity, activity,
metadata.url, metadata.url,

View File

@ -13,7 +13,6 @@ import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.CommonActivity.showToast
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.plugins.PLUGINS_KEY import com.lagradost.cloudstream3.plugins.PLUGINS_KEY
import com.lagradost.cloudstream3.plugins.PLUGINS_KEY_LOCAL 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_TOKEN_KEY
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_UNIXTIME_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.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.syncproviders.providers.OpenSubtitlesApi.Companion.OPEN_SUBTITLES_USER_KEY
import com.lagradost.cloudstream3.utils.DataStore.getDefaultSharedPrefs import com.lagradost.cloudstream3.utils.DataStore.getDefaultSharedPrefs
import com.lagradost.cloudstream3.utils.DataStore.getSharedPrefs import com.lagradost.cloudstream3.utils.DataStore.getSharedPrefs

View File

@ -279,30 +279,40 @@
<requestFocus /> <requestFocus />
</ImageView>--> </ImageView>-->
</FrameLayout> </FrameLayout>
<!--https://www.digitalocean.com/community/tutorials/android-viewpager-example-tutorial-->
<FrameLayout <FrameLayout
tools:visibility="visible"
android:visibility="gone"
android:id="@+id/home_preview" android:id="@+id/home_preview"
android:layout_width="match_parent" 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 <ImageView
android:alpha="0.8" android:visibility="gone"
android:id="@+id/home_preview_image" android:id="@+id/home_preview_image"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:alpha="0.8"
android:scaleType="centerCrop" android:scaleType="centerCrop"
tools:src="@drawable/example_poster" /> tools:src="@drawable/example_poster" />
<View <View
android:visibility="visible"
android:id="@+id/title_shadow_top" android:id="@+id/title_shadow_top"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="150dp" android:layout_height="150dp"
android:alpha="1"
android:rotation="180"
android:layout_gravity="top" android:layout_gravity="top"
android:background="@drawable/background_shadow" /> android:alpha="1"
android:background="@drawable/background_shadow"
android:rotation="180"
android:visibility="visible" />
<View <View
android:id="@+id/title_shadow" android:id="@+id/title_shadow"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -312,62 +322,63 @@
<LinearLayout <LinearLayout
android:id="@+id/home_padding" android:id="@+id/home_padding"
android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.SearchView <androidx.appcompat.widget.SearchView
android:id="@+id/home_search" android:id="@+id/home_search"
android:layout_width="match_parent" android:layout_width="match_parent"
android:gravity="start"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start" android:layout_gravity="start"
android:editTextColor="@color/white"
android:gravity="start"
android:iconifiedByDefault="true" android:iconifiedByDefault="true"
android:textColor="@color/white"
android:textColorHint="@color/white"
app:iconifiedByDefault="true" app:iconifiedByDefault="true"
app:queryBackground="@color/transparent" app:queryBackground="@color/transparent"
app:queryHint="@string/search" app:queryHint="@string/search"
android:textColor="@color/white"
android:textColorHint="@color/white"
android:editTextColor="@color/white"
app:searchIcon="@drawable/search_icon" app:searchIcon="@drawable/search_icon"
tools:ignore="RtlSymmetry" /> tools:ignore="RtlSymmetry" />
</LinearLayout> </LinearLayout>
<!-- <!--
<TextView <TextView
android:visibility="gone" android:visibility="gone"
android:id="@+id/test_search" android:id="@+id/test_search"
android:background="?android:attr/selectableItemBackgroundBorderless" android:background="?android:attr/selectableItemBackgroundBorderless"
android:layout_gravity="start" android:layout_gravity="start"
android:gravity="center" android:gravity="center"
android:textSize="20dp" android:textSize="20dp"
android:layout_margin="20dp" android:layout_margin="20dp"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/search" android:text="@string/search"
android:textColor="@color/white" android:textColor="@color/white"
app:drawableLeftCompat="@drawable/search_icon" app:drawableLeftCompat="@drawable/search_icon"
app:tint="@color/white" /> app:tint="@color/white" />
--> -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:paddingStart="30dp"
android:paddingEnd="30dp"
android:textStyle="bold"
android:paddingBottom="10dp"
android:id="@+id/home_preview_title" android:id="@+id/home_preview_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:paddingStart="30dp"
android:paddingEnd="30dp"
android:paddingBottom="10dp"
android:textColor="?attr/white" android:textColor="?attr/white"
android:textSize="17sp" android:textSize="17sp"
android:textStyle="bold"
tools:text="The Perfect Run" /> tools:text="The Perfect Run" />
<!--<TextView <!--<TextView
android:paddingStart="30dp" android:paddingStart="30dp"
@ -380,60 +391,62 @@
android:textSize="14sp" android:textSize="14sp"
tools:text="5 seasons 50 episodes" />--> tools:text="5 seasons 50 episodes" />-->
<TextView <TextView
android:paddingStart="30dp"
android:paddingEnd="30dp"
android:id="@+id/home_preview_tags" android:id="@+id/home_preview_tags"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:paddingStart="30dp"
android:paddingEnd="30dp"
android:textColor="?attr/white" android:textColor="?attr/white"
android:textSize="14sp" android:textSize="14sp"
tools:text="Hello • World • Tags" /> tools:text="Hello • World • Tags" />
<LinearLayout <LinearLayout
android:padding="20dp"
android:gravity="center"
android:layout_gravity="center"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal"
android:padding="20dp">
<TextView <TextView
android:id="@+id/home_preview_bookmark" 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_width="70dp"
android:layout_height="wrap_content" 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:text="@string/none"
android:textColor="?attr/white" android:textColor="?attr/white"
app:drawableTint="?attr/white"
app:drawableTopCompat="@drawable/ic_baseline_add_24" app:drawableTopCompat="@drawable/ic_baseline_add_24"
app:tint="?attr/white" app:tint="?attr/white" />
app:drawableTint="?attr/white" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:layout_gravity="center"
style="@style/WhiteButton"
android:id="@+id/home_preview_play" android:id="@+id/home_preview_play"
style="@style/WhiteButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_gravity="center"
android:text="@string/home_play" android:text="@string/home_play"
app:icon="@drawable/ic_baseline_play_arrow_24" /> app:icon="@drawable/ic_baseline_play_arrow_24" />
<TextView <TextView
android:background="?android:attr/selectableItemBackgroundBorderless"
android:id="@+id/home_preview_info" android:id="@+id/home_preview_info"
android:gravity="center" android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginStart="25dp" android:layout_marginStart="25dp"
android:layout_marginEnd="25dp" android:layout_marginEnd="25dp"
android:layout_width="70dp" android:background="?android:attr/selectableItemBackgroundBorderless"
android:layout_height="wrap_content" android:gravity="center"
android:text="@string/home_info" android:text="@string/home_info"
android:textColor="?attr/white" android:textColor="?attr/white"
app:drawableTint="?attr/white"
app:drawableTopCompat="@drawable/ic_outline_info_24" app:drawableTopCompat="@drawable/ic_outline_info_24"
app:tint="?attr/white" app:tint="?attr/white" />
app:drawableTint="?attr/white" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</FrameLayout> </FrameLayout>
@ -522,15 +535,15 @@
<com.google.android.material.chip.ChipGroup <com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content" android:layout_width="wrap_content"
app:singleSelection="true"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal"
app:singleSelection="true">
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/home_type_watching_btt" android:id="@+id/home_type_watching_btt"
style="@style/ChipFilled" style="@style/ChipFilled"
android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/nav_rail_view" android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusRight="@id/home_plan_to_watch_btt" android:nextFocusRight="@id/home_plan_to_watch_btt"
@ -539,8 +552,8 @@
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/home_plan_to_watch_btt" android:id="@+id/home_plan_to_watch_btt"
style="@style/ChipFilled" style="@style/ChipFilled"
android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_watching_btt" android:nextFocusLeft="@id/home_type_watching_btt"
android:nextFocusRight="@id/home_type_on_hold_btt" android:nextFocusRight="@id/home_type_on_hold_btt"
@ -549,8 +562,8 @@
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/home_type_on_hold_btt" android:id="@+id/home_type_on_hold_btt"
style="@style/ChipFilled" style="@style/ChipFilled"
android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_plan_to_watch_btt" android:nextFocusLeft="@id/home_plan_to_watch_btt"
android:nextFocusRight="@id/home_type_dropped_btt" android:nextFocusRight="@id/home_type_dropped_btt"
@ -559,8 +572,8 @@
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/home_type_dropped_btt" android:id="@+id/home_type_dropped_btt"
style="@style/ChipFilled" style="@style/ChipFilled"
android:layout_height="wrap_content"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_on_hold_btt" android:nextFocusLeft="@id/home_type_on_hold_btt"
android:nextFocusRight="@id/home_type_completed_btt" android:nextFocusRight="@id/home_type_completed_btt"
@ -568,10 +581,10 @@
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/home_type_completed_btt" android:id="@+id/home_type_completed_btt"
android:layout_height="wrap_content" style="@style/ChipFilled"
android:layout_width="wrap_content" android:layout_width="wrap_content"
style="@style/ChipFilled" android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_dropped_btt" android:nextFocusLeft="@id/home_type_dropped_btt"
android:text="@string/type_completed" /> android:text="@string/type_completed" />
</com.google.android.material.chip.ChipGroup> </com.google.android.material.chip.ChipGroup>

View File

@ -162,7 +162,7 @@ class ProviderTests {
// @Test // @Test
// fun providerCorrectHomepage() { // fun providerCorrectHomepage() {
// runBlocking { // runBlocking {
// getAllProviders().apmap { api -> // getAllProviders().amap { api ->
// if (api.hasMainPage) { // if (api.hasMainPage) {
// try { // try {
// val homepage = api.getMainPage() // val homepage = api.getMainPage()
@ -197,7 +197,7 @@ class ProviderTests {
// suspend fun providerCorrect() { // suspend fun providerCorrect() {
// val invalidProvider = ArrayList<Pair<MainAPI, Exception?>>() // val invalidProvider = ArrayList<Pair<MainAPI, Exception?>>()
// val providers = getAllProviders() // val providers = getAllProviders()
// providers.apmap { api -> // providers.amap { api ->
// try { // try {
// println("Trying $api") // println("Trying $api")
// if (testSingleProviderApi(api)) { // if (testSingleProviderApi(api)) {