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
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)) {

View File

@ -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(

View File

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

View File

@ -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,

View File

@ -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,

View File

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

View File

@ -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://"

View File

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

View File

@ -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")) {

View File

@ -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()) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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.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))

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

@ -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,

View File

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

View File

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

View File

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