mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge branch 'recloudstream:master' into githubAccount
This commit is contained in:
commit
69bc1322b6
9 changed files with 131 additions and 86 deletions
|
@ -22,7 +22,6 @@ import okhttp3.Interceptor
|
|||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.collections.MutableList
|
||||
|
||||
const val USER_AGENT =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
||||
|
@ -332,13 +331,24 @@ data class SettingsJson(
|
|||
data class MainPageData(
|
||||
val name: String,
|
||||
val data: String,
|
||||
val horizontalImages: Boolean = false
|
||||
)
|
||||
|
||||
data class MainPageRequest(
|
||||
val name: String,
|
||||
val data: String,
|
||||
val horizontalImages: Boolean,
|
||||
//TODO genre selection or smth
|
||||
)
|
||||
|
||||
fun mainPage(url: String, name: String, horizontalImages: Boolean = false): MainPageData {
|
||||
return MainPageData(name = name, data = url, horizontalImages = horizontalImages)
|
||||
}
|
||||
|
||||
fun mainPageOf(vararg elements: MainPageData): List<MainPageData> {
|
||||
return elements.toList()
|
||||
}
|
||||
|
||||
/** return list of MainPageData with url to name, make for more readable code */
|
||||
fun mainPageOf(vararg elements: Pair<String, String>): List<MainPageData> {
|
||||
return elements.map { (url, name) -> MainPageData(name = name, data = url) }
|
||||
|
@ -347,7 +357,7 @@ fun mainPageOf(vararg elements: Pair<String, String>): List<MainPageData> {
|
|||
fun newHomePageResponse(
|
||||
name: String,
|
||||
list: List<SearchResponse>,
|
||||
hasNext: Boolean? = null
|
||||
hasNext: Boolean? = null,
|
||||
): HomePageResponse {
|
||||
return HomePageResponse(
|
||||
listOf(HomePageList(name, list)),
|
||||
|
@ -355,6 +365,17 @@ fun newHomePageResponse(
|
|||
)
|
||||
}
|
||||
|
||||
fun newHomePageResponse(
|
||||
data: MainPageRequest,
|
||||
list: List<SearchResponse>,
|
||||
hasNext: Boolean? = null,
|
||||
): HomePageResponse {
|
||||
return HomePageResponse(
|
||||
listOf(HomePageList(data.name, list, data.horizontalImages)),
|
||||
hasNext = hasNext ?: list.isNotEmpty()
|
||||
)
|
||||
}
|
||||
|
||||
fun newHomePageResponse(list: HomePageList, hasNext: Boolean? = null): HomePageResponse {
|
||||
return HomePageResponse(listOf(list), hasNext = hasNext ?: list.list.isNotEmpty())
|
||||
}
|
||||
|
@ -391,14 +412,17 @@ abstract class MainAPI {
|
|||
|
||||
/** if this is turned on then it will request the homepage one after the other,
|
||||
used to delay if they block many request at the same time*/
|
||||
open var sequentialMainPage : Boolean = false
|
||||
open var sequentialMainPage: Boolean = false
|
||||
|
||||
/** in milliseconds, this can be used to add more delay between homepage requests
|
||||
* on first load if sequentialMainPage is turned on */
|
||||
open var sequentialMainPageDelay : Long = 0L
|
||||
open var sequentialMainPageDelay: Long = 0L
|
||||
|
||||
/** in milliseconds, this can be used to add more delay between homepage requests when scrolling */
|
||||
open var sequentialMainPageScrollDelay : Long = 0L
|
||||
open var sequentialMainPageScrollDelay: Long = 0L
|
||||
|
||||
/** used to keep track when last homepage request was in unixtime ms */
|
||||
var lastHomepageRequest : Long = 0L
|
||||
var lastHomepageRequest: Long = 0L
|
||||
|
||||
open var lang = "en" // ISO_639_1 check SubtitleHelper
|
||||
|
||||
|
@ -431,7 +455,8 @@ abstract class MainAPI {
|
|||
open val vpnStatus = VPNStatus.None
|
||||
open val providerType = ProviderType.DirectProvider
|
||||
|
||||
open val mainPage = listOf(MainPageData("", ""))
|
||||
//emptyList<MainPageData>() //
|
||||
open val mainPage = listOf(MainPageData("", "", false))
|
||||
|
||||
@WorkerThread
|
||||
open suspend fun getMainPage(
|
||||
|
|
|
@ -66,7 +66,7 @@ class APIRepository(val api: MainAPI) {
|
|||
|
||||
suspend fun waitForHomeDelay() {
|
||||
val delta = api.sequentialMainPageScrollDelay + api.lastHomepageRequest - unixTimeMS
|
||||
if(delta < 0) return
|
||||
if (delta < 0) return
|
||||
delay(delta)
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ class APIRepository(val api: MainAPI) {
|
|||
api.lastHomepageRequest = unixTimeMS
|
||||
|
||||
nameIndex?.let { api.mainPage.getOrNull(it) }?.let { data ->
|
||||
listOf(api.getMainPage(page, MainPageRequest(data.name, data.data)))
|
||||
listOf(api.getMainPage(page, MainPageRequest(data.name, data.data, data.horizontalImages)))
|
||||
} ?: run {
|
||||
if (api.sequentialMainPage) {
|
||||
var first = true
|
||||
|
@ -84,11 +84,17 @@ class APIRepository(val api: MainAPI) {
|
|||
delay(api.sequentialMainPageDelay)
|
||||
first = false
|
||||
|
||||
api.getMainPage(page, MainPageRequest(data.name, data.data))
|
||||
api.getMainPage(
|
||||
page,
|
||||
MainPageRequest(data.name, data.data, data.horizontalImages)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
api.mainPage.apmap { data ->
|
||||
api.getMainPage(page, MainPageRequest(data.name, data.data))
|
||||
api.getMainPage(
|
||||
page,
|
||||
MainPageRequest(data.name, data.data, data.horizontalImages)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import androidx.core.view.isVisible
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser
|
||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||
import com.lagradost.cloudstream3.MainActivity.Companion.afterRepositoryLoadedEvent
|
||||
import com.lagradost.cloudstream3.R
|
||||
|
@ -25,7 +24,6 @@ import com.lagradost.cloudstream3.mvvm.observe
|
|||
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
||||
import com.lagradost.cloudstream3.ui.result.setText
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.downloadAllPluginsDialog
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
|
@ -34,7 +32,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
|||
import com.lagradost.cloudstream3.widget.LinearRecycleViewLayoutManager
|
||||
import kotlinx.android.synthetic.main.add_repo_input.*
|
||||
import kotlinx.android.synthetic.main.fragment_extensions.*
|
||||
import kotlinx.android.synthetic.main.fragment_extensions.list_repositories
|
||||
|
||||
const val PUBLIC_REPOSITORIES_LIST = "https://recloudstream.github.io/repos/"
|
||||
|
||||
|
@ -128,20 +125,20 @@ class ExtensionsFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
list_repositories?.setOnClickListener {
|
||||
// Open webview on tv if browser fails
|
||||
val isTv = isTvSettings()
|
||||
openBrowser(PUBLIC_REPOSITORIES_LIST, isTv, this)
|
||||
|
||||
// Set clipboard on TV because the browser might not exist or work properly
|
||||
if (isTv) {
|
||||
val serviceClipboard =
|
||||
(activity?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?)
|
||||
?: return@setOnClickListener
|
||||
val clip = ClipData.newPlainText("Repository url", PUBLIC_REPOSITORIES_LIST)
|
||||
serviceClipboard.setPrimaryClip(clip)
|
||||
}
|
||||
}
|
||||
// list_repositories?.setOnClickListener {
|
||||
// // Open webview on tv if browser fails
|
||||
// val isTv = isTvSettings()
|
||||
// openBrowser(PUBLIC_REPOSITORIES_LIST, isTv, this)
|
||||
//
|
||||
// // Set clipboard on TV because the browser might not exist or work properly
|
||||
// if (isTv) {
|
||||
// val serviceClipboard =
|
||||
// (activity?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?)
|
||||
// ?: return@setOnClickListener
|
||||
// val clip = ClipData.newPlainText("Repository url", PUBLIC_REPOSITORIES_LIST)
|
||||
// serviceClipboard.setPrimaryClip(clip)
|
||||
// }
|
||||
// }
|
||||
|
||||
observe(extensionViewModel.pluginStats) {
|
||||
when (it) {
|
||||
|
@ -200,11 +197,11 @@ class ExtensionsFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
dialog.list_repositories?.setOnClickListener {
|
||||
// Open webview on tv if browser fails
|
||||
openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this)
|
||||
dialog.dismissSafe()
|
||||
}
|
||||
// dialog.list_repositories?.setOnClickListener {
|
||||
// // Open webview on tv if browser fails
|
||||
// openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this)
|
||||
// dialog.dismissSafe()
|
||||
// }
|
||||
|
||||
// dialog.text2?.text = provider.name
|
||||
dialog.apply_btt?.setOnClickListener secondListener@{
|
||||
|
|
|
@ -12,7 +12,6 @@ import com.lagradost.cloudstream3.CommonActivity.showToast
|
|||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.apmap
|
||||
import com.lagradost.cloudstream3.mvvm.launchSafe
|
||||
import com.lagradost.cloudstream3.plugins.PluginData
|
||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||
import com.lagradost.cloudstream3.plugins.PluginManager.getPluginPath
|
||||
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
||||
|
@ -21,8 +20,8 @@ import com.lagradost.cloudstream3.ui.result.txt
|
|||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread
|
||||
import kotlinx.coroutines.launch
|
||||
import me.xdrop.fuzzywuzzy.FuzzySearch
|
||||
import java.io.File
|
||||
|
||||
typealias Plugin = Pair<String, SitePlugin>
|
||||
/**
|
||||
|
@ -47,7 +46,11 @@ class PluginsViewModel : ViewModel() {
|
|||
private val repositoryCache: MutableMap<String, List<Plugin>> = mutableMapOf()
|
||||
const val TAG = "PLG"
|
||||
|
||||
private fun isDownloaded(context: Context, pluginName: String, repositoryUrl: String): Boolean {
|
||||
private fun isDownloaded(
|
||||
context: Context,
|
||||
pluginName: String,
|
||||
repositoryUrl: String
|
||||
): Boolean {
|
||||
return getPluginPath(context, pluginName, repositoryUrl).exists()
|
||||
}
|
||||
|
||||
|
@ -73,7 +76,13 @@ class PluginsViewModel : ViewModel() {
|
|||
if (activity == null) return@ioSafe
|
||||
val plugins = getPlugins(repositoryUrl)
|
||||
|
||||
plugins.filter { plugin -> !isDownloaded(activity, plugin.second.internalName, repositoryUrl) }.also { list ->
|
||||
plugins.filter { plugin ->
|
||||
!isDownloaded(
|
||||
activity,
|
||||
plugin.second.internalName,
|
||||
repositoryUrl
|
||||
)
|
||||
}.also { list ->
|
||||
main {
|
||||
showToast(
|
||||
activity,
|
||||
|
@ -133,9 +142,13 @@ class PluginsViewModel : ViewModel() {
|
|||
if (activity == null) return@ioSafe
|
||||
val (repo, metadata) = plugin
|
||||
|
||||
val file = getPluginPath(activity, plugin.second.internalName, plugin.first)
|
||||
val file = if (isLocal) File(plugin.second.url) else getPluginPath(
|
||||
activity,
|
||||
plugin.second.internalName,
|
||||
plugin.first
|
||||
)
|
||||
|
||||
val (success, message) = if (file.exists() || isLocal) {
|
||||
val (success, message) = if (file.exists()) {
|
||||
PluginManager.deletePlugin(file) to R.string.plugin_deleted
|
||||
} else {
|
||||
PluginManager.downloadAndLoadPlugin(
|
||||
|
@ -167,7 +180,9 @@ class PluginsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
this.plugins = list
|
||||
_filteredPlugins.postValue(false to list.filterTvTypes().filterLang().sortByQuery(currentQuery))
|
||||
_filteredPlugins.postValue(
|
||||
false to list.filterTvTypes().filterLang().sortByQuery(currentQuery)
|
||||
)
|
||||
}
|
||||
|
||||
// Perhaps can be optimized?
|
||||
|
@ -175,7 +190,8 @@ class PluginsViewModel : ViewModel() {
|
|||
if (tvTypes.isEmpty()) return this
|
||||
return this.filter {
|
||||
(it.plugin.second.tvTypes?.any { type -> tvTypes.contains(type) } == true) ||
|
||||
(tvTypes.contains("Others") && (it.plugin.second.tvTypes ?: emptyList()).isEmpty())
|
||||
(tvTypes.contains("Others") && (it.plugin.second.tvTypes
|
||||
?: emptyList()).isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +215,9 @@ class PluginsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
fun updateFilteredPlugins() {
|
||||
_filteredPlugins.postValue(false to plugins.filterTvTypes().filterLang().sortByQuery(currentQuery))
|
||||
_filteredPlugins.postValue(
|
||||
false to plugins.filterTvTypes().filterLang().sortByQuery(currentQuery)
|
||||
)
|
||||
}
|
||||
|
||||
fun updatePluginList(context: Context?, repositoryUrl: String) = viewModelScope.launchSafe {
|
||||
|
@ -210,7 +228,9 @@ class PluginsViewModel : ViewModel() {
|
|||
|
||||
fun search(query: String?) {
|
||||
currentQuery = query
|
||||
_filteredPlugins.postValue(true to (filteredPlugins.value?.second?.sortByQuery(query) ?: emptyList()))
|
||||
_filteredPlugins.postValue(
|
||||
true to (filteredPlugins.value?.second?.sortByQuery(query) ?: emptyList())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -226,6 +246,8 @@ class PluginsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
plugins = downloadedPlugins
|
||||
_filteredPlugins.postValue(false to downloadedPlugins.filterTvTypes().filterLang().sortByQuery(currentQuery))
|
||||
_filteredPlugins.postValue(
|
||||
false to downloadedPlugins.filterTvTypes().filterLang().sortByQuery(currentQuery)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -7,21 +7,16 @@ import android.view.ViewGroup
|
|||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser
|
||||
import com.lagradost.cloudstream3.MainActivity.Companion.afterRepositoryLoadedEvent
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
||||
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.extensions.PUBLIC_REPOSITORIES_LIST
|
||||
import com.lagradost.cloudstream3.ui.settings.extensions.PluginsViewModel
|
||||
import com.lagradost.cloudstream3.ui.settings.extensions.RepoAdapter
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||
import kotlinx.android.synthetic.main.fragment_extensions.blank_repo_screen
|
||||
import kotlinx.android.synthetic.main.fragment_extensions.list_repositories
|
||||
import kotlinx.android.synthetic.main.fragment_extensions.repo_recycler_view
|
||||
import kotlinx.android.synthetic.main.fragment_setup_extensions.*
|
||||
import kotlinx.android.synthetic.main.fragment_setup_media.next_btt
|
||||
import kotlinx.android.synthetic.main.fragment_setup_media.prev_btt
|
||||
import kotlinx.android.synthetic.main.fragment_setup_media.setup_root
|
||||
|
@ -64,18 +59,19 @@ class SetupFragmentExtensions : Fragment() {
|
|||
val hasRepos = repositories.isNotEmpty()
|
||||
repo_recycler_view?.isVisible = hasRepos
|
||||
blank_repo_screen?.isVisible = !hasRepos
|
||||
view_public_repositories_button?.isVisible = hasRepos
|
||||
// view_public_repositories_button?.isVisible = hasRepos
|
||||
|
||||
if (hasRepos) {
|
||||
repo_recycler_view?.adapter = RepoAdapter(true, {}, {
|
||||
PluginsViewModel.downloadAll(activity, it.url, null)
|
||||
}).apply { updateList(repositories) }
|
||||
} else {
|
||||
list_repositories?.setOnClickListener {
|
||||
// Open webview on tv if browser fails
|
||||
openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this)
|
||||
}
|
||||
}
|
||||
// else {
|
||||
// list_repositories?.setOnClickListener {
|
||||
// // Open webview on tv if browser fails
|
||||
// openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,9 +80,9 @@ class SetupFragmentExtensions : Fragment() {
|
|||
context?.fixPaddingStatusbar(setup_root)
|
||||
val isSetup = arguments?.getBoolean(SETUP_EXTENSION_BUNDLE_IS_SETUP) ?: false
|
||||
|
||||
view_public_repositories_button?.setOnClickListener {
|
||||
openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this)
|
||||
}
|
||||
// view_public_repositories_button?.setOnClickListener {
|
||||
// openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this)
|
||||
// }
|
||||
|
||||
with(context) {
|
||||
if (this == null) return
|
||||
|
|
|
@ -28,15 +28,15 @@
|
|||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:nextFocusDown="@id/repo_name_input"
|
||||
android:id="@+id/list_repositories"
|
||||
android:nextFocusLeft="@id/apply_btt"
|
||||
android:nextFocusRight="@id/cancel_btt"
|
||||
style="@style/WhiteButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/view_public_repositories_button_short" />
|
||||
<!-- <com.google.android.material.button.MaterialButton-->
|
||||
<!-- android:nextFocusDown="@id/repo_name_input"-->
|
||||
<!-- android:id="@+id/list_repositories"-->
|
||||
<!-- android:nextFocusLeft="@id/apply_btt"-->
|
||||
<!-- android:nextFocusRight="@id/cancel_btt"-->
|
||||
<!-- style="@style/WhiteButton"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_gravity="center_vertical"-->
|
||||
<!-- android:text="@string/view_public_repositories_button_short" />-->
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
|
@ -70,7 +70,6 @@
|
|||
android:autofillHints="username"
|
||||
android:hint="@string/repository_name_hint"
|
||||
android:inputType="text"
|
||||
android:nextFocusUp="@id/list_repositories"
|
||||
android:nextFocusLeft="@id/apply_btt"
|
||||
android:nextFocusRight="@id/cancel_btt"
|
||||
android:nextFocusDown="@id/site_url_input"
|
||||
|
|
|
@ -47,12 +47,12 @@
|
|||
android:text="@string/blank_repo_message"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/list_repositories"
|
||||
style="@style/WhiteButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:nextFocusDown="@id/add_repo_button"
|
||||
android:text="@string/view_public_repositories_button" />
|
||||
<!-- <com.google.android.material.button.MaterialButton-->
|
||||
<!-- android:id="@+id/list_repositories"-->
|
||||
<!-- style="@style/WhiteButton"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:nextFocusDown="@id/add_repo_button"-->
|
||||
<!-- android:text="@string/view_public_repositories_button" />-->
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
@ -44,11 +44,11 @@
|
|||
android:text="@string/blank_repo_message"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/list_repositories"
|
||||
style="@style/WhiteButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@string/view_public_repositories_button" />
|
||||
<!-- <com.google.android.material.button.MaterialButton-->
|
||||
<!-- android:id="@+id/list_repositories"-->
|
||||
<!-- style="@style/WhiteButton"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:text="@string/view_public_repositories_button" />-->
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -68,12 +68,12 @@
|
|||
android:gravity="bottom|end"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/view_public_repositories_button"
|
||||
style="@style/WhiteButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:text="@string/add_repository" />
|
||||
<!-- <com.google.android.material.button.MaterialButton-->
|
||||
<!-- android:id="@+id/view_public_repositories_button"-->
|
||||
<!-- style="@style/WhiteButton"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_gravity="center_vertical|end"-->
|
||||
<!-- android:text="@string/add_repository" />-->
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/next_btt"
|
||||
|
|
|
@ -608,7 +608,7 @@
|
|||
<string name="plugins_disabled" formatted="true">Disabled: %d</string>
|
||||
<string name="plugins_not_downloaded" formatted="true">Not downloaded: %d</string>
|
||||
<string name="plugins_updated" formatted="true">Updated %d plugins</string>
|
||||
<string name="blank_repo_message">Add a repository to install site extensions</string>
|
||||
<string name="blank_repo_message">CloudStream has no sites installed by default. You need to install the sites from repositories.\n\nBecause of a brainless DMCA takedown by Sky Uk Limited 🤮 we cannot link the repository sites in app.\n\nJoin our discord for links or search online.</string>
|
||||
<string name="view_public_repositories_button">View community repositories</string>
|
||||
<string name="view_public_repositories_button_short">Public list</string>
|
||||
<string name="uppercase_all_subtitles">Uppercase all subtitles</string>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue