homepage loading error catch

This commit is contained in:
LagradOst 2021-07-29 17:16:08 +02:00
parent 3bbcdfef1f
commit 522e53eca6
10 changed files with 306 additions and 126 deletions

View file

@ -91,18 +91,18 @@ object UIHelper {
return color return color
} }
fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String) { fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String, startAction: Int = 0) {
this.runOnUiThread { this.runOnUiThread {
viewModelStore.clear() viewModelStore.clear()
this.supportFragmentManager.beginTransaction() this.supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit) .setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
.add(R.id.homeRoot, ResultFragment.newInstance(url, slug, apiName)) .add(R.id.homeRoot, ResultFragment.newInstance(url, slug, apiName, startAction))
.commit() .commit()
} }
} }
fun Activity?.loadSearchResult(card : SearchResponse) { fun Activity?.loadSearchResult(card: SearchResponse, startAction: Int = 0) {
(this as AppCompatActivity?)?.loadResult(card.url, card.slug, card.apiName) (this as AppCompatActivity?)?.loadResult(card.url, card.slug, card.apiName, startAction)
} }
fun Context.getStatusBarHeight(): Int { fun Context.getStatusBarHeight(): Int {

View file

@ -1,7 +1,9 @@
package com.lagradost.cloudstream3.ui.home package com.lagradost.cloudstream3.ui.home
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent
import android.content.res.Configuration import android.content.res.Configuration
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -15,6 +17,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.GlideUrl
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.AnimeSearchResponse import com.lagradost.cloudstream3.AnimeSearchResponse
import com.lagradost.cloudstream3.HomePageResponse import com.lagradost.cloudstream3.HomePageResponse
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
@ -22,9 +25,11 @@ import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.UIHelper.getGridIsCompact import com.lagradost.cloudstream3.UIHelper.getGridIsCompact
import com.lagradost.cloudstream3.UIHelper.loadSearchResult import com.lagradost.cloudstream3.UIHelper.loadSearchResult
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIconsAndNoStringRes
import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.ui.AutofitRecyclerView import com.lagradost.cloudstream3.ui.AutofitRecyclerView
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
import com.lagradost.cloudstream3.ui.search.SearchAdapter import com.lagradost.cloudstream3.ui.search.SearchAdapter
import com.lagradost.cloudstream3.utils.DataStore.getKey import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.setKey import com.lagradost.cloudstream3.utils.DataStore.setKey
@ -78,7 +83,7 @@ class HomeFragment : Fragment() {
activity.loadSearchResult(random) activity.loadSearchResult(random)
} }
home_main_play.setOnClickListener { home_main_play.setOnClickListener {
activity.loadSearchResult(random) activity.loadSearchResult(random, START_ACTION_RESUME_LATEST)
} }
home_main_info.setOnClickListener { home_main_info.setOnClickListener {
activity.loadSearchResult(random) activity.loadSearchResult(random)
@ -124,6 +129,14 @@ class HomeFragment : Fragment() {
configEvent.invoke(currentSpan) configEvent.invoke(currentSpan)
} }
private val apiChangeClickListener = View.OnClickListener { view ->
val validAPIs = apis.filter { api -> api.hasMainPage }
view.popupMenuNoIconsAndNoStringRes(validAPIs.mapIndexed { index, api -> Pair(index, api.name) }) {
homeViewModel.load(validAPIs[itemId])
}
}
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)
fixGrid() fixGrid()
@ -157,14 +170,16 @@ class HomeFragment : Fragment() {
chooseRandomMainPage(currentMainList[currentMainIndex]) chooseRandomMainPage(currentMainList[currentMainIndex])
} }
home_change_api.setOnClickListener(apiChangeClickListener)
observe(homeViewModel.apiName) { observe(homeViewModel.apiName) {
context?.setKey(HOMEPAGE_API, it) context?.setKey(HOMEPAGE_API, it)
} }
observe(homeViewModel.page) { observe(homeViewModel.page) { data ->
when (it) { when (data) {
is Resource.Success -> { is Resource.Success -> {
val d = it.value val d = data.value
currentHomePage = d currentHomePage = d
(home_master_recycler?.adapter as ParentItemAdapter?)?.items = d.items (home_master_recycler?.adapter as ParentItemAdapter?)?.items = d.items
home_master_recycler?.adapter?.notifyDataSetChanged() home_master_recycler?.adapter?.notifyDataSetChanged()
@ -173,12 +188,39 @@ class HomeFragment : Fragment() {
currentMainList.add(response) currentMainList.add(response)
} }
currentMainIndex = 0 currentMainIndex = 0
home_loading.visibility = View.GONE
home_loading_error.visibility = View.GONE
home_loaded.visibility = View.VISIBLE
} }
is Resource.Failure -> { is Resource.Failure -> {
result_error_text.text = data.errorString
home_reload_connectionerror.setOnClickListener(apiChangeClickListener)
home_reload_connection_open_in_browser.setOnClickListener { view ->
val validAPIs = apis//.filter { api -> api.hasMainPage }
view.popupMenuNoIconsAndNoStringRes(validAPIs.mapIndexed { index, api ->
Pair(
index,
api.name
)
}) {
val i = Intent(Intent.ACTION_VIEW)
i.data = Uri.parse(validAPIs[itemId].mainUrl)
startActivity(i)
}
}
home_loading.visibility = View.GONE
home_loading_error.visibility = View.VISIBLE
home_loaded.visibility = View.GONE
} }
is Resource.Loading -> { is Resource.Loading -> {
home_loading.visibility = View.VISIBLE
home_loading_error.visibility = View.GONE
home_loaded.visibility = View.GONE
} }
} }
} }
@ -226,6 +268,6 @@ class HomeFragment : Fragment() {
home_master_recycler.adapter = adapter home_master_recycler.adapter = adapter
home_master_recycler.layoutManager = GridLayoutManager(context, 1) home_master_recycler.layoutManager = GridLayoutManager(context, 1)
homeViewModel.load(context?.getKey(HOMEPAGE_API)) homeViewModel.load(context?.getKey<String>(HOMEPAGE_API))
} }
} }

View file

@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope
import com.lagradost.cloudstream3.APIHolder.apis import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
import com.lagradost.cloudstream3.HomePageResponse import com.lagradost.cloudstream3.HomePageResponse
import com.lagradost.cloudstream3.MainAPI
import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.APIRepository
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -24,8 +25,7 @@ class HomeViewModel : ViewModel() {
return APIRepository(apis.first { it.hasMainPage }) return APIRepository(apis.first { it.hasMainPage })
} }
fun load(preferredApiName: String?) = viewModelScope.launch { fun load(api : MainAPI?) = viewModelScope.launch {
val api = getApiFromNameNull(preferredApiName)
repo = if (api?.hasMainPage == true) { repo = if (api?.hasMainPage == true) {
APIRepository(api) APIRepository(api)
} else { } else {
@ -34,4 +34,9 @@ class HomeViewModel : ViewModel() {
_page.postValue(Resource.Loading()) _page.postValue(Resource.Loading())
_page.postValue(repo?.getMainPage()) _page.postValue(repo?.getMainPage())
} }
fun load(preferredApiName: String?) = viewModelScope.launch {
val api = getApiFromNameNull(preferredApiName)
load(api)
}
} }

View file

@ -142,10 +142,11 @@ class EpisodeAdapter(
val name = if (card.name == null) "Episode ${card.episode}" else "${card.episode}. ${card.name}" val name = if (card.name == null) "Episode ${card.episode}" else "${card.episode}. ${card.name}"
episodeText.text = name episodeText.text = name
val watchProgress = card.getWatchProgress() val displayPos = card.getDisplayPosition()
episodeProgress?.max = (card.duration / 1000).toInt()
episodeProgress?.progress = (displayPos / 1000).toInt()
episodeProgress?.progress = (watchProgress * 50).toInt() episodeProgress?.visibility = if (displayPos > 0L) View.VISIBLE else View.GONE
episodeProgress?.visibility = if (watchProgress > 0.0f) View.VISIBLE else View.GONE
if (card.poster != null) { if (card.poster != null) {
episodePoster?.visibility = View.VISIBLE episodePoster?.visibility = View.VISIBLE

View file

@ -73,6 +73,9 @@ import kotlin.collections.HashMap
const val MAX_SYNO_LENGH = 300 const val MAX_SYNO_LENGH = 300
const val START_ACTION_NORMAL = 0
const val START_ACTION_RESUME_LATEST = 1
data class ResultEpisode( data class ResultEpisode(
val name: String?, val name: String?,
val poster: String?, val poster: String?,
@ -133,18 +136,20 @@ fun Context.buildResultEpisode(
) )
} }
/** 0f-1f */
fun ResultEpisode.getWatchProgress(): Float { fun ResultEpisode.getWatchProgress(): Float {
return getDisplayPosition().toFloat() / duration return (getDisplayPosition() / 1000).toFloat() / (duration / 1000).toFloat()
} }
class ResultFragment : Fragment() { class ResultFragment : Fragment() {
companion object { companion object {
fun newInstance(url: String, slug: String, apiName: String) = fun newInstance(url: String, slug: String, apiName: String, startAction: Int = 0) =
ResultFragment().apply { ResultFragment().apply {
arguments = Bundle().apply { arguments = Bundle().apply {
putString("url", url) putString("url", url)
putString("slug", slug) putString("slug", slug)
putString("apiName", apiName) putString("apiName", apiName)
putInt("startAction", startAction)
} }
} }
} }
@ -156,7 +161,7 @@ class ResultFragment : Fragment() {
private var currentHeaderName: String? = null private var currentHeaderName: String? = null
private var currentType: TvType? = null private var currentType: TvType? = null
private var currentEpisodes: List<ResultEpisode>? = null private var currentEpisodes: List<ResultEpisode>? = null
var downloadButton : EasyDownloadButton? = null var downloadButton: EasyDownloadButton? = null
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -229,6 +234,8 @@ class ResultFragment : Fragment() {
} }
} }
var startAction: Int? = null
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -252,6 +259,7 @@ class ResultFragment : Fragment() {
url = arguments?.getString("url") url = arguments?.getString("url")
val slug = arguments?.getString("slug") val slug = arguments?.getString("slug")
val apiName = arguments?.getString("apiName") ?: return val apiName = arguments?.getString("apiName") ?: return
startAction = arguments?.getInt("startAction") ?: START_ACTION_NORMAL
val api = getApiFromName(apiName) val api = getApiFromName(apiName)
if (media_route_button != null) { if (media_route_button != null) {
@ -459,6 +467,7 @@ class ResultFragment : Fragment() {
val isLoaded = when (episodeClick.action) { val isLoaded = when (episodeClick.action) {
ACTION_PLAY_EPISODE_IN_PLAYER -> true ACTION_PLAY_EPISODE_IN_PLAYER -> true
ACTION_CLICK_DEFAULT -> true
ACTION_CHROME_CAST_EPISODE -> requireLinks(true) ACTION_CHROME_CAST_EPISODE -> requireLinks(true)
ACTION_CHROME_CAST_MIRROR -> requireLinks(true) ACTION_CHROME_CAST_MIRROR -> requireLinks(true)
else -> requireLinks(false) else -> requireLinks(false)
@ -673,6 +682,23 @@ class ResultFragment : Fragment() {
result_bookmark_button.text = getString(it.stringRes) result_bookmark_button.text = getString(it.stringRes)
} }
observe(viewModel.episodes) { episodeList ->
when (startAction) {
START_ACTION_RESUME_LATEST -> {
for (ep in episodeList) {
if (ep.getWatchProgress() > 0.90f) { // watched too much
continue
}
handleAction(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, ep))
startAction = null
break
}
}
else -> {
}
}
}
observe(viewModel.allEpisodes) { observe(viewModel.allEpisodes) {
allEpisodes = it allEpisodes = it
} }

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,5.69l5,4.5V18h-2v-6H9v6H7v-7.81l5,-4.5M12,3L2,12h3v8h6v-6h2v6h6v-8h3L12,3z"/>
</vector>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
@ -8,18 +8,107 @@
android:id="@+id/home_root" android:id="@+id/home_root"
tools:context=".ui.home.HomeFragment"> tools:context=".ui.home.HomeFragment">
<ProgressBar
android:visibility="visible"
tools:visibility="gone"
android:id="@+id/home_loading"
android:layout_gravity="center"
android:layout_width="50dp"
android:layout_height="50dp">
</ProgressBar>
<LinearLayout
tools:visibility="gone"
android:id="@+id/home_loading_error"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:layout_gravity="center"
android:layout_height="50dp"
android:layout_margin="5dp"
android:visibility="visible"
android:textStyle="bold"
app:rippleColor="?attr/grayBackground"
android:textColor="?attr/grayBackground"
app:iconTint="?attr/grayBackground"
android:textAllCaps="false"
app:iconGravity="textStart"
app:strokeColor="?attr/grayBackground"
app:backgroundTint="?attr/textColor"
app:icon="@drawable/ic_baseline_autorenew_24"
app:iconSize="20dp"
android:text="@string/reload_error"
android:id="@+id/home_reload_connectionerror"
android:textSize="15sp"
app:cornerRadius="5dp"
android:layout_width="wrap_content"
android:minWidth="200dp"
>
</com.google.android.material.button.MaterialButton>
<com.google.android.material.button.MaterialButton
android:layout_gravity="center"
android:layout_height="50dp"
android:layout_margin="5dp"
app:iconGravity="textStart"
app:strokeColor="?attr/textColor"
android:backgroundTint="?attr/grayBackground"
app:rippleColor="?attr/textColor"
android:textColor="?attr/textColor"
app:iconTint="?attr/textColor"
android:textAllCaps="false"
android:textStyle="bold"
app:icon="@drawable/ic_baseline_public_24"
app:iconSize="20dp"
android:text="@string/result_open_in_browser"
android:id="@+id/home_reload_connection_open_in_browser"
android:textSize="15sp"
app:cornerRadius="5dp"
android:layout_width="wrap_content"
android:minWidth="200dp"
>
</com.google.android.material.button.MaterialButton>
<TextView
android:layout_margin="5dp"
android:gravity="center"
android:layout_gravity="center"
android:id="@+id/result_error_text"
android:textColor="?attr/textColor"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/home_loaded"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<ImageView
android:id="@+id/home_change_api"
android:layout_margin="10dp"
android:layout_gravity="end"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_outline_settings_24"
android:layout_width="25dp"
android:layout_height="25dp"
android:contentDescription="@string/home_change_provider">
</ImageView>
<LinearLayout <LinearLayout
android:layout_marginTop="-20dp"
android:id="@+id/home_main_holder" android:id="@+id/home_main_holder"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<ImageView <ImageView
android:layout_marginTop="10dp"
android:foreground="?android:attr/selectableItemBackgroundBorderless" android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:id="@+id/home_main_poster" android:id="@+id/home_main_poster"
tools:src="@drawable/example_poster" tools:src="@drawable/example_poster"
@ -120,5 +209,6 @@
tools:listitem="@layout/homepage_parent" tools:listitem="@layout/homepage_parent"
/> />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.core.widget.NestedScrollView> </FrameLayout>

View file

@ -18,6 +18,7 @@
android:layout_width="50dp" android:layout_height="50dp"> android:layout_width="50dp" android:layout_height="50dp">
</ProgressBar> </ProgressBar>
<LinearLayout <LinearLayout
tools:visibility="gone"
android:id="@+id/result_loading_error" android:id="@+id/result_loading_error"
android:orientation="vertical" android:orientation="vertical"
android:layout_gravity="center" android:layout_gravity="center"
@ -28,17 +29,22 @@
android:layout_height="50dp" android:layout_height="50dp"
android:layout_margin="5dp" android:layout_margin="5dp"
android:visibility="visible"
android:textStyle="bold"
app:rippleColor="?attr/grayBackground"
android:textColor="?attr/grayBackground"
app:iconTint="?attr/grayBackground"
android:textAllCaps="false"
app:iconGravity="textStart"
app:strokeColor="?attr/grayBackground"
app:backgroundTint="?attr/textColor"
app:icon="@drawable/ic_baseline_autorenew_24" app:icon="@drawable/ic_baseline_autorenew_24"
app:iconSize="20dp" app:iconSize="20dp"
android:text="@string/reload_error" android:text="@string/reload_error"
android:id="@+id/result_reload_connectionerror" android:id="@+id/result_reload_connectionerror"
android:textAllCaps="false"
android:textSize="15sp" android:textSize="15sp"
app:cornerRadius="5dp" app:cornerRadius="5dp"
app:strokeWidth="2dp"
app:strokeColor="@color/colorAccent"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
app:rippleColor="@color/colorPrimary"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:minWidth="200dp" android:minWidth="200dp"
> >
@ -48,17 +54,21 @@
android:layout_height="50dp" android:layout_height="50dp"
android:layout_margin="5dp" android:layout_margin="5dp"
app:iconGravity="textStart"
app:strokeColor="?attr/textColor"
android:backgroundTint="?attr/grayBackground"
app:rippleColor="?attr/textColor"
android:textColor="?attr/textColor"
app:iconTint="?attr/textColor"
android:textAllCaps="false"
android:textStyle="bold"
app:icon="@drawable/ic_baseline_public_24" app:icon="@drawable/ic_baseline_public_24"
app:iconSize="20dp" app:iconSize="20dp"
android:text="@string/result_open_in_browser" android:text="@string/result_open_in_browser"
android:id="@+id/result_reload_connection_open_in_browser" android:id="@+id/result_reload_connection_open_in_browser"
android:textAllCaps="false"
android:textSize="15sp" android:textSize="15sp"
app:cornerRadius="5dp" app:cornerRadius="5dp"
app:strokeWidth="2dp"
app:strokeColor="@color/colorAccent"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
app:rippleColor="@color/colorPrimary"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:minWidth="200dp" android:minWidth="200dp"
> >
@ -68,7 +78,7 @@
android:gravity="center" android:gravity="center"
android:layout_gravity="center" android:layout_gravity="center"
android:id="@+id/result_error_text" android:id="@+id/result_error_text"
android:textColor="?attr/colorPrimary" android:textColor="?attr/textColor"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
</TextView> </TextView>

View file

@ -3,7 +3,7 @@
<item <item
android:id="@+id/navigation_home" android:id="@+id/navigation_home"
android:icon="@drawable/ic_home_black_24dp" android:icon="@drawable/ic_outline_home_24"
android:title="@string/title_home"/> android:title="@string/title_home"/>
<item <item
android:id="@+id/navigation_search" android:id="@+id/navigation_search"

View file

@ -60,4 +60,5 @@
<string name="home_play">Play</string> <string name="home_play">Play</string>
<string name="home_info">Info</string> <string name="home_info">Info</string>
<string name="home_next_random">Next Random</string> <string name="home_next_random">Next Random</string>
<string name="home_change_provider">Change Provider</string>
</resources> </resources>