forked from recloudstream/cloudstream
search providers settings
This commit is contained in:
parent
4780935d55
commit
3290fceb47
13 changed files with 289 additions and 25 deletions
|
@ -69,6 +69,23 @@ object APIHolder {
|
|||
setOf(apis[defProvider].name)
|
||||
)?.toHashSet() ?: hashSetOf(apis[defProvider].name)
|
||||
}
|
||||
|
||||
fun Activity.getApiTypeSettings(): HashSet<TvType> {
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val list = settingsManager.getStringSet(
|
||||
this.getString(R.string.search_types_list_key),
|
||||
setOf(apis[defProvider].name)
|
||||
)
|
||||
val hashSet = HashSet<TvType>()
|
||||
hashSet.addAll(TvType.values())
|
||||
if(list.isNullOrEmpty()) return hashSet
|
||||
|
||||
val names = TvType.values().map { it.name }.toHashSet()
|
||||
val realSet = list.filter { names.contains(it) }.map { TvType.valueOf(it) }.toHashSet()
|
||||
if(realSet.isEmpty()) return hashSet
|
||||
|
||||
return realSet
|
||||
}
|
||||
}
|
||||
|
||||
/**Every provider will **not** have try catch built in, so handle exceptions when calling these functions*/
|
||||
|
@ -186,6 +203,7 @@ enum class DubStatus {
|
|||
|
||||
enum class TvType {
|
||||
Movie,
|
||||
AnimeMovie,
|
||||
TvSeries,
|
||||
Cartoon,
|
||||
Anime,
|
||||
|
@ -194,7 +212,7 @@ enum class TvType {
|
|||
|
||||
// IN CASE OF FUTURE ANIME MOVIE OR SMTH
|
||||
fun TvType.isMovieType(): Boolean {
|
||||
return this == TvType.Movie
|
||||
return this == TvType.Movie || this == TvType.AnimeMovie
|
||||
}
|
||||
|
||||
data class SubtitleFile(val lang: String, val url: String)
|
||||
|
|
|
@ -20,7 +20,7 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
|
||||
override val supportedTypes: Set<TvType>
|
||||
get() = setOf(
|
||||
TvType.Movie,
|
||||
TvType.AnimeMovie,
|
||||
TvType.Anime,
|
||||
)
|
||||
|
||||
|
@ -90,7 +90,7 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
returnValue.add(
|
||||
if (getIsMovie(href)) {
|
||||
MovieSearchResponse(
|
||||
title, href, this.name, TvType.Movie, img, null
|
||||
title, href, this.name, TvType.AnimeMovie, img, null
|
||||
)
|
||||
} else {
|
||||
AnimeSearchResponse(
|
||||
|
@ -127,7 +127,7 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
returnValue.add(
|
||||
if (getIsMovie(href)) {
|
||||
MovieSearchResponse(
|
||||
title, href, this.name, TvType.Movie, img, null
|
||||
title, href, this.name, TvType.AnimeMovie, img, null
|
||||
)
|
||||
} else {
|
||||
AnimeSearchResponse(
|
||||
|
@ -197,7 +197,7 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
episode.title,
|
||||
realSlug,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
TvType.AnimeMovie,
|
||||
episode.serversHTML,
|
||||
if (poster == null) null else fixUrl(poster),
|
||||
episode.year?.toIntOrNull(),
|
||||
|
|
|
@ -17,7 +17,7 @@ class TenshiProvider : MainAPI() {
|
|||
|
||||
fun getType(t: String): TvType {
|
||||
return if (t.contains("OVA") || t.contains("Special")) TvType.ONA
|
||||
else if (t.contains("Movie")) TvType.Movie
|
||||
else if (t.contains("Movie")) TvType.AnimeMovie
|
||||
else TvType.Anime
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ class TenshiProvider : MainAPI() {
|
|||
get() = false
|
||||
|
||||
override val supportedTypes: Set<TvType>
|
||||
get() = setOf(TvType.Anime, TvType.Movie, TvType.ONA)
|
||||
get() = setOf(TvType.Anime, TvType.AnimeMovie, TvType.ONA)
|
||||
|
||||
private fun autoLoadToken(): Boolean {
|
||||
if (token != null) return true
|
||||
|
|
|
@ -13,7 +13,7 @@ class WcoProvider : MainAPI() {
|
|||
companion object {
|
||||
fun getType(t: String): TvType {
|
||||
return if (t.contains("OVA") || t.contains("Special")) TvType.ONA
|
||||
else if (t.contains("Movie")) TvType.Movie
|
||||
else if (t.contains("Movie")) TvType.AnimeMovie
|
||||
else TvType.Anime
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class WcoProvider : MainAPI() {
|
|||
|
||||
override val supportedTypes: Set<TvType>
|
||||
get() = setOf(
|
||||
TvType.Movie,
|
||||
TvType.AnimeMovie,
|
||||
TvType.Anime,
|
||||
TvType.ONA
|
||||
)
|
||||
|
@ -91,9 +91,9 @@ class WcoProvider : MainAPI() {
|
|||
val type = i.selectFirst(".film-detail.film-detail-fix > div > span:nth-child(3)").text()
|
||||
|
||||
returnValue.add(
|
||||
if (getType(type) == TvType.Movie) {
|
||||
if (getType(type) == TvType.AnimeMovie) {
|
||||
MovieSearchResponse(
|
||||
title, href, this.name, TvType.Movie, img, year
|
||||
title, href, this.name, TvType.AnimeMovie, img, year
|
||||
)
|
||||
} else {
|
||||
AnimeSearchResponse(
|
||||
|
@ -152,9 +152,9 @@ class WcoProvider : MainAPI() {
|
|||
val type = filmInfo?.select("span")?.get(1)?.text().toString()
|
||||
if (title != "null") {
|
||||
returnValue.add(
|
||||
if (getType(type) == TvType.Movie) {
|
||||
if (getType(type) == TvType.AnimeMovie) {
|
||||
MovieSearchResponse(
|
||||
title, href, this.name, TvType.Movie, img, year
|
||||
title, href, this.name, TvType.AnimeMovie, img, year
|
||||
)
|
||||
} else {
|
||||
AnimeSearchResponse(
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
class APIRepository(val api: MainAPI) {
|
||||
companion object {
|
||||
var providersActive = HashSet<String>()
|
||||
var typesActive = HashSet<TvType>()
|
||||
}
|
||||
|
||||
val name: String get() = api.name
|
||||
|
@ -22,9 +23,10 @@ class APIRepository(val api: MainAPI) {
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun search(query: String): Resource<ArrayList<SearchResponse>> {
|
||||
suspend fun search(query: String): Resource<List<SearchResponse>> {
|
||||
return safeApiCall {
|
||||
api.search(query) ?: throw ErrorLoadingException()
|
||||
return@safeApiCall (api.search(query)
|
||||
?: throw ErrorLoadingException()).filter { typesActive.contains(it.type) }.toList()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ class HomeChildItemAdapter(
|
|||
textType?.text = when (card.type) {
|
||||
TvType.Anime -> "Anime"
|
||||
TvType.Movie -> "Movie"
|
||||
TvType.AnimeMovie -> "Movie"
|
||||
TvType.ONA -> "ONA"
|
||||
TvType.TvSeries -> "TV"
|
||||
TvType.Cartoon -> "Cartoon"
|
||||
|
|
|
@ -899,7 +899,7 @@ class ResultFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
if (d.type == TvType.Movie) {
|
||||
if (d.type.isMovieType()) {
|
||||
val hasDownloadSupport = api.hasDownloadSupport
|
||||
lateFixDownloadButton(true)
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ class SearchAdapter(
|
|||
textType?.text = when (card.type) {
|
||||
TvType.Anime -> "Anime"
|
||||
TvType.Movie -> "Movie"
|
||||
TvType.AnimeMovie -> "Movie"
|
||||
TvType.ONA -> "ONA"
|
||||
TvType.TvSeries -> "TV"
|
||||
TvType.Cartoon -> "Cartoon"
|
||||
|
|
|
@ -8,7 +8,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.*
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -16,20 +16,28 @@ import androidx.lifecycle.ViewModelProvider
|
|||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial
|
||||
import com.lagradost.cloudstream3.APIHolder.apis
|
||||
import com.lagradost.cloudstream3.APIHolder.getApiSettings
|
||||
import com.lagradost.cloudstream3.APIHolder.getApiTypeSettings
|
||||
import com.lagradost.cloudstream3.HomePageList
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.TvType
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.observe
|
||||
import com.lagradost.cloudstream3.ui.APIRepository.Companion.providersActive
|
||||
import com.lagradost.cloudstream3.ui.APIRepository.Companion.typesActive
|
||||
import com.lagradost.cloudstream3.ui.home.HomeFragment
|
||||
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.loadHomepageList
|
||||
import com.lagradost.cloudstream3.ui.home.ParentItemAdapter
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||
import com.lagradost.cloudstream3.utils.SEARCH_PROVIDER_TOGGLE
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
||||
import kotlinx.android.synthetic.main.fragment_search.*
|
||||
import java.util.HashSet
|
||||
|
||||
class SearchFragment : Fragment() {
|
||||
private lateinit var searchViewModel: SearchViewModel
|
||||
|
@ -95,10 +103,175 @@ class SearchFragment : Fragment() {
|
|||
val searchMagIcon = main_search.findViewById<ImageView>(androidx.appcompat.R.id.search_mag_icon)
|
||||
searchMagIcon.scaleX = 0.65f
|
||||
searchMagIcon.scaleY = 0.65f
|
||||
search_filter.setOnClickListener {
|
||||
search_filter.setOnClickListener { view ->
|
||||
val apiNamesSetting = activity?.getApiSettings()
|
||||
if (apiNamesSetting != null) {
|
||||
val apiNames = apis.map { it.name }
|
||||
val builder =
|
||||
AlertDialog.Builder(view.context, R.style.AlertDialogCustom).setView(R.layout.provider_list)
|
||||
|
||||
val dialog = builder.create()
|
||||
dialog.show()
|
||||
|
||||
val listView = dialog.findViewById<ListView>(R.id.listview1)!!
|
||||
val listView2 = dialog.findViewById<ListView>(R.id.listview2)!!
|
||||
val toggle = dialog.findViewById<SwitchMaterial>(R.id.toggle1)!!
|
||||
val applyButton = dialog.findViewById<TextView>(R.id.apply_btt)!!
|
||||
val cancelButton = dialog.findViewById<TextView>(R.id.cancel_btt)!!
|
||||
// val applyHolder = dialog.findViewById<LinearLayout>(R.id.apply_btt_holder)!!
|
||||
|
||||
toggle.text = getString(R.string.search_provider_text)
|
||||
|
||||
val arrayAdapter = ArrayAdapter<String>(view.context, R.layout.sort_bottom_single_choice)
|
||||
arrayAdapter.addAll(apiNames)
|
||||
|
||||
listView.adapter = arrayAdapter
|
||||
listView.choiceMode = AbsListView.CHOICE_MODE_MULTIPLE
|
||||
|
||||
val typeChoices = listOf(
|
||||
Pair("Movies", listOf(TvType.Movie)),
|
||||
Pair("TvSeries", listOf(TvType.TvSeries)),
|
||||
Pair("Cartoons", listOf(TvType.Cartoon)),
|
||||
Pair("Anime", listOf(TvType.Anime, TvType.ONA, TvType.AnimeMovie))
|
||||
)
|
||||
|
||||
val arrayAdapter2 = ArrayAdapter<String>(view.context, R.layout.sort_bottom_single_choice)
|
||||
arrayAdapter2.addAll(typeChoices.map { it.first })
|
||||
|
||||
listView2.adapter = arrayAdapter2
|
||||
listView2.choiceMode = AbsListView.CHOICE_MODE_MULTIPLE
|
||||
|
||||
|
||||
/*fun updateMulti() {
|
||||
val set = HashSet<TvType>()
|
||||
|
||||
for ((index, api) in apis.withIndex()) {
|
||||
if (listView?.checkedItemPositions[index]) {
|
||||
set.addAll(api.supportedTypes)
|
||||
}
|
||||
}
|
||||
|
||||
if (set.size == 0) {
|
||||
set.addAll(TvType.values())
|
||||
}
|
||||
|
||||
for ((index, choice) in typeChoices.withIndex()) {
|
||||
listView2?.setItemChecked(index, choice.second.any { set.contains(it) })
|
||||
}
|
||||
}*/
|
||||
|
||||
for ((index, item) in apiNames.withIndex()) {
|
||||
listView.setItemChecked(index, apiNamesSetting.contains(item))
|
||||
}
|
||||
|
||||
for ((index, item) in typeChoices.withIndex()) {
|
||||
listView2.setItemChecked(index, item.second.any { typesActive.contains(it) })
|
||||
}
|
||||
|
||||
fun toggleSearch(isOn: Boolean) {
|
||||
if (isOn) {
|
||||
listView2?.visibility = View.VISIBLE
|
||||
listView?.visibility = View.GONE
|
||||
} else {
|
||||
listView?.visibility = View.VISIBLE
|
||||
listView2?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
val defVal = context?.getKey(SEARCH_PROVIDER_TOGGLE, true) ?: true
|
||||
toggleSearch(defVal)
|
||||
|
||||
toggle.isChecked = defVal
|
||||
toggle.setOnCheckedChangeListener { _, isOn ->
|
||||
toggleSearch(isOn)
|
||||
}
|
||||
|
||||
listView.setOnItemClickListener { _, _, i, _ ->
|
||||
val types = HashSet<TvType>()
|
||||
for ((index, api) in apis.withIndex()) {
|
||||
if (listView?.checkedItemPositions[index]) {
|
||||
types.addAll(api.supportedTypes)
|
||||
}
|
||||
}
|
||||
for ((typeIndex, type) in typeChoices.withIndex()) {
|
||||
listView2.setItemChecked(typeIndex, type.second.any { types.contains(it) })
|
||||
}
|
||||
}
|
||||
|
||||
listView2.setOnItemClickListener { _, _, i, _ ->
|
||||
for ((index, api) in apis.withIndex()) {
|
||||
var isSupported = false
|
||||
|
||||
for ((typeIndex, type) in typeChoices.withIndex()) {
|
||||
if (listView2?.checkedItemPositions[typeIndex]) {
|
||||
if (api.supportedTypes.any { type.second.contains(it) }) {
|
||||
isSupported = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listView?.setItemChecked(
|
||||
index,
|
||||
isSupported
|
||||
)
|
||||
}
|
||||
|
||||
//updateMulti()
|
||||
}
|
||||
|
||||
dialog.setOnDismissListener {
|
||||
context?.setKey(SEARCH_PROVIDER_TOGGLE, toggle.isChecked ?: true)
|
||||
}
|
||||
|
||||
applyButton.setOnClickListener {
|
||||
val settingsManagerLocal = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
|
||||
val activeTypes = HashSet<TvType>()
|
||||
for ((index, name) in typeChoices.withIndex()) {
|
||||
if (listView2?.checkedItemPositions[index]) {
|
||||
activeTypes.addAll(typeChoices[index].second)
|
||||
}
|
||||
}
|
||||
|
||||
if (activeTypes.size == 0) {
|
||||
activeTypes.addAll(TvType.values())
|
||||
}
|
||||
|
||||
|
||||
val activeApis = HashSet<String>()
|
||||
for ((index, name) in apiNames.withIndex()) {
|
||||
if (listView?.checkedItemPositions[index]) {
|
||||
activeApis.add(name)
|
||||
}
|
||||
}
|
||||
|
||||
if (activeApis.size == 0) {
|
||||
activeApis.addAll(apiNames)
|
||||
}
|
||||
|
||||
val edit = settingsManagerLocal.edit()
|
||||
edit.putStringSet(
|
||||
getString(R.string.search_providers_list_key),
|
||||
activeApis
|
||||
)
|
||||
edit.putStringSet(
|
||||
getString(R.string.search_types_list_key),
|
||||
activeTypes.map { it.name }.toSet()
|
||||
)
|
||||
edit.apply()
|
||||
providersActive = activeApis
|
||||
typesActive = activeTypes
|
||||
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
cancelButton.setOnClickListener {
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
//listView.setSelection(selectedIndex)
|
||||
// listView.setItemChecked(selectedIndex, true)
|
||||
/*
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(requireContext())
|
||||
|
||||
builder.setMultiChoiceItems(
|
||||
|
@ -125,7 +298,7 @@ class SearchFragment : Fragment() {
|
|||
}
|
||||
builder.setTitle("Search Providers")
|
||||
builder.setNegativeButton("Ok") { _, _ -> }
|
||||
builder.show()
|
||||
builder.show()*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,6 +351,7 @@ class SearchFragment : Fragment() {
|
|||
|
||||
activity?.let {
|
||||
providersActive = it.getApiSettings()
|
||||
typesActive = it.getApiTypeSettings()
|
||||
}
|
||||
|
||||
main_search.setOnQueryTextFocusChangeListener { searchView, b ->
|
||||
|
|
|
@ -13,7 +13,7 @@ import kotlinx.coroutines.launch
|
|||
|
||||
data class OnGoingSearch(
|
||||
val apiName: String,
|
||||
val data: Resource<ArrayList<SearchResponse>>
|
||||
val data: Resource<List<SearchResponse>>
|
||||
)
|
||||
|
||||
class SearchViewModel : ViewModel() {
|
||||
|
@ -56,7 +56,7 @@ class SearchViewModel : ViewModel() {
|
|||
if (localSearchCounter != searchCounter) return@launch
|
||||
|
||||
val list = ArrayList<SearchResponse>()
|
||||
val nestedList = currentList.map { it.data }.filterIsInstance<Resource.Success<ArrayList<SearchResponse>>>().map { it.value }
|
||||
val nestedList = currentList.map { it.data }.filterIsInstance<Resource.Success<List<SearchResponse>>>().map { it.value }
|
||||
|
||||
// I do it this way to move the relevant search results to the top
|
||||
var index = 0
|
||||
|
|
|
@ -10,6 +10,7 @@ const val DOWNLOAD_HEADER_CACHE = "download_header_cache"
|
|||
const val DOWNLOAD_EPISODE_CACHE = "download_episode_cache"
|
||||
const val VIDEO_PLAYER_BRIGHTNESS = "video_player_alpha"
|
||||
const val HOMEPAGE_API = "home_api_used"
|
||||
const val SEARCH_PROVIDER_TOGGLE = "settings_providers_toggle"
|
||||
|
||||
const val PREFERENCES_NAME: String = "rebuild_preference"
|
||||
|
||||
|
|
65
app/src/main/res/layout/provider_list.xml
Normal file
65
app/src/main/res/layout/provider_list.xml
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?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:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:background="?attr/bitDarkerGrayBackground"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:layout_marginTop="10dp"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:textStyle="bold"
|
||||
android:textSize="20sp"
|
||||
android:textColor="?attr/textColor"
|
||||
android:id="@+id/toggle1"
|
||||
tools:text="Search" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
|
||||
</com.google.android.material.switchmaterial.SwitchMaterial>
|
||||
<ListView
|
||||
android:id="@+id/listview1"
|
||||
android:layout_marginTop="-10dp"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:paddingTop="10dp"
|
||||
tools:listitem="@layout/sort_bottom_single_choice"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_rowWeight="1"
|
||||
/>
|
||||
<ListView
|
||||
android:id="@+id/listview2"
|
||||
android:layout_marginTop="-10dp"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:paddingTop="10dp"
|
||||
tools:listitem="@layout/sort_bottom_single_choice"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_rowWeight="1"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:id="@+id/apply_btt_holder"
|
||||
android:orientation="horizontal"
|
||||
android:layout_gravity="bottom"
|
||||
android:gravity="bottom|end"
|
||||
android:layout_marginTop="-60dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/WhiteButton"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:text="@string/sort_apply"
|
||||
android:id="@+id/apply_btt"
|
||||
android:layout_width="wrap_content"
|
||||
/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/BlackButton"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:text="@string/sort_cancel"
|
||||
android:id="@+id/cancel_btt"
|
||||
android:layout_width="wrap_content"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -4,9 +4,10 @@
|
|||
<string name="title_search">Search</string>
|
||||
<string name="title_downloads">Downloads</string>
|
||||
<string name="title_settings">Settings</string>
|
||||
<string name="search_hint">Search...</string>
|
||||
<string name="search_hint">Search…</string>
|
||||
<string name="change_providers_descript">Change Providers</string>
|
||||
<string name="search_providers_list_key">search_providers_list</string>
|
||||
<string name="search_types_list_key">search_type_list</string>
|
||||
<string name="grid_format_key">grid_format</string>
|
||||
<string name="search_poster_descript">Poster</string>
|
||||
<string name="no_data">No Data</string>
|
||||
|
@ -80,4 +81,5 @@
|
|||
<string name="subs_default_reset_toast">Reset to default value</string>
|
||||
<string name="preview_background">Preview Background</string>
|
||||
<string name="subs_font">Font</string>
|
||||
<string name="search_provider_text">Search Providers</string>
|
||||
</resources>
|
Loading…
Reference in a new issue