diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt index 5616a70e..5712b118 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt @@ -19,7 +19,6 @@ import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.malApi import com.lagradost.cloudstream3.ui.player.SubtitleData import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink -import okhttp3.Headers import okhttp3.Interceptor import java.text.SimpleDateFormat import java.util.* @@ -530,9 +529,9 @@ enum class ShowStatus { Ongoing, } -enum class DubStatus { - Dubbed, - Subbed, +enum class DubStatus(val id: Int) { + Dubbed(1), + Subbed(0), } enum class TvType { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index e3cdb12f..c4ea5689 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -101,6 +101,21 @@ class HomeFragment : Fragment() { var currentSpan = 1 val listHomepageItems = mutableListOf() + private val errorProfilePics = listOf( + R.drawable.monke_benene, + R.drawable.monke_burrito, + R.drawable.monke_coco, + R.drawable.monke_cookie, + R.drawable.monke_flusdered, + R.drawable.monke_funny, + R.drawable.monke_like, + R.drawable.monke_party, + R.drawable.monke_sob, + R.drawable.monke_drink, + ) + + val errorProfilePic = errorProfilePics.random() + fun Activity.loadHomepageList(item: HomePageList) { val context = this val bottomSheetDialogBuilder = BottomSheetDialog(context) @@ -865,7 +880,7 @@ class HomeFragment : Fragment() { for (syncApi in OAuth2API.OAuth2Apis) { val login = syncApi.loginInfo() val pic = login?.profilePicture - if (home_profile_picture?.setImage(pic) == true) { + if (home_profile_picture?.setImage(pic, errorImageDrawable = errorProfilePic) == true) { home_profile_picture_holder?.isVisible = true break } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt index 86d5a865..edafc6da 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt @@ -145,17 +145,17 @@ fun ResultEpisode.getDisplayPosition(): Long { fun buildResultEpisode( headerName: String, - name: String?, - poster: String?, + name: String? = null, + poster: String? = null, episode: Int, - season: Int?, + season: Int? = null, data: String, apiName: String, id: Int, index: Int, - rating: Int?, - description: String?, - isFiller: Boolean?, + rating: Int? = null, + description: String? = null, + isFiller: Boolean? = null, tvType: TvType, parentId: Int, ): ResultEpisode { @@ -1478,6 +1478,7 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio when (startAction) { START_ACTION_RESUME_LATEST -> { for (ep in episodeList) { + println("WATCH STATUS::: S${ep.season} E ${ep.episode} - ${ep.getWatchProgress()}") if (ep.getWatchProgress() > 0.90f) { // watched too much continue } @@ -1488,6 +1489,7 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio START_ACTION_LOAD_EP -> { for (ep in episodeList) { if (ep.id == startValue) { // watched too much + println("WATCH STATUS::: START_ACTION_LOAD_EP S${ep.season} E ${ep.episode} - ${ep.getWatchProgress()}") handleAction(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, ep)) break } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt index 08a20eb3..84aab52f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt @@ -389,33 +389,35 @@ class ResultViewModel : ViewModel() { val fillerEpisodes = if (showFillers) safeApiCall { getFillerEpisodes(d.name) } else null - var idIndex = 0 + val existingEpisodes = HashSet() val res = d.episodes.map { ep -> val episodes = ArrayList() + val idIndex = ep.key.id for ((index, i) in ep.value.withIndex()) { - val episode = i.episode ?: (index + 1) - episodes.add(buildResultEpisode( - d.name, - filterName(i.name), - i.posterUrl, - episode, - i.season, - i.data, - apiName, - mainId + index + 1 + idIndex * 100000, - index, - i.rating, - i.description, - if (fillerEpisodes is Resource.Success) fillerEpisodes.value?.let { - it.contains(episode) && it[episode] == true - } ?: false else false, - d.type, - mainId - )) + val id = mainId + episode + idIndex * 1000000 + if (!existingEpisodes.contains(episode)) { + existingEpisodes.add(id) + episodes.add(buildResultEpisode( + d.name, + filterName(i.name), + i.posterUrl, + episode, + i.season, + i.data, + apiName, + id, + index, + i.rating, + i.description, + if (fillerEpisodes is Resource.Success) fillerEpisodes.value?.let { + it.contains(episode) && it[episode] == true + } ?: false else false, + d.type, + mainId + )) + } } - idIndex++ - episodes.sortBy { it.episode } Pair(ep.key, episodes) }.toMap() @@ -431,27 +433,33 @@ class ResultViewModel : ViewModel() { is TvSeriesLoadResponse -> { val episodes = ArrayList() - for ((index, i) in d.episodes.withIndex()) { - episodes.add( - buildResultEpisode( - d.name, - filterName(i.name), - i.posterUrl, - i.episode ?: (index + 1), - i.season, - i.data, - apiName, - (mainId + index + 1).hashCode(), - index, - i.rating, - i.description, - null, - d.type, - mainId + val existingEpisodes = HashSet() + for ((index, i) in d.episodes.sortedBy { + (it.season?.times(10000) ?: 0) + (it.episode ?: 0) + }.withIndex()) { + val id = mainId + (i.season?.times(100000) ?: 0) + (i.episode ?: 0) + 1 + if (!existingEpisodes.contains(id)) { + existingEpisodes.add(id) + episodes.add( + buildResultEpisode( + d.name, + filterName(i.name), + i.posterUrl, + i.episode ?: (index + 1), + i.season, + i.data, + apiName, + id, + index, + i.rating, + i.description, + null, + d.type, + mainId + ) ) - ) + } } - episodes.sortBy { (it.season?.times(10000) ?: 0) + it.episode } updateEpisodes(mainId, episodes, -1) } is MovieLoadResponse -> { diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt index 2fd0aa17..1d5488db 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt @@ -14,7 +14,7 @@ import com.lagradost.cloudstream3.ui.WatchType const val VIDEO_POS_DUR = "video_pos_dur" const val RESULT_WATCH_STATE = "result_watch_state" const val RESULT_WATCH_STATE_DATA = "result_watch_state_data" -const val RESULT_RESUME_WATCHING = "result_resume_watching" +const val RESULT_RESUME_WATCHING = "result_resume_watching_2" // changed due to id changes const val RESULT_SEASON = "result_season" const val RESULT_DUB = "result_dub" diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt index 90c8d3f5..50e1a7a7 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt @@ -19,6 +19,7 @@ import android.widget.ListAdapter import android.widget.ListView import androidx.annotation.AttrRes import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes import androidx.annotation.IdRes import androidx.appcompat.view.ContextThemeWrapper import androidx.appcompat.view.menu.MenuBuilder @@ -148,14 +149,24 @@ object UIHelper { return color } - fun ImageView?.setImage(url: String?, headers: Map? = null): Boolean { + fun ImageView?.setImage( + url: String?, + headers: Map? = null, + @DrawableRes + errorImageDrawable: Int? = null + ): Boolean { if (this == null || url.isNullOrBlank()) return false return try { - GlideApp.with(this.context) + val builder = GlideApp.with(this.context) .load(GlideUrl(url) { headers ?: emptyMap() }).transition( DrawableTransitionOptions.withCrossFade() ) - .into(this) + + if (errorImageDrawable != null) + builder.error(errorImageDrawable).into(this) + else + builder.into(this) + true } catch (e: Exception) { logError(e) @@ -316,7 +327,7 @@ object UIHelper { } fun Context?.IsBottomLayout(): Boolean { - if(this == null) return true + if (this == null) return true val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) return settingsManager.getBoolean(getString(R.string.bottom_title_key), true) } diff --git a/app/src/main/res/drawable/monke_benene.xml b/app/src/main/res/drawable/monke_benene.xml new file mode 100644 index 00000000..7bf2fc8b --- /dev/null +++ b/app/src/main/res/drawable/monke_benene.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/monke_burrito.xml b/app/src/main/res/drawable/monke_burrito.xml new file mode 100644 index 00000000..a11ce065 --- /dev/null +++ b/app/src/main/res/drawable/monke_burrito.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/monke_coco.xml b/app/src/main/res/drawable/monke_coco.xml new file mode 100644 index 00000000..e1c27503 --- /dev/null +++ b/app/src/main/res/drawable/monke_coco.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/monke_cookie.xml b/app/src/main/res/drawable/monke_cookie.xml new file mode 100644 index 00000000..2ca63024 --- /dev/null +++ b/app/src/main/res/drawable/monke_cookie.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/monke_drink.xml b/app/src/main/res/drawable/monke_drink.xml new file mode 100644 index 00000000..b0485f5e --- /dev/null +++ b/app/src/main/res/drawable/monke_drink.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/monke_flusdered.xml b/app/src/main/res/drawable/monke_flusdered.xml new file mode 100644 index 00000000..48653189 --- /dev/null +++ b/app/src/main/res/drawable/monke_flusdered.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/monke_funny.xml b/app/src/main/res/drawable/monke_funny.xml new file mode 100644 index 00000000..12b2a035 --- /dev/null +++ b/app/src/main/res/drawable/monke_funny.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/monke_like.xml b/app/src/main/res/drawable/monke_like.xml new file mode 100644 index 00000000..40edced0 --- /dev/null +++ b/app/src/main/res/drawable/monke_like.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/monke_party.xml b/app/src/main/res/drawable/monke_party.xml new file mode 100644 index 00000000..5eb14f03 --- /dev/null +++ b/app/src/main/res/drawable/monke_party.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/monke_sob.xml b/app/src/main/res/drawable/monke_sob.xml new file mode 100644 index 00000000..b8b566de --- /dev/null +++ b/app/src/main/res/drawable/monke_sob.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/app/src/test/java/com/lagradost/cloudstream3/ProviderTests.kt b/app/src/test/java/com/lagradost/cloudstream3/ProviderTests.kt index d8438ce2..1c3b4b1b 100644 --- a/app/src/test/java/com/lagradost/cloudstream3/ProviderTests.kt +++ b/app/src/test/java/com/lagradost/cloudstream3/ProviderTests.kt @@ -97,7 +97,7 @@ class ProviderTests { continue } - val url = (load.episodes[load.episodes.keys.first()])?.first()?.url + val url = (load.episodes[load.episodes.keys.first()])?.first()?.data validResults = loadLinks(api, url) if (!validResults) continue }