From 60aca3ebdc12ffdb9663f2bed1cc7c03a207e069 Mon Sep 17 00:00:00 2001 From: reduplicated <110570621+reduplicated@users.noreply.github.com> Date: Sat, 21 Jan 2023 23:22:48 +0100 Subject: [PATCH] very nice long hold popups --- .../lagradost/cloudstream3/MainActivity.kt | 138 +++++++++++- .../cloudstream3/ui/home/HomeFragment.kt | 12 ++ .../cloudstream3/ui/result/ResultFragment.kt | 1 + .../ui/result/ResultViewModel2.kt | 27 ++- .../cloudstream3/ui/search/SearchFragment.kt | 2 + .../cloudstream3/ui/search/SearchHelper.kt | 12 +- .../res/layout/bottom_resultview_preview.xml | 197 ++++++++++++++++++ app/src/main/res/layout/loading_list.xml | 44 ++-- 8 files changed, 392 insertions(+), 41 deletions(-) create mode 100644 app/src/main/res/layout/bottom_resultview_preview.xml diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 4907411f..857eaa6a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -1,16 +1,14 @@ package com.lagradost.cloudstream3 import android.content.ComponentName -import android.content.DialogInterface +import android.content.Context import android.content.Intent import android.content.res.ColorStateList import android.content.res.Configuration import android.os.Bundle +import android.util.AttributeSet import android.util.Log -import android.view.KeyEvent -import android.view.Menu -import android.view.MenuItem -import android.view.WindowManager +import android.view.* import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.annotation.IdRes @@ -19,6 +17,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.ViewModelProvider import androidx.navigation.NavController import androidx.navigation.NavDestination import androidx.navigation.NavDestination.Companion.hierarchy @@ -31,6 +30,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.google.android.gms.cast.framework.* +import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.navigationrail.NavigationRailView import com.jaredrummler.android.colorpicker.ColorPickerDialogListener import com.lagradost.cloudstream3.APIHolder.allProviders @@ -46,8 +46,7 @@ import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent import com.lagradost.cloudstream3.CommonActivity.onUserLeaveHint import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.CommonActivity.updateLocale -import com.lagradost.cloudstream3.mvvm.logError -import com.lagradost.cloudstream3.mvvm.normalSafeApiCall +import com.lagradost.cloudstream3.mvvm.* import com.lagradost.cloudstream3.network.initClient import com.lagradost.cloudstream3.plugins.PluginManager import com.lagradost.cloudstream3.plugins.PluginManager.loadAllOnlinePlugins @@ -61,9 +60,13 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStri import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringSearch import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.inAppAuths import com.lagradost.cloudstream3.ui.APIRepository +import com.lagradost.cloudstream3.ui.WatchType import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO import com.lagradost.cloudstream3.ui.home.HomeViewModel +import com.lagradost.cloudstream3.ui.result.ResultViewModel2 import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST +import com.lagradost.cloudstream3.ui.result.setImage +import com.lagradost.cloudstream3.ui.result.setText import com.lagradost.cloudstream3.ui.search.SearchFragment import com.lagradost.cloudstream3.ui.search.SearchResultBuilder import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings @@ -74,6 +77,7 @@ import com.lagradost.cloudstream3.ui.settings.SettingsGeneral import com.lagradost.cloudstream3.ui.setup.HAS_DONE_SETUP_KEY import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.utils.AppUtils.html import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable import com.lagradost.cloudstream3.utils.AppUtils.loadCache import com.lagradost.cloudstream3.utils.AppUtils.loadRepository @@ -86,9 +90,11 @@ import com.lagradost.cloudstream3.utils.DataStore.getKey import com.lagradost.cloudstream3.utils.DataStore.setKey import com.lagradost.cloudstream3.utils.DataStoreHelper.migrateResumeWatching import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate +import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog import com.lagradost.cloudstream3.utils.UIHelper.changeStatusBarState import com.lagradost.cloudstream3.utils.UIHelper.checkWrite import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute +import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe import com.lagradost.cloudstream3.utils.UIHelper.getResourceColor import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard import com.lagradost.cloudstream3.utils.UIHelper.navigate @@ -96,6 +102,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.requestRW import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.ResponseParser import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.bottom_resultview_preview.* import kotlinx.android.synthetic.main.fragment_result_swipe.* import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock @@ -244,6 +251,10 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { Event() // homepage api, used to speed up time to load for homepage val afterRepositoryLoadedEvent = Event() + // kinda shitty solution, but cant com main->home otherwise for popups + val bookmarksUpdatedEvent = Event() + + /** * @return true if the str has launched an app task (be it successful or not) * @param isWebview does not handle providers and opening download page if true. Can still add repos and login. @@ -336,6 +347,16 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { } } + var lastPopup : SearchResponse? = null + fun loadPopup(result: SearchResponse) { + lastPopup = result + viewModel.load( + this, result.url, result.apiName, false, if (getApiDubstatusSettings() + .contains(DubStatus.Dubbed) + ) DubStatus.Dubbed else DubStatus.Subbed, null + ) + } + override fun onColorSelected(dialogId: Int, color: Int) { onColorSelectedEvent.invoke(Pair(dialogId, color)) } @@ -619,6 +640,37 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { } } + lateinit var viewModel: ResultViewModel2 + + override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { + viewModel = + ViewModelProvider(this)[ResultViewModel2::class.java] + + return super.onCreateView(name, context, attrs) + } + + private fun hidePreviewPopupDialog() { + viewModel.clear() + bottomPreviewPopup.dismissSafe(this) + } + + var bottomPreviewPopup: BottomSheetDialog? = null + private fun showPreviewPopupDialog(): BottomSheetDialog { + val ret = (bottomPreviewPopup ?: run { + val builder = + BottomSheetDialog(this) + builder.setContentView(R.layout.bottom_resultview_preview) + builder.setOnDismissListener { + bottomPreviewPopup = null + viewModel.clear() + } + builder.setCanceledOnTouchOutside(true) + builder.show() + builder + }) + bottomPreviewPopup = ret + return ret + } override fun onCreate(savedInstanceState: Bundle?) { app.initClient(this) @@ -708,6 +760,78 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { builder.show().setDefaultFocus() } + observeNullable(viewModel.page) { resource -> + if (resource == null) { + bottomPreviewPopup.dismissSafe(this) + return@observeNullable + } + when (resource) { + is Resource.Failure -> { + showToast(this, R.string.error) + hidePreviewPopupDialog() + } + is Resource.Loading -> { + showPreviewPopupDialog().apply { + resultview_preview_loading?.isVisible = true + resultview_preview_result?.isVisible = false + resultview_preview_loading_shimmer?.startShimmer() + } + } + is Resource.Success -> { + val d = resource.value + showPreviewPopupDialog().apply { + resultview_preview_loading?.isVisible = false + resultview_preview_result?.isVisible = true + resultview_preview_loading_shimmer?.stopShimmer() + + resultview_preview_title?.text = d.title + + resultview_preview_meta_type.setText(d.typeText) + resultview_preview_meta_year.setText(d.yearText) + resultview_preview_meta_duration.setText(d.durationText) + resultview_preview_meta_rating.setText(d.ratingText) + + resultview_preview_description?.setText(d.plotText) + resultview_preview_poster?.setImage( + d.posterImage ?: d.posterBackgroundImage + ) + + resultview_preview_poster?.setOnClickListener { + //viewModel.updateWatchStatus(WatchType.PLANTOWATCH) + val value = viewModel.watchStatus.value ?: WatchType.NONE + + this@MainActivity.showBottomDialog( + WatchType.values().map { getString(it.stringRes) }.toList(), + value.ordinal, + this@MainActivity.getString(R.string.action_add_to_bookmarks), + showApply = false, + {}) { + viewModel.updateWatchStatus(WatchType.values()[it]) + bookmarksUpdatedEvent(true) + } + } + + if (!isTvSettings()) // dont want this clickable on tv layout + resultview_preview_description?.setOnClickListener { view -> + view.context?.let { ctx -> + val builder: AlertDialog.Builder = + AlertDialog.Builder(ctx, R.style.AlertDialogCustom) + builder.setMessage(d.plotText.asString(ctx).html()) + .setTitle(d.plotHeaderText.asString(ctx)) + .show() + } + } + + resultview_preview_more_info?.setOnClickListener { + hidePreviewPopupDialog() + lastPopup?.let { + loadSearchResult(it) + } + } + } + } + } + } // ioSafe { // val plugins = 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 bb183f12..8a8f90b4 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 @@ -32,6 +32,7 @@ import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent +import com.lagradost.cloudstream3.MainActivity.Companion.bookmarksUpdatedEvent import com.lagradost.cloudstream3.MainActivity.Companion.mainPluginsLoadedEvent import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.logError @@ -435,6 +436,11 @@ class HomeFragment : Fragment() { return inflater.inflate(layout, container, false) } + override fun onDestroyView() { + bottomSheetDialog?.ownHide() + super.onDestroyView() + } + private fun fixGrid() { activity?.getSpanCount()?.let { currentSpan = it @@ -461,14 +467,20 @@ class HomeFragment : Fragment() { fixGrid() } + fun bookmarksUpdated(_data : Boolean) { + reloadStored() + } + override fun onResume() { super.onResume() reloadStored() + bookmarksUpdatedEvent += ::bookmarksUpdated afterPluginsLoadedEvent += ::afterPluginsLoaded mainPluginsLoadedEvent += ::afterMainPluginsLoaded } override fun onStop() { + bookmarksUpdatedEvent -= ::bookmarksUpdated afterPluginsLoadedEvent -= ::afterPluginsLoaded mainPluginsLoadedEvent -= ::afterMainPluginsLoaded super.onStop() 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 68a57b7f..9cfbf45c 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 @@ -850,6 +850,7 @@ open class ResultFragment : ResultTrailerPlayer() { } observe(viewModel.page) { data -> + if(data == null) return@observe when (data) { is Resource.Success -> { val d = data.value diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt index 6e249aa4..6ed32b15 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt @@ -55,7 +55,6 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason import com.lagradost.cloudstream3.utils.UIHelper.navigate import kotlinx.coroutines.* import java.io.File -import java.lang.Math.abs import java.util.concurrent.TimeUnit @@ -314,6 +313,11 @@ data class ExtractedTrailerData( class ResultViewModel2 : ViewModel() { private var currentResponse: LoadResponse? = null + fun clear() { + currentResponse = null + _page.postValue(null) + } + data class EpisodeIndexer( val dubStatus: DubStatus, val season: Int, @@ -340,9 +344,9 @@ class ResultViewModel2 : ViewModel() { //private val currentHeaderName get() = currentResponse?.name - private val _page: MutableLiveData> = - MutableLiveData(Resource.Loading()) - val page: LiveData> = _page + private val _page: MutableLiveData?> = + MutableLiveData(null) + val page: LiveData?> = _page private val _episodes: MutableLiveData>> = MutableLiveData(ResourceSome.Loading()) @@ -398,7 +402,6 @@ class ResultViewModel2 : ViewModel() { private val _selectedDubStatusIndex: MutableLiveData = MutableLiveData(-1) val selectedDubStatusIndex: LiveData = _selectedDubStatusIndex - private val _loadedLinks: MutableLiveData> = MutableLiveData(Some.None) val loadedLinks: LiveData> = _loadedLinks @@ -1627,10 +1630,11 @@ class ResultViewModel2 : ViewModel() { if (ranges?.contains(range) != true) { // if the current ranges does not include the range then select the range with the closest matching start episode // this usually happends when dub has less episodes then sub -> the range does not exist - ranges?.minByOrNull { kotlin.math.abs(it.startEpisode - range.startEpisode) }?.let { r -> - postEpisodeRange(indexer, r) - return - } + ranges?.minByOrNull { kotlin.math.abs(it.startEpisode - range.startEpisode) } + ?.let { r -> + postEpisodeRange(indexer, r) + return + } } val isMovie = currentResponse?.isMovie() == true @@ -2111,6 +2115,7 @@ class ResultViewModel2 : ViewModel() { showFillers: Boolean, dubStatus: DubStatus, autostart: AutoResume?, + loadTrailers: Boolean = true, ) = viewModelScope.launchSafe { _page.postValue(Resource.Loading(url)) @@ -2189,8 +2194,8 @@ class ResultViewModel2 : ViewModel() { System.currentTimeMillis(), ) ) - - loadTrailers(data.value) + if (loadTrailers) + loadTrailers(data.value) postSuccessful( data.value, updateEpisodes = true, diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt index 1da30691..4144a042 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt @@ -45,6 +45,7 @@ import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.updateChips import com.lagradost.cloudstream3.ui.home.ParentItemAdapter import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings +import com.lagradost.cloudstream3.utils.AppUtils.ownHide import com.lagradost.cloudstream3.utils.AppUtils.ownShow import com.lagradost.cloudstream3.utils.AppUtils.setDefaultFocus import com.lagradost.cloudstream3.utils.Coroutines.main @@ -121,6 +122,7 @@ class SearchFragment : Fragment() { override fun onDestroyView() { hideKeyboard() + bottomSheetDialog?.ownHide() super.onDestroyView() } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchHelper.kt index 1de89809..45336d5b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchHelper.kt @@ -3,11 +3,13 @@ package com.lagradost.cloudstream3.ui.search import android.app.Activity import android.widget.Toast import com.lagradost.cloudstream3.CommonActivity.showToast +import com.lagradost.cloudstream3.MainActivity import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_PLAY_FILE import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick import com.lagradost.cloudstream3.ui.download.DownloadClickEvent import com.lagradost.cloudstream3.ui.result.START_ACTION_LOAD_EP +import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult import com.lagradost.cloudstream3.utils.DataStoreHelper import com.lagradost.cloudstream3.utils.VideoDownloadHelper @@ -54,7 +56,15 @@ object SearchHelper { } } SEARCH_ACTION_SHOW_METADATA -> { - showToast(activity, callback.card.name, Toast.LENGTH_SHORT) + if(!isTvSettings()) { // we only want this on phone as UI is not done yet on tv + (activity as? MainActivity?)?.apply { + loadPopup(callback.card) + } ?: kotlin.run { + showToast(activity, callback.card.name, Toast.LENGTH_SHORT) + } + } else { + showToast(activity, callback.card.name, Toast.LENGTH_SHORT) + } } } } diff --git a/app/src/main/res/layout/bottom_resultview_preview.xml b/app/src/main/res/layout/bottom_resultview_preview.xml new file mode 100644 index 00000000..ce41cb65 --- /dev/null +++ b/app/src/main/res/layout/bottom_resultview_preview.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/loading_list.xml b/app/src/main/res/layout/loading_list.xml index ccd4a8d6..1ed01c8e 100644 --- a/app/src/main/res/layout/loading_list.xml +++ b/app/src/main/res/layout/loading_list.xml @@ -1,59 +1,59 @@ + android:layout_width="match_parent" + android:layout_height="200dp" + android:orientation="vertical" + android:paddingTop="@dimen/loading_margin" + android:paddingBottom="@dimen/loading_margin"> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + android:layout_width="@dimen/loading_margin" + android:layout_height="wrap_content" /> + android:layout_width="@dimen/loading_margin" + android:layout_height="wrap_content" /> + android:layout_width="@dimen/loading_margin" + android:layout_height="wrap_content" /> + android:layout_width="@dimen/loading_margin" + android:layout_height="wrap_content" /> + android:layout_width="@dimen/loading_margin" + android:layout_height="wrap_content" /> + android:layout_width="@dimen/loading_margin" + android:layout_height="match_parent" /> + android:layout_width="@dimen/loading_margin" + android:layout_height="wrap_content" />