mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	Plugin setup screen and hopefully fix critical error
This commit is contained in:
		
							parent
							
								
									2c399e6916
								
							
						
					
					
						commit
						6e819e3b96
					
				
					 12 changed files with 333 additions and 128 deletions
				
			
		|  | @ -10,6 +10,7 @@ import com.fasterxml.jackson.annotation.JsonProperty | |||
| import com.fasterxml.jackson.databind.DeserializationFeature | ||||
| import com.fasterxml.jackson.databind.json.JsonMapper | ||||
| import com.fasterxml.jackson.module.kotlin.KotlinModule | ||||
| import com.lagradost.cloudstream3.mvvm.debugWarning | ||||
| import com.lagradost.cloudstream3.mvvm.logError | ||||
| import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.aniListApi | ||||
| import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.malApi | ||||
|  | @ -69,7 +70,11 @@ object APIHolder { | |||
|     fun getApiFromNameNull(apiName: String?): MainAPI? { | ||||
|         if (apiName == null) return null | ||||
|         initMap() | ||||
|         return apiMap?.get(apiName)?.let { apis.getOrNull(it) } | ||||
|         // Fuck it load from allProviders since they're dynamically loaded | ||||
|         // This is required right now because apiMap might be outdated | ||||
|         // TODO FIX when we switch to LoadPlugin() | ||||
|         debugWarning { "FIX LoadPlugin! getApiFromNameNull sucks right now 💀" } | ||||
|         return apiMap?.get(apiName)?.let { apis.getOrNull(it) } ?: allProviders.firstOrNull { it.name == apiName } | ||||
|     } | ||||
| 
 | ||||
|     fun getApiFromUrlNull(url: String?): MainAPI? { | ||||
|  |  | |||
|  | @ -670,6 +670,11 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | |||
|         try { | ||||
|             if (getKey(HAS_DONE_SETUP_KEY, false) != true) { | ||||
|                 navController.navigate(R.id.navigation_setup_language) | ||||
|                 // If no plugins bring up extensions screen | ||||
|             } else if (PluginManager.getPluginsOnline().isEmpty() | ||||
|                 && PluginManager.getPluginsLocal().isEmpty() | ||||
|             ) { | ||||
|                 navController.navigate(R.id.navigation_setup_extensions) | ||||
|             } | ||||
|         } catch (e: Exception) { | ||||
|             logError(e) | ||||
|  |  | |||
|  | @ -18,6 +18,16 @@ import java.io.File | |||
| import java.io.InputStream | ||||
| import java.io.OutputStream | ||||
| 
 | ||||
| /** | ||||
|  * Comes with the app, always available in the app, non removable. | ||||
|  * */ | ||||
| val PREBUILT_REPOSITORIES = arrayOf( | ||||
|     // TODO FIX | ||||
|     RepositoryData( | ||||
|         "Testing repository", | ||||
|         "https://raw.githubusercontent.com/recloudstream/cs-repos/master/test.json" | ||||
|     ) | ||||
| ) | ||||
| 
 | ||||
| data class Repository( | ||||
|     @JsonProperty("name") val name: String, | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ class ExtensionsFragment : Fragment() { | |||
| 
 | ||||
|         setUpToolbar(R.string.extensions) | ||||
| 
 | ||||
|         repo_recycler_view?.adapter = RepoAdapter(emptyArray(), { | ||||
|         repo_recycler_view?.adapter = RepoAdapter(emptyArray(), false, { | ||||
|             findNavController().navigate( | ||||
|                 R.id.navigation_settings_extensions_to_navigation_settings_plugins, | ||||
|                 Bundle().apply { | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ class PluginsFragment : Fragment() { | |||
|         settings_toolbar?.setOnMenuItemClickListener { menuItem -> | ||||
|             when (menuItem?.itemId) { | ||||
|                 R.id.download_all -> { | ||||
|                     pluginViewModel.downloadAll(activity, url) | ||||
|                     PluginsViewModel.downloadAll(activity, url, pluginViewModel) | ||||
|                 } | ||||
|                 else -> {} | ||||
|             } | ||||
|  |  | |||
|  | @ -29,75 +29,82 @@ class PluginsViewModel : ViewModel() { | |||
|     companion object { | ||||
|         private val repositoryCache: MutableMap<String, List<Plugin>> = mutableMapOf() | ||||
|         const val TAG = "PLG" | ||||
|     } | ||||
| 
 | ||||
|     private suspend fun getPlugins( | ||||
|         repositoryUrl: String, | ||||
|         canUseCache: Boolean = true | ||||
|     ): List<Plugin> { | ||||
|         Log.i(TAG, "getPlugins = $repositoryUrl") | ||||
|         if (canUseCache && repositoryCache.containsKey(repositoryUrl)) { | ||||
|             repositoryCache[repositoryUrl]?.let { | ||||
|                 return it | ||||
|             } | ||||
|         private fun isDownloaded(plugin: Plugin, data: Set<String>? = null): Boolean { | ||||
|             return (data ?: getDownloads()).contains(plugin.second.internalName) | ||||
|         } | ||||
|         return RepositoryManager.getRepoPlugins(repositoryUrl) | ||||
|             ?.also { repositoryCache[repositoryUrl] = it } ?: emptyList() | ||||
|     } | ||||
| 
 | ||||
|     private fun getStoredPlugins(): Array<PluginData> { | ||||
|         return PluginManager.getPluginsOnline() | ||||
|     } | ||||
| 
 | ||||
|     private fun getDownloads(): Set<String> { | ||||
|         return getStoredPlugins().map { it.internalName }.toSet() | ||||
|     } | ||||
| 
 | ||||
|     private fun isDownloaded(plugin: Plugin, data: Set<String>? = null): Boolean { | ||||
|         return (data ?: getDownloads()).contains(plugin.second.internalName) | ||||
|     } | ||||
| 
 | ||||
|     fun downloadAll(activity: Activity?, repositoryUrl: String) = ioSafe { | ||||
|         if (activity == null) return@ioSafe | ||||
|         val stored = getDownloads() | ||||
|         val plugins = getPlugins(repositoryUrl) | ||||
| 
 | ||||
|         plugins.filter { plugin -> !isDownloaded(plugin, stored) }.also { list -> | ||||
|             main { | ||||
|                 showToast( | ||||
|                     activity, | ||||
|                     if (list.isEmpty()) { | ||||
|                         txt( | ||||
|                             R.string.batch_download_nothing_to_download_format, | ||||
|                             txt(R.string.plugin) | ||||
|                         ) | ||||
|                     } else { | ||||
|                         txt(R.string.batch_download_start_format, list.size, txt(if(list.size == 1) R.string.plugin_singular else R.string.plugin)) | ||||
|                     }, | ||||
|                     Toast.LENGTH_SHORT | ||||
|                 ) | ||||
|         private suspend fun getPlugins( | ||||
|             repositoryUrl: String, | ||||
|             canUseCache: Boolean = true | ||||
|         ): List<Plugin> { | ||||
|             Log.i(TAG, "getPlugins = $repositoryUrl") | ||||
|             if (canUseCache && repositoryCache.containsKey(repositoryUrl)) { | ||||
|                 repositoryCache[repositoryUrl]?.let { | ||||
|                     return it | ||||
|                 } | ||||
|             } | ||||
|         }.apmap { (repo, metadata) -> | ||||
|             PluginManager.downloadAndLoadPlugin( | ||||
|                 activity, | ||||
|                 metadata.url, | ||||
|                 metadata.name, | ||||
|                 repo | ||||
|             ) | ||||
|         }.main { list -> | ||||
|             if (list.any { it }) { | ||||
|                 showToast( | ||||
|             return RepositoryManager.getRepoPlugins(repositoryUrl) | ||||
|                 ?.also { repositoryCache[repositoryUrl] = it } ?: emptyList() | ||||
|         } | ||||
| 
 | ||||
|         private fun getStoredPlugins(): Array<PluginData> { | ||||
|             return PluginManager.getPluginsOnline() | ||||
|         } | ||||
| 
 | ||||
|         private fun getDownloads(): Set<String> { | ||||
|             return getStoredPlugins().map { it.internalName }.toSet() | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * @param viewModel optional, updates the plugins livedata for that viewModel if included | ||||
|          * */ | ||||
|         fun downloadAll(activity: Activity?, repositoryUrl: String, viewModel: PluginsViewModel?) = ioSafe { | ||||
|             if (activity == null) return@ioSafe | ||||
|             val stored = getDownloads() | ||||
|             val plugins = getPlugins(repositoryUrl) | ||||
| 
 | ||||
|             plugins.filter { plugin -> !isDownloaded(plugin, stored) }.also { list -> | ||||
|                 main { | ||||
|                     showToast( | ||||
|                         activity, | ||||
|                         if (list.isEmpty()) { | ||||
|                             txt( | ||||
|                                 R.string.batch_download_nothing_to_download_format, | ||||
|                                 txt(R.string.plugin) | ||||
|                             ) | ||||
|                         } else { | ||||
|                             txt( | ||||
|                                 R.string.batch_download_start_format, | ||||
|                                 list.size, | ||||
|                                 txt(if (list.size == 1) R.string.plugin_singular else R.string.plugin) | ||||
|                             ) | ||||
|                         }, | ||||
|                         Toast.LENGTH_SHORT | ||||
|                     ) | ||||
|                 } | ||||
|             }.apmap { (repo, metadata) -> | ||||
|                 PluginManager.downloadAndLoadPlugin( | ||||
|                     activity, | ||||
|                     txt( | ||||
|                         R.string.batch_download_finish_format, | ||||
|                         list.count { it }, | ||||
|                         txt(if(list.size == 1) R.string.plugin_singular else R.string.plugin) | ||||
|                     ), | ||||
|                     Toast.LENGTH_SHORT | ||||
|                     metadata.url, | ||||
|                     metadata.name, | ||||
|                     repo | ||||
|                 ) | ||||
|                 updatePluginListPrivate(repositoryUrl) | ||||
|             } else if (list.isNotEmpty()) { | ||||
|                 showToast(activity, R.string.download_failed, Toast.LENGTH_SHORT) | ||||
|             }.main { list -> | ||||
|                 if (list.any { it }) { | ||||
|                     showToast( | ||||
|                         activity, | ||||
|                         txt( | ||||
|                             R.string.batch_download_finish_format, | ||||
|                             list.count { it }, | ||||
|                             txt(if (list.size == 1) R.string.plugin_singular else R.string.plugin) | ||||
|                         ), | ||||
|                         Toast.LENGTH_SHORT | ||||
|                     ) | ||||
|                     viewModel?.updatePluginListPrivate(repositoryUrl) | ||||
|                 } else if (list.isNotEmpty()) { | ||||
|                     showToast(activity, R.string.download_failed, Toast.LENGTH_SHORT) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -5,13 +5,16 @@ import android.view.View | |||
| import android.view.ViewGroup | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.plugins.PREBUILT_REPOSITORIES | ||||
| import com.lagradost.cloudstream3.ui.settings.AccountClickCallback | ||||
| import kotlinx.android.synthetic.main.repository_item.view.* | ||||
| 
 | ||||
| class RepoAdapter( | ||||
|     var repositories: Array<RepositoryData>, | ||||
|     val isSetup: Boolean, | ||||
|     val clickCallback: RepoAdapter.(RepositoryData) -> Unit, | ||||
|     val imageClickCallback: RepoAdapter.(RepositoryData) -> Unit | ||||
|     val imageClickCallback: RepoAdapter.(RepositoryData) -> Unit, | ||||
|     /** In setup mode the trash icons will be replaced with download icons */ | ||||
| ) : | ||||
|     RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||||
|  | @ -37,7 +40,16 @@ class RepoAdapter( | |||
|         fun bind( | ||||
|             repositoryData: RepositoryData | ||||
|         ) { | ||||
|             itemView.action_button?.setImageResource(R.drawable.ic_baseline_delete_outline_24) | ||||
|             val isPrebuilt = PREBUILT_REPOSITORIES.contains(repositoryData) | ||||
|             val drawable = | ||||
|                 if (isSetup) R.drawable.netflix_download else R.drawable.ic_baseline_delete_outline_24 | ||||
| 
 | ||||
|             // Only shows icon if on setup or if it isn't a prebuilt repo. | ||||
|             // No delete buttons on prebuilt repos. | ||||
|             if (!isPrebuilt || isSetup) { | ||||
|                 itemView.action_button?.setImageResource(drawable) | ||||
|             } | ||||
| 
 | ||||
|             itemView.action_button?.setOnClickListener { | ||||
|                 imageClickCallback(repositoryData) | ||||
|             } | ||||
|  |  | |||
|  | @ -0,0 +1,68 @@ | |||
| package com.lagradost.cloudstream3.ui.setup | ||||
| 
 | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import androidx.core.view.isVisible | ||||
| import androidx.fragment.app.Fragment | ||||
| import androidx.navigation.fragment.findNavController | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.plugins.PREBUILT_REPOSITORIES | ||||
| import com.lagradost.cloudstream3.ui.settings.extensions.PluginsViewModel | ||||
| import com.lagradost.cloudstream3.ui.settings.extensions.RepoAdapter | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | ||||
| import kotlinx.android.synthetic.main.fragment_extensions.* | ||||
| import kotlinx.android.synthetic.main.fragment_setup_media.* | ||||
| 
 | ||||
| 
 | ||||
| class SetupFragmentExtensions : Fragment() { | ||||
|     companion object { | ||||
|         const val SETUP_EXTENSION_BUNDLE_IS_SETUP = "isSetup" | ||||
|         fun newInstance(isSetup: Boolean): Bundle { | ||||
|             return Bundle().apply { | ||||
|                 putBoolean(SETUP_EXTENSION_BUNDLE_IS_SETUP, isSetup) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateView( | ||||
|         inflater: LayoutInflater, container: ViewGroup?, | ||||
|         savedInstanceState: Bundle? | ||||
|     ): View? { | ||||
|         return inflater.inflate(R.layout.fragment_setup_extensions, container, false) | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
|         context?.fixPaddingStatusbar(setup_root) | ||||
|         val isSetup = arguments?.getBoolean(SETUP_EXTENSION_BUNDLE_IS_SETUP) ?: false | ||||
| 
 | ||||
|         with(context) { | ||||
|             if (this == null) return | ||||
| 
 | ||||
|             repo_recycler_view?.adapter = RepoAdapter(PREBUILT_REPOSITORIES, true, {}, { | ||||
|                 PluginsViewModel.downloadAll(activity, it.url, null) | ||||
|             }) | ||||
| 
 | ||||
|             if (!isSetup) { | ||||
|                 next_btt.setText(R.string.setup_done) | ||||
|             } | ||||
|             prev_btt?.isVisible = isSetup | ||||
| 
 | ||||
|             next_btt?.setOnClickListener { | ||||
|                 // Continue setup | ||||
|                 if (isSetup) | ||||
|                     findNavController().navigate(R.id.action_navigation_setup_extensions_to_navigation_setup_provider_languages) | ||||
|                 else | ||||
|                     findNavController().popBackStack() | ||||
|             } | ||||
| 
 | ||||
|             prev_btt?.setOnClickListener { | ||||
|                 findNavController().popBackStack() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -14,6 +14,7 @@ import com.lagradost.cloudstream3.BuildConfig | |||
| import com.lagradost.cloudstream3.CommonActivity | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.plugins.PluginManager | ||||
| import com.lagradost.cloudstream3.ui.settings.appLanguages | ||||
| import com.lagradost.cloudstream3.ui.settings.getCurrentLocale | ||||
| import com.lagradost.cloudstream3.utils.SubtitleHelper | ||||
|  | @ -23,6 +24,7 @@ import kotlinx.android.synthetic.main.fragment_setup_media.listview1 | |||
| import kotlinx.android.synthetic.main.fragment_setup_media.next_btt | ||||
| 
 | ||||
| const val HAS_DONE_SETUP_KEY = "HAS_DONE_SETUP" | ||||
| 
 | ||||
| class SetupFragmentLanguage : Fragment() { | ||||
|     override fun onCreateView( | ||||
|         inflater: LayoutInflater, container: ViewGroup?, | ||||
|  | @ -76,7 +78,13 @@ class SetupFragmentLanguage : Fragment() { | |||
|                 } | ||||
| 
 | ||||
|                 next_btt?.setOnClickListener { | ||||
|                     findNavController().navigate(R.id.action_navigation_setup_language_to_navigation_setup_provider_languages) | ||||
|                     // If no plugins go to plugins page | ||||
|                     val nextDestination = if (PluginManager.getPluginsOnline() | ||||
|                             .isEmpty() | ||||
|                     ) R.id.action_navigation_global_to_navigation_setup_extensions | ||||
|                     else R.id.action_navigation_setup_language_to_navigation_setup_provider_languages | ||||
| 
 | ||||
|                     findNavController().navigate(nextDestination, SetupFragmentExtensions.newInstance(true)) | ||||
|                 } | ||||
| 
 | ||||
|                 skip_btt?.setOnClickListener { | ||||
|  |  | |||
							
								
								
									
										56
									
								
								app/src/main/res/layout/fragment_setup_extensions.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								app/src/main/res/layout/fragment_setup_extensions.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:id="@+id/setup_root" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:orientation="vertical"> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginTop="20dp" | ||||
|         android:gravity="center" | ||||
|         android:text="@string/extensions" | ||||
|         android:textSize="18sp" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:gravity="center" | ||||
|         android:text="@string/setup_extensions_subtext" /> | ||||
| 
 | ||||
|     <androidx.recyclerview.widget.RecyclerView | ||||
|         android:id="@+id/repo_recycler_view" | ||||
|         app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         tools:listitem="@layout/repository_item" /> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         android:id="@+id/apply_btt_holder" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="60dp" | ||||
|         android:layout_gravity="bottom" | ||||
|         android:layout_marginTop="-60dp" | ||||
|         android:gravity="bottom|end" | ||||
|         android:orientation="horizontal"> | ||||
| 
 | ||||
|         <com.google.android.material.button.MaterialButton | ||||
|             android:id="@+id/next_btt" | ||||
|             style="@style/WhiteButton" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_gravity="center_vertical|end" | ||||
|             android:text="@string/next" /> | ||||
| 
 | ||||
|         <com.google.android.material.button.MaterialButton | ||||
|             android:id="@+id/prev_btt" | ||||
|             style="@style/BlackButton" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_gravity="center_vertical|end" | ||||
|             android:text="@string/previous" /> | ||||
|     </LinearLayout> | ||||
| 
 | ||||
| 
 | ||||
| </LinearLayout> | ||||
|  | @ -5,30 +5,30 @@ | |||
|     android:id="@+id/mobile_navigation" | ||||
|     app:startDestination="@+id/navigation_home"> | ||||
|     <action | ||||
|             android:id="@+id/global_to_navigation_results_tv" | ||||
|             app:destination="@id/navigation_results_tv" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim"> | ||||
|         android:id="@+id/global_to_navigation_results_tv" | ||||
|         app:destination="@id/navigation_results_tv" | ||||
|         app:enterAnim="@anim/enter_anim" | ||||
|         app:exitAnim="@anim/exit_anim" | ||||
|         app:popEnterAnim="@anim/enter_anim" | ||||
|         app:popExitAnim="@anim/exit_anim"> | ||||
|         <argument | ||||
|                 android:name="url" | ||||
|                 app:argType="string" /> | ||||
|             android:name="url" | ||||
|             app:argType="string" /> | ||||
|         <argument | ||||
|                 android:name="apiName" | ||||
|                 app:argType="string" /> | ||||
|             android:name="apiName" | ||||
|             app:argType="string" /> | ||||
|         <argument | ||||
|                 android:name="startAction" | ||||
|                 android:defaultValue="0" | ||||
|                 app:argType="integer" /> | ||||
|             android:name="startAction" | ||||
|             android:defaultValue="0" | ||||
|             app:argType="integer" /> | ||||
|         <argument | ||||
|                 android:name="startValue" | ||||
|                 android:defaultValue="0" | ||||
|                 app:argType="integer" /> | ||||
|             android:name="startValue" | ||||
|             android:defaultValue="0" | ||||
|             app:argType="integer" /> | ||||
|         <argument | ||||
|                 android:name="restart" | ||||
|                 android:defaultValue="false" | ||||
|                 app:argType="boolean" /> | ||||
|             android:name="restart" | ||||
|             android:defaultValue="false" | ||||
|             app:argType="boolean" /> | ||||
|     </action> | ||||
|     <action | ||||
|         android:id="@+id/global_to_navigation_results_phone" | ||||
|  | @ -160,7 +160,8 @@ | |||
|         app:enterAnim="@anim/enter_anim" | ||||
|         app:exitAnim="@anim/exit_anim" | ||||
|         app:popEnterAnim="@anim/enter_anim" | ||||
|         app:popExitAnim="@anim/exit_anim"> | ||||
|         app:popExitAnim="@anim/exit_anim" | ||||
|         tools:layout="@layout/fragment_extensions"> | ||||
|         <action | ||||
|             android:id="@+id/navigation_settings_extensions_to_navigation_settings_plugins" | ||||
|             app:destination="@id/navigation_settings_plugins" | ||||
|  | @ -186,7 +187,8 @@ | |||
|         app:enterAnim="@anim/enter_anim" | ||||
|         app:exitAnim="@anim/exit_anim" | ||||
|         app:popEnterAnim="@anim/enter_anim" | ||||
|         app:popExitAnim="@anim/exit_anim" /> | ||||
|         app:popExitAnim="@anim/exit_anim" | ||||
|         tools:layout="@layout/fragment_plugins" /> | ||||
| 
 | ||||
|     <fragment | ||||
|         android:id="@+id/navigation_settings_lang" | ||||
|  | @ -258,8 +260,7 @@ | |||
|         app:exitAnim="@anim/exit_anim" | ||||
|         app:popEnterAnim="@anim/enter_anim" | ||||
|         app:popExitAnim="@anim/exit_anim" | ||||
|         tools:layout="@layout/fragment_search"> | ||||
|     </fragment> | ||||
|         tools:layout="@layout/fragment_search" /> | ||||
| 
 | ||||
|     <fragment | ||||
|         android:id="@+id/navigation_downloads" | ||||
|  | @ -406,53 +407,53 @@ | |||
|     </fragment> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_results_phone" | ||||
|             android:name="com.lagradost.cloudstream3.ui.result.ResultFragmentPhone" | ||||
|             android:layout_height="match_parent" | ||||
|         android:id="@+id/navigation_results_phone" | ||||
|         android:name="com.lagradost.cloudstream3.ui.result.ResultFragmentPhone" | ||||
|         android:layout_height="match_parent" | ||||
|         app:enterAnim="@anim/enter_anim" | ||||
|         app:exitAnim="@anim/exit_anim" | ||||
|         app:popEnterAnim="@anim/enter_anim" | ||||
|         app:popExitAnim="@anim/exit_anim" | ||||
|         tools:layout="@layout/fragment_result_swipe"> | ||||
|         <action | ||||
|             android:id="@+id/action_navigation_results_phone_to_navigation_quick_search" | ||||
|             app:destination="@id/navigation_quick_search" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" | ||||
|             tools:layout="@layout/fragment_result_swipe"> | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
|         <action | ||||
|                 android:id="@+id/action_navigation_results_phone_to_navigation_quick_search" | ||||
|                 app:destination="@id/navigation_quick_search" | ||||
|                 app:enterAnim="@anim/enter_anim" | ||||
|                 app:exitAnim="@anim/exit_anim" | ||||
|                 app:popEnterAnim="@anim/enter_anim" | ||||
|                 app:popExitAnim="@anim/exit_anim" /> | ||||
|         <action | ||||
|                 android:id="@+id/action_navigation_results_phone_to_navigation_player" | ||||
|                 app:destination="@id/navigation_player" | ||||
|                 app:enterAnim="@anim/enter_anim" | ||||
|                 app:exitAnim="@anim/exit_anim" | ||||
|                 app:popEnterAnim="@anim/enter_anim" | ||||
|                 app:popExitAnim="@anim/exit_anim" /> | ||||
|             android:id="@+id/action_navigation_results_phone_to_navigation_player" | ||||
|             app:destination="@id/navigation_player" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
|     </fragment> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_results_tv" | ||||
|             android:name="com.lagradost.cloudstream3.ui.result.ResultFragmentTv" | ||||
|             android:layout_height="match_parent" | ||||
|         android:id="@+id/navigation_results_tv" | ||||
|         android:name="com.lagradost.cloudstream3.ui.result.ResultFragmentTv" | ||||
|         android:layout_height="match_parent" | ||||
|         app:enterAnim="@anim/enter_anim" | ||||
|         app:exitAnim="@anim/exit_anim" | ||||
|         app:popEnterAnim="@anim/enter_anim" | ||||
|         app:popExitAnim="@anim/exit_anim" | ||||
|         tools:layout="@layout/fragment_result_swipe"> | ||||
|         <action | ||||
|             android:id="@+id/action_navigation_results_tv_to_navigation_quick_search" | ||||
|             app:destination="@id/navigation_quick_search" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" | ||||
|             tools:layout="@layout/fragment_result_swipe"> | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
|         <action | ||||
|                 android:id="@+id/action_navigation_results_tv_to_navigation_quick_search" | ||||
|                 app:destination="@id/navigation_quick_search" | ||||
|                 app:enterAnim="@anim/enter_anim" | ||||
|                 app:exitAnim="@anim/exit_anim" | ||||
|                 app:popEnterAnim="@anim/enter_anim" | ||||
|                 app:popExitAnim="@anim/exit_anim" /> | ||||
|         <action | ||||
|                 android:id="@+id/action_navigation_results_tv_to_navigation_player" | ||||
|                 app:destination="@id/navigation_player" | ||||
|                 app:enterAnim="@anim/enter_anim" | ||||
|                 app:exitAnim="@anim/exit_anim" | ||||
|                 app:popEnterAnim="@anim/enter_anim" | ||||
|                 app:popExitAnim="@anim/exit_anim" /> | ||||
|             android:id="@+id/action_navigation_results_tv_to_navigation_player" | ||||
|             app:destination="@id/navigation_player" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
|     </fragment> | ||||
| 
 | ||||
|     <!--<fragment | ||||
|  | @ -508,6 +509,38 @@ | |||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
|     </fragment> | ||||
| 
 | ||||
|     <action | ||||
|         android:id="@+id/action_navigation_global_to_navigation_setup_extensions" | ||||
|         app:destination="@id/navigation_setup_extensions" | ||||
|         app:enterAnim="@anim/enter_anim" | ||||
|         app:exitAnim="@anim/exit_anim" | ||||
|         app:popEnterAnim="@anim/enter_anim" | ||||
|         app:popExitAnim="@anim/exit_anim"> | ||||
|         <argument | ||||
|             android:name="isSetup" | ||||
|             android:defaultValue="false" | ||||
|             app:argType="boolean" /> | ||||
|     </action> | ||||
| 
 | ||||
|     <fragment | ||||
|         android:id="@+id/navigation_setup_extensions" | ||||
|         android:name="com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions" | ||||
|         android:layout_height="match_parent" | ||||
|         app:enterAnim="@anim/enter_anim" | ||||
|         app:exitAnim="@anim/exit_anim" | ||||
|         app:popEnterAnim="@anim/enter_anim" | ||||
|         app:popExitAnim="@anim/exit_anim" | ||||
|         tools:layout="@layout/fragment_setup_extensions"> | ||||
|         <action | ||||
|             android:id="@+id/action_navigation_setup_extensions_to_navigation_setup_provider_languages" | ||||
|             app:destination="@id/navigation_setup_provider_languages" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
|     </fragment> | ||||
| 
 | ||||
|     <fragment | ||||
|         android:id="@+id/navigation_setup_provider_languages" | ||||
|         android:name="com.lagradost.cloudstream3.ui.setup.SetupFragmentProviderLanguage" | ||||
|  |  | |||
|  | @ -585,4 +585,5 @@ | |||
|     <string name="plugin">plugins</string> | ||||
|     <string name="delete_repository_plugins">This will also delete all repository plugins</string> | ||||
|     <string name="delete_repository">Delete repository</string> | ||||
|     <string name="setup_extensions_subtext">Download the list of sites you want to use</string> | ||||
| </resources> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue