mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	fixed homepage
This commit is contained in:
		
							parent
							
								
									1c494f0ce2
								
							
						
					
					
						commit
						f268418190
					
				
					 7 changed files with 316 additions and 227 deletions
				
			
		|  | @ -1,40 +1,39 @@ | |||
| package com.lagradost.cloudstream3.plugins | ||||
| 
 | ||||
| import android.app.* | ||||
| import dalvik.system.PathClassLoader | ||||
| import com.google.gson.Gson | ||||
| import android.content.Context | ||||
| import android.content.res.AssetManager | ||||
| import android.content.res.Resources | ||||
| import android.os.Environment | ||||
| import android.widget.Toast | ||||
| import android.content.Context | ||||
| import android.os.Build | ||||
| import android.os.Environment | ||||
| import android.util.Log | ||||
| import android.widget.Toast | ||||
| import androidx.core.app.NotificationCompat | ||||
| import androidx.core.app.NotificationManagerCompat | ||||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.google.gson.Gson | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.APIHolder.removePluginMapping | ||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.getKey | ||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey | ||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.setKey | ||||
| import com.lagradost.cloudstream3.plugins.RepositoryManager.ONLINE_PLUGINS_FOLDER | ||||
| import com.lagradost.cloudstream3.plugins.RepositoryManager.downloadPluginToFile | ||||
| import com.lagradost.cloudstream3.CommonActivity.showToast | ||||
| import com.lagradost.cloudstream3.plugins.RepositoryManager.getRepoPlugins | ||||
| import com.lagradost.cloudstream3.ui.settings.extensions.REPOSITORIES_KEY | ||||
| import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadManager.sanitizeFilename | ||||
| import com.lagradost.cloudstream3.APIHolder.removePluginMapping | ||||
| import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent | ||||
| import com.lagradost.cloudstream3.mvvm.debugPrint | ||||
| import com.lagradost.cloudstream3.mvvm.logError | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.plugins.RepositoryManager.ONLINE_PLUGINS_FOLDER | ||||
| import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.ioSafe | ||||
| import com.lagradost.cloudstream3.plugins.RepositoryManager.downloadPluginToFile | ||||
| import com.lagradost.cloudstream3.plugins.RepositoryManager.getRepoPlugins | ||||
| import com.lagradost.cloudstream3.ui.settings.extensions.REPOSITORIES_KEY | ||||
| import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.main | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadManager.sanitizeFilename | ||||
| import com.lagradost.cloudstream3.utils.extractorApis | ||||
| import dalvik.system.PathClassLoader | ||||
| import kotlinx.coroutines.sync.Mutex | ||||
| import kotlinx.coroutines.sync.withLock | ||||
| import java.io.File | ||||
|  | @ -217,7 +216,7 @@ object PluginManager { | |||
|      * 3. If outdated download and load the plugin | ||||
|      * 4. Else load the plugin normally | ||||
|      **/ | ||||
|     fun updateAllOnlinePluginsAndLoadThem(activity: Activity) = ioSafe { | ||||
|     fun updateAllOnlinePluginsAndLoadThem(activity: Activity) { | ||||
|         // Load all plugins as fast as possible! | ||||
|         loadAllOnlinePlugins(activity) | ||||
| 
 | ||||
|  | @ -227,7 +226,7 @@ object PluginManager { | |||
|         val urls = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY) | ||||
|             ?: emptyArray()) + PREBUILT_REPOSITORIES | ||||
| 
 | ||||
|         val onlinePlugins = urls.toList().amap { | ||||
|         val onlinePlugins = urls.toList().apmap { | ||||
|             getRepoPlugins(it.url)?.toList() ?: emptyList() | ||||
|         }.flatten().distinctBy { it.second.url } | ||||
| 
 | ||||
|  | @ -248,7 +247,7 @@ object PluginManager { | |||
| 
 | ||||
|         val updatedPlugins = mutableListOf<String>() | ||||
| 
 | ||||
|         outdatedPlugins.amap { pluginData -> | ||||
|         outdatedPlugins.apmap { pluginData -> | ||||
|             if (pluginData.isDisabled) { | ||||
|                 //updatedPlugins.add(activity.getString(R.string.single_plugin_disabled, pluginData.onlineData.second.name)) | ||||
|                 unloadPlugin(pluginData.savedData.filePath) | ||||
|  | @ -279,9 +278,9 @@ object PluginManager { | |||
|     /** | ||||
|      * Use updateAllOnlinePluginsAndLoadThem | ||||
|      * */ | ||||
|     fun loadAllOnlinePlugins(activity: Activity) = ioSafe { | ||||
|     fun loadAllOnlinePlugins(activity: Activity) { | ||||
|         // Load all plugins as fast as possible! | ||||
|         (getPluginsOnline()).toList().amap { pluginData -> | ||||
|         (getPluginsOnline()).toList().apmap { pluginData -> | ||||
|             loadPlugin( | ||||
|                 activity, | ||||
|                 File(pluginData.filePath), | ||||
|  | @ -290,7 +289,7 @@ object PluginManager { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun loadAllLocalPlugins(activity: Activity) = ioSafe { | ||||
|     fun loadAllLocalPlugins(activity: Activity) { | ||||
|         val dir = File(LOCAL_PLUGINS_PATH) | ||||
|         removeKey(PLUGINS_KEY_LOCAL) | ||||
| 
 | ||||
|  | @ -298,7 +297,7 @@ object PluginManager { | |||
|             val res = dir.mkdirs() | ||||
|             if (!res) { | ||||
|                 Log.w(TAG, "Failed to create local directories") | ||||
|                 return@ioSafe | ||||
|                 return | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| package com.lagradost.cloudstream3.ui.home | ||||
| 
 | ||||
| import android.animation.LayoutTransition | ||||
| import android.annotation.SuppressLint | ||||
| import android.app.Activity | ||||
| import android.content.Context | ||||
|  | @ -26,13 +25,13 @@ import androidx.recyclerview.widget.LinearLayoutManager | |||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import androidx.transition.ChangeBounds | ||||
| import androidx.transition.TransitionManager | ||||
| import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback | ||||
| import com.google.android.material.bottomsheet.BottomSheetBehavior | ||||
| import com.google.android.material.bottomsheet.BottomSheetDialog | ||||
| import com.google.android.material.button.MaterialButton | ||||
| import com.google.android.material.chip.Chip | ||||
| import com.google.android.material.chip.ChipGroup | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.APIHolder.allProviders | ||||
| import com.lagradost.cloudstream3.APIHolder.apis | ||||
| import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia | ||||
| import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull | ||||
|  | @ -554,7 +553,9 @@ class HomeFragment : Fragment() { | |||
|                 is Resource.Success -> { | ||||
|                     home_preview?.isVisible = true | ||||
|                     (home_preview_viewpager?.adapter as? HomeScrollAdapter)?.apply { | ||||
|                         setItems(preview.value) | ||||
|                         if (!setItems(preview.value.second, preview.value.first)) { | ||||
|                             home_preview_viewpager?.setCurrentItem(0, false) | ||||
|                         } | ||||
|                         // home_preview_viewpager?.setCurrentItem(1000, false) | ||||
|                     } | ||||
| 
 | ||||
|  | @ -563,6 +564,10 @@ class HomeFragment : Fragment() { | |||
|                     //} | ||||
|                 } | ||||
|                 else -> { | ||||
|                     (home_preview_viewpager?.adapter as? HomeScrollAdapter)?.setItems( | ||||
|                         listOf(), | ||||
|                         false | ||||
|                     ) | ||||
|                     home_preview?.isVisible = false | ||||
|                     context?.fixPaddingStatusbar(home_watch_holder) | ||||
|                 } | ||||
|  | @ -577,59 +582,75 @@ class HomeFragment : Fragment() { | |||
|         } | ||||
| 
 | ||||
|         home_preview_viewpager?.apply { | ||||
|             setPageTransformer(false, HomeScrollTransformer()) | ||||
|             adapter = HomeScrollAdapter { load -> | ||||
|                 load.apply { | ||||
|                     home_preview_title_holder?.let { parent -> | ||||
|                         TransitionManager.beginDelayedTransition(parent, ChangeBounds()) | ||||
|                     } | ||||
| 
 | ||||
|                     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() | ||||
|             setPageTransformer(HomeScrollTransformer()) | ||||
|             val callback: OnPageChangeCallback = object : OnPageChangeCallback() { | ||||
|                 override fun onPageSelected(position: Int) { | ||||
|                     (home_preview_viewpager?.adapter as? HomeScrollAdapter)?.apply { | ||||
|                         if (position >= itemCount - 1 && hasMoreItems) { | ||||
|                             hasMoreItems = false // dont make two requests | ||||
|                             homeViewModel.loadMoreHomeScrollResponses() | ||||
|                         } | ||||
| 
 | ||||
|                         getItem(position) | ||||
|                             ?.apply { | ||||
|                                 home_preview_title_holder?.let { parent -> | ||||
|                                     TransitionManager.beginDelayedTransition(parent, ChangeBounds()) | ||||
|                                 } | ||||
| 
 | ||||
|                                 // 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(this.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(this.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(this, newValue) | ||||
|                                         reloadStored() | ||||
|                                     } | ||||
|                                 } | ||||
| 
 | ||||
|                             } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
|             registerOnPageChangeCallback(callback) | ||||
|             adapter = HomeScrollAdapter() | ||||
|         } | ||||
| 
 | ||||
|         observe(homeViewModel.apiName) { apiName -> | ||||
|  |  | |||
|  | @ -1,60 +1,89 @@ | |||
| package com.lagradost.cloudstream3.ui.home | ||||
| 
 | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.ImageView | ||||
| import androidx.viewpager.widget.PagerAdapter | ||||
| import androidx.core.view.isGone | ||||
| import androidx.recyclerview.widget.DiffUtil | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.lagradost.cloudstream3.LoadResponse | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.setImage | ||||
| import kotlinx.android.synthetic.main.home_scroll_view.view.* | ||||
| 
 | ||||
| 
 | ||||
| class HomeScrollAdapter(private val onPrimaryCallback: (LoadResponse) -> Unit) : PagerAdapter() { | ||||
|     private var items: List<LoadResponse> = listOf() | ||||
| class HomeScrollAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
|     private var items: MutableList<LoadResponse> = mutableListOf() | ||||
|     var hasMoreItems: Boolean = false | ||||
| 
 | ||||
|     fun setItems(newItems: List<LoadResponse>) { | ||||
|         items = newItems | ||||
| 
 | ||||
|         notifyDataSetChanged() | ||||
|     fun getItem(position: Int) : LoadResponse? { | ||||
|         return items.getOrNull(position) | ||||
|     } | ||||
| 
 | ||||
|     override fun getCount(): Int { | ||||
|         return Int.MAX_VALUE//items.size | ||||
|     fun setItems(newItems: List<LoadResponse>, hasNext: Boolean): Boolean { | ||||
|         val isSame = newItems.firstOrNull()?.url == items.firstOrNull()?.url | ||||
|         hasMoreItems = hasNext | ||||
| 
 | ||||
|         val diffResult = DiffUtil.calculateDiff( | ||||
|             HomeScrollDiffCallback(this.items, newItems) | ||||
|         ) | ||||
| 
 | ||||
|         items.clear() | ||||
|         items.addAll(newItems) | ||||
| 
 | ||||
| 
 | ||||
|         diffResult.dispatchUpdatesTo(this) | ||||
| 
 | ||||
|         return isSame | ||||
|     } | ||||
| 
 | ||||
|     override fun getItemPosition(`object`: Any): Int { | ||||
|         return POSITION_NONE//super.getItemPosition(`object`) | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||||
|         return CardViewHolder( | ||||
|             LayoutInflater.from(parent.context).inflate(R.layout.home_scroll_view, parent, false), | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     private fun getItemAtPosition(idx: Int): LoadResponse { | ||||
|         return items[idx % items.size] | ||||
|     override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { | ||||
|         when (holder) { | ||||
|             is CardViewHolder -> { | ||||
|                 holder.bind(items[position]) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun setPrimaryItem(container: ViewGroup, position: Int, `object`: Any) { | ||||
|         super.setPrimaryItem(container, position, `object`) | ||||
|         onPrimaryCallback.invoke(getItemAtPosition(position)) | ||||
|     class CardViewHolder | ||||
|     constructor( | ||||
|         itemView: View, | ||||
|     ) : | ||||
|         RecyclerView.ViewHolder(itemView) { | ||||
| 
 | ||||
|         fun bind(card: LoadResponse) { | ||||
|             card.apply { | ||||
|                 itemView.home_scroll_preview_tags?.text = tags?.joinToString(" • ") ?: "" | ||||
|                 itemView.home_scroll_preview_tags?.isGone = tags.isNullOrEmpty() | ||||
|                 itemView.home_scroll_preview?.setImage(posterUrl, posterHeaders) | ||||
|                 itemView.home_scroll_preview_title?.text = name | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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) | ||||
|     class HomeScrollDiffCallback( | ||||
|         private val oldList: List<LoadResponse>, | ||||
|         private val newList: List<LoadResponse> | ||||
|     ) : | ||||
|         DiffUtil.Callback() { | ||||
|         override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = | ||||
|             oldList[oldItemPosition].url == newList[newItemPosition].url | ||||
| 
 | ||||
|         // val itemView: View = mLayoutInflater.inflate(R.layout.pager_item, container, false) | ||||
|         override fun getOldListSize() = oldList.size | ||||
| 
 | ||||
|         // val imageView: ImageView = itemView.findViewById<View>(R.id.imageView) as ImageView | ||||
|         // imageView.setImageResource(mResources.get(position)) | ||||
|         override fun getNewListSize() = newList.size | ||||
| 
 | ||||
|         container.addView(image) | ||||
| 
 | ||||
|         return image | ||||
|         override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = | ||||
|             oldList[oldItemPosition] == newList[newItemPosition] | ||||
|     } | ||||
| 
 | ||||
|     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` | ||||
|     override fun getItemCount(): Int { | ||||
|         return items.size | ||||
|     } | ||||
| } | ||||
|  | @ -1,13 +1,23 @@ | |||
| package com.lagradost.cloudstream3.ui.home | ||||
| 
 | ||||
| import android.view.View | ||||
| import androidx.viewpager.widget.ViewPager | ||||
| import androidx.viewpager2.widget.ViewPager2 | ||||
| 
 | ||||
| class HomeScrollTransformer : ViewPager.PageTransformer { | ||||
| class HomeScrollTransformer : ViewPager2.PageTransformer { | ||||
|     override fun transformPage(page: View, position: Float) { | ||||
|         //page.translationX = -position * page.width / 2.0f | ||||
| 
 | ||||
|         //val params = RecyclerView.LayoutParams( | ||||
|         //    RecyclerView.LayoutParams.MATCH_PARENT, | ||||
|         //    0 | ||||
|         //) | ||||
|         //page.layoutParams = params | ||||
|         //progressBar?.layoutParams = params | ||||
| 
 | ||||
|         val padding = (-position * page.width / 2).toInt() | ||||
|         page.setPadding( | ||||
|             maxOf(0, (-position * page.width / 2).toInt()), 0, | ||||
|             maxOf(0, (position * page.width / 2).toInt()), 0 | ||||
|             padding, 0, | ||||
|             -padding, 0 | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|  | @ -4,6 +4,7 @@ import androidx.lifecycle.LiveData | |||
| import androidx.lifecycle.MutableLiveData | ||||
| import androidx.lifecycle.ViewModel | ||||
| import androidx.lifecycle.viewModelScope | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.APIHolder.apis | ||||
| import com.lagradost.cloudstream3.APIHolder.filterHomePageListByFilmQuality | ||||
| import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia | ||||
|  | @ -12,17 +13,12 @@ import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull | |||
| import com.lagradost.cloudstream3.AcraApplication.Companion.context | ||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.getKey | ||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.setKey | ||||
| import com.lagradost.cloudstream3.HomePageList | ||||
| import com.lagradost.cloudstream3.LoadResponse | ||||
| import com.lagradost.cloudstream3.MainAPI | ||||
| import com.lagradost.cloudstream3.SearchResponse | ||||
| import com.lagradost.cloudstream3.mvvm.* | ||||
| 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 | ||||
|  | @ -35,7 +31,6 @@ 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 | ||||
|  | @ -49,6 +44,8 @@ class HomeViewModel : ViewModel() { | |||
|     private val _randomItems = MutableLiveData<List<SearchResponse>?>(null) | ||||
|     val randomItems: LiveData<List<SearchResponse>?> = _randomItems | ||||
| 
 | ||||
|     private var currentShuffledList: List<SearchResponse> = listOf() | ||||
| 
 | ||||
|     private fun autoloadRepo(): APIRepository { | ||||
|         return APIRepository(apis.first { it.hasMainPage }) | ||||
|     } | ||||
|  | @ -61,9 +58,12 @@ class HomeViewModel : ViewModel() { | |||
|     val bookmarks: LiveData<Pair<Boolean, List<SearchResponse>>> = _bookmarks | ||||
| 
 | ||||
|     private val _resumeWatching = MutableLiveData<List<SearchResponse>>() | ||||
|     private val _preview = MutableLiveData<Resource<List<LoadResponse>>>() | ||||
|     private val _preview = MutableLiveData<Resource<Pair<Boolean, List<LoadResponse>>>>() | ||||
|     private val previewResponses = mutableListOf<LoadResponse>() | ||||
|     private val previewResponsesAdded = mutableSetOf<String>() | ||||
| 
 | ||||
|     val resumeWatching: LiveData<List<SearchResponse>> = _resumeWatching | ||||
|     val preview: LiveData<Resource<List<LoadResponse>>> = _preview | ||||
|     val preview: LiveData<Resource<Pair<Boolean, List<LoadResponse>>>> = _preview | ||||
| 
 | ||||
|     fun loadResumeWatching() = viewModelScope.launchSafe { | ||||
|         val resumeWatching = withContext(Dispatchers.IO) { | ||||
|  | @ -212,6 +212,40 @@ class HomeViewModel : ViewModel() { | |||
|         expandAndReturn(name) | ||||
|     } | ||||
| 
 | ||||
|     // returns the amount of items added and modifies current | ||||
|     private suspend fun updatePreviewResponses( | ||||
|         current: MutableList<LoadResponse>, | ||||
|         alreadyAdded: MutableSet<String>, | ||||
|         shuffledList: List<SearchResponse>, | ||||
|         size: Int | ||||
|     ): Int { | ||||
|         var count = 0 | ||||
| 
 | ||||
|         val addItems = arrayListOf<SearchResponse>() | ||||
|         for (searchResponse in shuffledList) { | ||||
|             if (!alreadyAdded.contains(searchResponse.url)) { | ||||
|                 addItems.add(searchResponse) | ||||
|                 previewResponsesAdded.add(searchResponse.url) | ||||
|                 if (++count >= size) { | ||||
|                     break | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         val add = addItems.amap { searchResponse -> | ||||
|             repo?.load(searchResponse.url) | ||||
|         }.mapNotNull { if (it != null && it is Resource.Success) it.value else null } | ||||
|         current.addAll(add) | ||||
|         return add.size | ||||
|     } | ||||
| 
 | ||||
|     private var addJob: Job? = null | ||||
|     fun loadMoreHomeScrollResponses() { | ||||
|         addJob = ioSafe { | ||||
|             updatePreviewResponses(previewResponses, previewResponsesAdded, currentShuffledList, 1) | ||||
|             _preview.postValue(Resource.Success((previewResponsesAdded.size < currentShuffledList.size) to previewResponses)) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun load(api: MainAPI?) = ioSafe { | ||||
|         repo = if (api != null) { | ||||
|  | @ -226,6 +260,7 @@ class HomeViewModel : ViewModel() { | |||
|         if (repo?.hasMainPage == true) { | ||||
|             _page.postValue(Resource.Loading()) | ||||
|             _preview.postValue(Resource.Loading()) | ||||
|             addJob?.cancel() | ||||
| 
 | ||||
|             when (val data = repo?.getMainPage(1, null)) { | ||||
|                 is Resource.Success -> { | ||||
|  | @ -241,64 +276,10 @@ class HomeViewModel : ViewModel() { | |||
|                         } | ||||
| 
 | ||||
|                         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) | ||||
|                             if(first == null ||first is Resource.Failure) { | ||||
|                                 first = repo?.load(items.random().list.random().url) | ||||
|                             } | ||||
|                             first?.let { | ||||
|                                 _preview.postValue(it) | ||||
|                             } ?: run { | ||||
|                                 _preview.postValue( | ||||
|                                     Resource.Failure( | ||||
|                                         false, | ||||
|                                         null, | ||||
|                                         null, | ||||
|                                         "No repo found, this should never happen" | ||||
|                                     ) | ||||
|                                 ) | ||||
|                             } | ||||
|                         } ?: run { | ||||
|                             _preview.postValue( | ||||
|                                 Resource.Failure( | ||||
|                                     false, | ||||
|                                     null, | ||||
|                                     null, | ||||
|                                     "No homepage items" | ||||
|                                 ) | ||||
|                             ) | ||||
|                         }*/ | ||||
| 
 | ||||
|                         _page.postValue(Resource.Success(expandable)) | ||||
| 
 | ||||
|                         previewResponses.clear() | ||||
|                         previewResponsesAdded.clear() | ||||
| 
 | ||||
|                         //val home = data.value | ||||
|                         if (items.isNotEmpty()) { | ||||
|  | @ -313,9 +294,30 @@ class HomeViewModel : ViewModel() { | |||
|                                     context?.filterSearchResultByFilmQuality(currentList.shuffled()) | ||||
|                                         ?: currentList.shuffled() | ||||
| 
 | ||||
|                                 updatePreviewResponses( | ||||
|                                     previewResponses, | ||||
|                                     previewResponsesAdded, | ||||
|                                     randomItems, | ||||
|                                     3 | ||||
|                                 ) | ||||
| 
 | ||||
|                                 _randomItems.postValue(randomItems) | ||||
|                                 currentShuffledList = randomItems | ||||
|                             } | ||||
|                         } | ||||
|                         if (previewResponses.isEmpty()) { | ||||
|                             _preview.postValue( | ||||
|                                 Resource.Failure( | ||||
|                                     false, | ||||
|                                     null, | ||||
|                                     null, | ||||
|                                     "No homepage responses" | ||||
|                                 ) | ||||
|                             ) | ||||
|                         } else { | ||||
|                             _preview.postValue(Resource.Success((previewResponsesAdded.size < currentShuffledList.size) to previewResponses)) | ||||
|                         } | ||||
|                         _page.postValue(Resource.Success(expandable)) | ||||
|                     } catch (e: Exception) { | ||||
|                         _randomItems.postValue(emptyList()) | ||||
|                         logError(e) | ||||
|  |  | |||
|  | @ -287,39 +287,23 @@ | |||
|                 android:visibility="gone" | ||||
|                 tools:visibility="visible"> | ||||
| 
 | ||||
|                 <androidx.viewpager.widget.ViewPager | ||||
|                 <androidx.viewpager2.widget.ViewPager2 | ||||
|                     android:id="@+id/home_preview_viewpager" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="match_parent"> | ||||
|                     android:layout_height="match_parent" | ||||
|                     android:orientation="horizontal"> | ||||
| 
 | ||||
|                 </androidx.viewpager.widget.ViewPager> | ||||
|                 </androidx.viewpager2.widget.ViewPager2> | ||||
| 
 | ||||
|                 <ImageView | ||||
|                     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" | ||||
|                     android:visibility="gone" | ||||
|                     tools:src="@drawable/example_poster" /> | ||||
| 
 | ||||
|                 <View | ||||
|                     android:id="@+id/title_shadow_top" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="150dp" | ||||
|                     android:layout_gravity="top" | ||||
|                     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" | ||||
|                     android:layout_height="300dp" | ||||
|                     android:layout_gravity="bottom" | ||||
|                     android:background="@drawable/background_shadow" /> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
|                     android:id="@+id/home_padding" | ||||
|                     android:layout_width="match_parent" | ||||
|  | @ -363,44 +347,14 @@ | |||
|                 --> | ||||
| 
 | ||||
|                 <LinearLayout | ||||
| 
 | ||||
|                     android:id="@+id/home_preview_title_holder" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content" | ||||
|                     android:layout_height="100dp" | ||||
|                     android:layout_gravity="bottom" | ||||
|                     android:gravity="center" | ||||
|                     android:orientation="vertical"> | ||||
| 
 | ||||
|                     <TextView | ||||
|                         android:id="@+id/home_preview_title" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:gravity="center" | ||||
|                         android:paddingBottom="10dp" | ||||
|                         android:paddingHorizontal="30dp" | ||||
|                         android:textColor="?attr/white" | ||||
|                         android:textSize="17sp" | ||||
|                         android:textStyle="bold" | ||||
|                         tools:text="The Perfect Run" /> | ||||
|                     <!--<TextView | ||||
|                         android:paddingStart="30dp" | ||||
|                         android:paddingEnd="30dp" | ||||
|                         android:id="@+id/home_season_tags" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:gravity="center" | ||||
|                         android:textColor="@color/white" | ||||
|                         android:textSize="14sp" | ||||
|                         tools:text="5 seasons 50 episodes" />--> | ||||
|                     <TextView | ||||
|                         android:id="@+id/home_preview_tags" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         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:layout_width="match_parent" | ||||
|  |  | |||
							
								
								
									
										74
									
								
								app/src/main/res/layout/home_scroll_view.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								app/src/main/res/layout/home_scroll_view.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="match_parent" | ||||
|     android:background="?attr/primaryGrayBackground" | ||||
|     android:layout_height="match_parent"> | ||||
| 
 | ||||
|     <ImageView | ||||
|         android:id="@+id/home_scroll_preview" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:scaleType="centerCrop" | ||||
|         tools:src="@drawable/example_poster" /> | ||||
| 
 | ||||
|     <View | ||||
|         android:id="@+id/title_shadow_top" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="150dp" | ||||
|         android:layout_gravity="top" | ||||
|         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" | ||||
|         android:layout_height="300dp" | ||||
|         android:layout_gravity="bottom" | ||||
|         android:background="@drawable/background_shadow" /> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_gravity="center_horizontal|bottom" | ||||
|         android:layout_marginBottom="100dp" | ||||
|         android:orientation="vertical"> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/home_scroll_preview_title" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_gravity="center_horizontal" | ||||
|             android:gravity="center" | ||||
|             android:paddingHorizontal="30dp" | ||||
|             android:paddingBottom="10dp" | ||||
|             android:textColor="?attr/white" | ||||
|             android:textSize="17sp" | ||||
|             android:textStyle="bold" | ||||
|             tools:text="The Perfect Run" /> | ||||
|         <!--<TextView | ||||
|             android:paddingStart="30dp" | ||||
|             android:paddingEnd="30dp" | ||||
|             android:id="@+id/home_season_tags" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:gravity="center" | ||||
|             android:textColor="@color/white" | ||||
|             android:textSize="14sp" | ||||
|             tools:text="5 seasons 50 episodes" />--> | ||||
|         <TextView | ||||
|             android:id="@+id/home_scroll_preview_tags" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_gravity="center_horizontal" | ||||
|             android:gravity="center" | ||||
|             android:paddingStart="30dp" | ||||
|             android:paddingEnd="30dp" | ||||
|             android:textColor="?attr/white" | ||||
|             android:textSize="14sp" | ||||
|             tools:text="Hello • World • Tags" /> | ||||
|     </LinearLayout> | ||||
| 
 | ||||
| </FrameLayout> | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue