forked from recloudstream/cloudstream
		
	Merge remote-tracking branch 'origin/master'
This commit is contained in:
		
						commit
						0ea243ebb6
					
				
					 11 changed files with 565 additions and 52 deletions
				
			
		|  | @ -3,6 +3,7 @@ package com.lagradost.cloudstream3.subtitles | ||||||
| import androidx.annotation.WorkerThread | import androidx.annotation.WorkerThread | ||||||
| import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities.SubtitleEntity | import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities.SubtitleEntity | ||||||
| import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities.SubtitleSearch | import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities.SubtitleSearch | ||||||
|  | import com.lagradost.cloudstream3.syncproviders.AuthAPI | ||||||
| 
 | 
 | ||||||
| interface AbstractSubProvider { | interface AbstractSubProvider { | ||||||
|     @WorkerThread |     @WorkerThread | ||||||
|  | @ -14,4 +15,6 @@ interface AbstractSubProvider { | ||||||
|     suspend fun load(data: SubtitleEntity): String? { |     suspend fun load(data: SubtitleEntity): String? { | ||||||
|         throw NotImplementedError() |         throw NotImplementedError() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | interface AbstractSubApi : AbstractSubProvider, AuthAPI | ||||||
|  | @ -9,9 +9,11 @@ class AbstractSubtitleEntities { | ||||||
|         var lang: String = "en", |         var lang: String = "en", | ||||||
|         var data: String = "", //Id or link, depends on provider how to process |         var data: String = "", //Id or link, depends on provider how to process | ||||||
|         var type: TvType = TvType.Movie, //Movie, TV series, etc.. |         var type: TvType = TvType.Movie, //Movie, TV series, etc.. | ||||||
|  |         var source: String, | ||||||
|         var epNumber: Int? = null, |         var epNumber: Int? = null, | ||||||
|         var seasonNumber: Int? = null, |         var seasonNumber: Int? = null, | ||||||
|         var year: Int? = null |         var year: Int? = null, | ||||||
|  |         var isHearingImpaired: Boolean = false | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     data class SubtitleSearch( |     data class SubtitleSearch( | ||||||
|  |  | ||||||
|  | @ -3,10 +3,7 @@ package com.lagradost.cloudstream3.syncproviders | ||||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.getKey | import com.lagradost.cloudstream3.AcraApplication.Companion.getKey | ||||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.removeKeys | import com.lagradost.cloudstream3.AcraApplication.Companion.removeKeys | ||||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.setKey | import com.lagradost.cloudstream3.AcraApplication.Companion.setKey | ||||||
| import com.lagradost.cloudstream3.syncproviders.providers.AniListApi | import com.lagradost.cloudstream3.syncproviders.providers.* | ||||||
| import com.lagradost.cloudstream3.syncproviders.providers.MALApi |  | ||||||
| import com.lagradost.cloudstream3.syncproviders.providers.NginxApi |  | ||||||
| import com.lagradost.cloudstream3.syncproviders.providers.OpenSubtitlesApi |  | ||||||
| import java.util.concurrent.TimeUnit | import java.util.concurrent.TimeUnit | ||||||
| 
 | 
 | ||||||
| abstract class AccountManager(private val defIndex: Int) : AuthAPI { | abstract class AccountManager(private val defIndex: Int) : AuthAPI { | ||||||
|  | @ -14,6 +11,8 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI { | ||||||
|         val malApi = MALApi(0) |         val malApi = MALApi(0) | ||||||
|         val aniListApi = AniListApi(0) |         val aniListApi = AniListApi(0) | ||||||
|         val openSubtitlesApi = OpenSubtitlesApi(0) |         val openSubtitlesApi = OpenSubtitlesApi(0) | ||||||
|  |         // Removed because of cloudflare | ||||||
|  | //        val indexSubtitlesApi = IndexSubtitleApi() | ||||||
|         val nginxApi = NginxApi(0) |         val nginxApi = NginxApi(0) | ||||||
| 
 | 
 | ||||||
|         // used to login via app intent |         // used to login via app intent | ||||||
|  | @ -39,7 +38,9 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI { | ||||||
| 
 | 
 | ||||||
|         val subtitleProviders |         val subtitleProviders | ||||||
|             get() = listOf( |             get() = listOf( | ||||||
|                 openSubtitlesApi |                 openSubtitlesApi, | ||||||
|  |                 // Removed because of cloudflare | ||||||
|  | //                indexSubtitlesApi | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|         const val appString = "cloudstreamapp" |         const val appString = "cloudstreamapp" | ||||||
|  |  | ||||||
|  | @ -1,13 +1,14 @@ | ||||||
| package com.lagradost.cloudstream3.syncproviders.providers | package com.lagradost.cloudstream3.syncproviders.providers | ||||||
| 
 | 
 | ||||||
| import android.util.Log | import android.util.Log | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.TvType | ||||||
| import com.lagradost.cloudstream3.subtitles.AbstractSubProvider | import com.lagradost.cloudstream3.app | ||||||
|  | import com.lagradost.cloudstream3.imdbUrlToIdNullable | ||||||
|  | import com.lagradost.cloudstream3.subtitles.AbstractSubApi | ||||||
| import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities | import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities | ||||||
| import com.lagradost.cloudstream3.syncproviders.AuthAPI |  | ||||||
| import com.lagradost.cloudstream3.utils.SubtitleHelper | import com.lagradost.cloudstream3.utils.SubtitleHelper | ||||||
| 
 | 
 | ||||||
| class IndexSubtitleApi : AuthAPI, AbstractSubProvider { | class IndexSubtitleApi : AbstractSubApi { | ||||||
|     override val name = "IndexSubtitle" |     override val name = "IndexSubtitle" | ||||||
|     override val idPrefix = "indexsubtitle" |     override val idPrefix = "indexsubtitle" | ||||||
|     override val requiresLogin = false |     override val requiresLogin = false | ||||||
|  | @ -42,7 +43,7 @@ class IndexSubtitleApi : AuthAPI, AbstractSubProvider { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun getOrdinal(num: Int?) : String? { |     private fun getOrdinal(num: Int?): String? { | ||||||
|         return when (num) { |         return when (num) { | ||||||
|             1 -> "First" |             1 -> "First" | ||||||
|             2 -> "Second" |             2 -> "Second" | ||||||
|  | @ -83,13 +84,15 @@ class IndexSubtitleApi : AuthAPI, AbstractSubProvider { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun isRightEps(text: String, seasonNum: Int?, epNum: Int?) : Boolean { |     private fun isRightEps(text: String, seasonNum: Int?, epNum: Int?): Boolean { | ||||||
|         val FILTER_EPS_REGEX = Regex("(?i)((Chapter\\s?0?${epNum})|((Season)?\\s?0?${seasonNum}?\\s?(Episode)\\s?0?${epNum}[^0-9]))|(?i)((S?0?${seasonNum}?E0?${epNum}[^0-9])|(0?${seasonNum}[a-z]0?${epNum}[^0-9]))") |         val FILTER_EPS_REGEX = | ||||||
|  |             Regex("(?i)((Chapter\\s?0?${epNum})|((Season)?\\s?0?${seasonNum}?\\s?(Episode)\\s?0?${epNum}[^0-9]))|(?i)((S?0?${seasonNum}?E0?${epNum}[^0-9])|(0?${seasonNum}[a-z]0?${epNum}[^0-9]))") | ||||||
|         return text.contains(FILTER_EPS_REGEX) |         return text.contains(FILTER_EPS_REGEX) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun haveEps(text: String) : Boolean { |     private fun haveEps(text: String): Boolean { | ||||||
|         val HAVE_EPS_REGEX = Regex("(?i)((Chapter\\s?0?\\d)|((Season)?\\s?0?\\d?\\s?(Episode)\\s?0?\\d))|(?i)((S?0?\\d?E0?\\d)|(0?\\d[a-z]0?\\d))") |         val HAVE_EPS_REGEX = | ||||||
|  |             Regex("(?i)((Chapter\\s?0?\\d)|((Season)?\\s?0?\\d?\\s?(Episode)\\s?0?\\d))|(?i)((S?0?\\d?E0?\\d)|(0?\\d[a-z]0?\\d))") | ||||||
|         return text.contains(HAVE_EPS_REGEX) |         return text.contains(HAVE_EPS_REGEX) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -104,13 +107,18 @@ class IndexSubtitleApi : AuthAPI, AbstractSubProvider { | ||||||
| 
 | 
 | ||||||
|         val urlItems = ArrayList<String>() |         val urlItems = ArrayList<String>() | ||||||
| 
 | 
 | ||||||
|         fun cleanResources(results: MutableList<AbstractSubtitleEntities.SubtitleEntity>, name: String, link: String) { |         fun cleanResources( | ||||||
|  |             results: MutableList<AbstractSubtitleEntities.SubtitleEntity>, | ||||||
|  |             name: String, | ||||||
|  |             link: String | ||||||
|  |         ) { | ||||||
|             results.add( |             results.add( | ||||||
|                 AbstractSubtitleEntities.SubtitleEntity( |                 AbstractSubtitleEntities.SubtitleEntity( | ||||||
|                     idPrefix = idPrefix, |                     idPrefix = idPrefix, | ||||||
|                     name = name, |                     name = name, | ||||||
|                     lang = queryLang.toString(), |                     lang = queryLang.toString(), | ||||||
|                     data = link, |                     data = link, | ||||||
|  |                     source = this.name, | ||||||
|                     type = if (seasonNum > 0) TvType.TvSeries else TvType.Movie, |                     type = if (seasonNum > 0) TvType.TvSeries else TvType.Movie, | ||||||
|                     epNumber = epNum, |                     epNumber = epNum, | ||||||
|                     seasonNumber = seasonNum, |                     seasonNumber = seasonNum, | ||||||
|  | @ -152,11 +160,13 @@ class IndexSubtitleApi : AuthAPI, AbstractSubProvider { | ||||||
|                                 it.selectFirst("a")!!.attr("href") |                                 it.selectFirst("a")!!.attr("href") | ||||||
|                             ) |                             ) | ||||||
|                             val itemDoc = app.get(urlItem).document |                             val itemDoc = app.get(urlItem).document | ||||||
|                             val id = imdbUrlToIdNullable(itemDoc.selectFirst("div.d-flex span.badge.badge-primary")?.parent() |                             val id = imdbUrlToIdNullable( | ||||||
|                                     ?.attr("href"))?.toLongOrNull() |                                 itemDoc.selectFirst("div.d-flex span.badge.badge-primary")?.parent() | ||||||
|  |                                     ?.attr("href") | ||||||
|  |                             )?.toLongOrNull() | ||||||
|                             val year = itemDoc.selectFirst("div.d-flex span.badge.badge-success") |                             val year = itemDoc.selectFirst("div.d-flex span.badge.badge-success") | ||||||
|                                     ?.ownText() |                                 ?.ownText() | ||||||
|                                     ?.trim().toString() |                                 ?.trim().toString() | ||||||
|                             Log.i(TAG, "id => $id \nyear => $year||$yearNum") |                             Log.i(TAG, "id => $id \nyear => $year||$yearNum") | ||||||
|                             if (imdbId > 0) { |                             if (imdbId > 0) { | ||||||
|                                 if (id == imdbId) { |                                 if (id == imdbId) { | ||||||
|  | @ -191,12 +201,13 @@ class IndexSubtitleApi : AuthAPI, AbstractSubProvider { | ||||||
|             val request = app.get(url) |             val request = app.get(url) | ||||||
|             if (request.isSuccessful) { |             if (request.isSuccessful) { | ||||||
|                 request.document.select("div.my-3.p-3 div.media").map { block -> |                 request.document.select("div.my-3.p-3 div.media").map { block -> | ||||||
|                     if (block.select("span.d-block span[data-original-title=Language]").text().trim() |                     if (block.select("span.d-block span[data-original-title=Language]").text() | ||||||
|  |                             .trim() | ||||||
|                             .contains("$queryLang") |                             .contains("$queryLang") | ||||||
|                     ) { |                     ) { | ||||||
|                         var name = block.select("strong.text-primary").text().trim() |                         var name = block.select("strong.text-primary").text().trim() | ||||||
|                         val link = fixUrl(block.selectFirst("a")!!.attr("href")) |                         val link = fixUrl(block.selectFirst("a")!!.attr("href")) | ||||||
|                         if(seasonNum > 0) { |                         if (seasonNum > 0) { | ||||||
|                             when { |                             when { | ||||||
|                                 isRightEps(name, seasonNum, epNum) -> { |                                 isRightEps(name, seasonNum, epNum) -> { | ||||||
|                                     cleanResources(results, name, link) |                                     cleanResources(results, name, link) | ||||||
|  | @ -222,7 +233,7 @@ class IndexSubtitleApi : AuthAPI, AbstractSubProvider { | ||||||
| 
 | 
 | ||||||
|         val req = app.get(data.data) |         val req = app.get(data.data) | ||||||
| 
 | 
 | ||||||
|         if(req.isSuccessful) { |         if (req.isSuccessful) { | ||||||
|             val document = req.document |             val document = req.document | ||||||
|             val link = if (document.select("div.my-3.p-3 div.media").size == 1) { |             val link = if (document.select("div.my-3.p-3 div.media").size == 1) { | ||||||
|                 fixUrl( |                 fixUrl( | ||||||
|  | @ -230,7 +241,8 @@ class IndexSubtitleApi : AuthAPI, AbstractSubProvider { | ||||||
|                 ) |                 ) | ||||||
|             } else { |             } else { | ||||||
|                 document.select("div.my-3.p-3 div.media").mapNotNull { block -> |                 document.select("div.my-3.p-3 div.media").mapNotNull { block -> | ||||||
|                     val name = block.selectFirst("strong.d-block.text-primary")?.text()?.trim().toString() |                     val name = | ||||||
|  |                         block.selectFirst("strong.d-block.text-primary")?.text()?.trim().toString() | ||||||
|                     if (seasonNum!! > 0) { |                     if (seasonNum!! > 0) { | ||||||
|                         if (isRightEps(name, seasonNum, epNum)) { |                         if (isRightEps(name, seasonNum, epNum)) { | ||||||
|                             fixUrl(block.selectFirst("a")!!.attr("href")) |                             fixUrl(block.selectFirst("a")!!.attr("href")) | ||||||
|  |  | ||||||
|  | @ -2,22 +2,19 @@ package com.lagradost.cloudstream3.syncproviders.providers | ||||||
| 
 | 
 | ||||||
| import android.util.Log | import android.util.Log | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
|  | import com.lagradost.cloudstream3.* | ||||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.getKey | import com.lagradost.cloudstream3.AcraApplication.Companion.getKey | ||||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey | import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey | ||||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.setKey | import com.lagradost.cloudstream3.AcraApplication.Companion.setKey | ||||||
| import com.lagradost.cloudstream3.ErrorLoadingException |  | ||||||
| import com.lagradost.cloudstream3.R |  | ||||||
| import com.lagradost.cloudstream3.TvType |  | ||||||
| import com.lagradost.cloudstream3.app |  | ||||||
| import com.lagradost.cloudstream3.mvvm.logError | import com.lagradost.cloudstream3.mvvm.logError | ||||||
| import com.lagradost.cloudstream3.subtitles.AbstractSubProvider | import com.lagradost.cloudstream3.subtitles.AbstractSubApi | ||||||
| import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities | import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities | ||||||
| import com.lagradost.cloudstream3.syncproviders.AuthAPI | import com.lagradost.cloudstream3.syncproviders.AuthAPI | ||||||
| import com.lagradost.cloudstream3.syncproviders.InAppAuthAPI | import com.lagradost.cloudstream3.syncproviders.InAppAuthAPI | ||||||
| import com.lagradost.cloudstream3.syncproviders.InAppAuthAPIManager | import com.lagradost.cloudstream3.syncproviders.InAppAuthAPIManager | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils | import com.lagradost.cloudstream3.utils.AppUtils | ||||||
| 
 | 
 | ||||||
| class OpenSubtitlesApi(index: Int) : InAppAuthAPIManager(index), AbstractSubProvider { | class OpenSubtitlesApi(index: Int) : InAppAuthAPIManager(index), AbstractSubApi { | ||||||
|     override val idPrefix = "opensubtitles" |     override val idPrefix = "opensubtitles" | ||||||
|     override val name = "OpenSubtitles" |     override val name = "OpenSubtitles" | ||||||
|     override val icon = R.drawable.open_subtitles_icon |     override val icon = R.drawable.open_subtitles_icon | ||||||
|  | @ -190,6 +187,7 @@ class OpenSubtitlesApi(index: Int) : InAppAuthAPIManager(index), AbstractSubProv | ||||||
|                 val resSeasonNum = featureDetails?.seasonNumber ?: query.seasonNumber |                 val resSeasonNum = featureDetails?.seasonNumber ?: query.seasonNumber | ||||||
|                 val year = featureDetails?.year ?: query.year |                 val year = featureDetails?.year ?: query.year | ||||||
|                 val type = if ((resSeasonNum ?: 0) > 0) TvType.TvSeries else TvType.Movie |                 val type = if ((resSeasonNum ?: 0) > 0) TvType.TvSeries else TvType.Movie | ||||||
|  |                 val isHearingImpaired = attr.hearing_impaired ?: false | ||||||
|                 //Log.i(TAG, "Result id/name => ${item.id} / $name") |                 //Log.i(TAG, "Result id/name => ${item.id} / $name") | ||||||
|                 item.attributes?.files?.forEach { file -> |                 item.attributes?.files?.forEach { file -> | ||||||
|                     val resultData = file.fileId?.toString() ?: "" |                     val resultData = file.fileId?.toString() ?: "" | ||||||
|  | @ -201,9 +199,11 @@ class OpenSubtitlesApi(index: Int) : InAppAuthAPIManager(index), AbstractSubProv | ||||||
|                             lang = lang, |                             lang = lang, | ||||||
|                             data = resultData, |                             data = resultData, | ||||||
|                             type = type, |                             type = type, | ||||||
|  |                             source = this.name, | ||||||
|                             epNumber = resEpNum, |                             epNumber = resEpNum, | ||||||
|                             seasonNumber = resSeasonNum, |                             seasonNumber = resSeasonNum, | ||||||
|                             year = year |                             year = year, | ||||||
|  |                             isHearingImpaired = isHearingImpaired | ||||||
|                         ) |                         ) | ||||||
|                     ) |                     ) | ||||||
|                 } |                 } | ||||||
|  | @ -277,7 +277,8 @@ class OpenSubtitlesApi(index: Int) : InAppAuthAPIManager(index), AbstractSubProv | ||||||
|         @JsonProperty("release") var release: String? = null, |         @JsonProperty("release") var release: String? = null, | ||||||
|         @JsonProperty("url") var url: String? = null, |         @JsonProperty("url") var url: String? = null, | ||||||
|         @JsonProperty("files") var files: List<ResultFiles>? = listOf(), |         @JsonProperty("files") var files: List<ResultFiles>? = listOf(), | ||||||
|         @JsonProperty("feature_details") var featDetails: ResultFeatureDetails? = ResultFeatureDetails() |         @JsonProperty("feature_details") var featDetails: ResultFeatureDetails? = ResultFeatureDetails(), | ||||||
|  |         @JsonProperty("hearing_impaired") var hearing_impaired: Boolean? = null, | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     data class ResultFiles( |     data class ResultFiles( | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import android.view.ViewGroup | ||||||
| import android.widget.* | import android.widget.* | ||||||
| import androidx.activity.result.contract.ActivityResultContracts | import androidx.activity.result.contract.ActivityResultContracts | ||||||
| import androidx.appcompat.app.AlertDialog | import androidx.appcompat.app.AlertDialog | ||||||
|  | import androidx.core.content.ContextCompat | ||||||
| import androidx.core.view.isGone | import androidx.core.view.isGone | ||||||
| import androidx.core.view.isVisible | import androidx.core.view.isVisible | ||||||
| import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||||
|  | @ -216,25 +217,80 @@ class GeneratorPlayer : FullScreenPlayer() { | ||||||
|         dismissCallback: (() -> Unit) |         dismissCallback: (() -> Unit) | ||||||
|     ) { |     ) { | ||||||
|         val providers = subsProviders |         val providers = subsProviders | ||||||
|  |         val isSingleProvider = subsProviders.size == 1 | ||||||
| 
 | 
 | ||||||
|         val dialog = Dialog(context, R.style.AlertDialogCustomBlack) |         val dialog = Dialog(context, R.style.AlertDialogCustomBlack) | ||||||
|         dialog.setContentView(R.layout.dialog_online_subtitles) |         dialog.setContentView(R.layout.dialog_online_subtitles) | ||||||
| 
 | 
 | ||||||
|  |         var currentSubtitles: List<AbstractSubtitleEntities.SubtitleEntity> = emptyList() | ||||||
|  |         var currentSubtitle: AbstractSubtitleEntities.SubtitleEntity? = null | ||||||
|  | 
 | ||||||
|  |         fun getName(entry: AbstractSubtitleEntities.SubtitleEntity, withLanguage: Boolean): String { | ||||||
|  |             if (entry.lang.isBlank() || !withLanguage) { | ||||||
|  |                 return entry.name | ||||||
|  |             } | ||||||
|  |             val language = fromTwoLettersToLanguage(entry.lang.trim()) ?: entry.lang | ||||||
|  |             return "$language ${entry.name}" | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         val layout = R.layout.sort_bottom_single_choice_double_text | ||||||
|         val arrayAdapter = |         val arrayAdapter = | ||||||
|             ArrayAdapter<String>(dialog.context, R.layout.sort_bottom_single_choice) |             object : ArrayAdapter<AbstractSubtitleEntities.SubtitleEntity>(dialog.context, layout) { | ||||||
|  |                 fun setHearingImpairedIcon( | ||||||
|  |                     imageViewEnd: ImageView?, | ||||||
|  |                     position: Int | ||||||
|  |                 ) { | ||||||
|  |                     if (imageViewEnd == null) return | ||||||
|  |                     val isHearingImpaired = | ||||||
|  |                         currentSubtitles.getOrNull(position)?.isHearingImpaired ?: false | ||||||
|  | 
 | ||||||
|  |                     val drawableEnd = if (isHearingImpaired) { | ||||||
|  |                         ContextCompat.getDrawable( | ||||||
|  |                             context, | ||||||
|  |                             R.drawable.ic_baseline_hearing_24 | ||||||
|  |                         )?.apply { | ||||||
|  |                             setTint( | ||||||
|  |                                 ContextCompat.getColor( | ||||||
|  |                                     context, | ||||||
|  |                                     R.color.textColor | ||||||
|  |                                 ) | ||||||
|  |                             ) | ||||||
|  |                         } | ||||||
|  |                     } else null | ||||||
|  | 
 | ||||||
|  |                     imageViewEnd.setImageDrawable(drawableEnd) | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { | ||||||
|  |                     val view = convertView ?: LayoutInflater.from(context) | ||||||
|  |                         .inflate(layout, null) | ||||||
|  | 
 | ||||||
|  |                     val item = getItem(position) | ||||||
|  | 
 | ||||||
|  |                     val mainTextView = view.findViewById<TextView>(R.id.main_text) | ||||||
|  |                     val secondaryTextView = view.findViewById<TextView>(R.id.secondary_text) | ||||||
|  |                     val drawableEnd = view.findViewById<ImageView>(R.id.drawable_end) | ||||||
|  | 
 | ||||||
|  |                     mainTextView?.text = item?.let { getName(it, false) } | ||||||
|  | 
 | ||||||
|  |                     val language = item?.let { fromTwoLettersToLanguage(it.lang.trim()) ?: it.lang } ?: "" | ||||||
|  |                     val providerSuffix = if (isSingleProvider || item == null) "" else " · ${item.source}" | ||||||
|  |                     secondaryTextView?.text = language + providerSuffix | ||||||
|  | 
 | ||||||
|  |                     setHearingImpairedIcon(drawableEnd, position) | ||||||
|  |                     return view | ||||||
|  |                 } | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|         dialog.show() |         dialog.show() | ||||||
| 
 |  | ||||||
|         dialog.cancel_btt.setOnClickListener { |         dialog.cancel_btt.setOnClickListener { | ||||||
|             dialog.dismissSafe() |             dialog.dismissSafe() | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         dialog.subtitle_adapter.choiceMode = AbsListView.CHOICE_MODE_SINGLE |         dialog.subtitle_adapter.choiceMode = AbsListView.CHOICE_MODE_SINGLE | ||||||
|         dialog.subtitle_adapter.adapter = arrayAdapter |         dialog.subtitle_adapter.adapter = arrayAdapter | ||||||
|         val adapter = dialog.subtitle_adapter.adapter as? ArrayAdapter<String> |         val adapter = | ||||||
| 
 |             dialog.subtitle_adapter.adapter as? ArrayAdapter<AbstractSubtitleEntities.SubtitleEntity> | ||||||
|         var currentSubtitles: List<AbstractSubtitleEntities.SubtitleEntity> = emptyList() |  | ||||||
|         var currentSubtitle: AbstractSubtitleEntities.SubtitleEntity? = null |  | ||||||
| 
 | 
 | ||||||
|         dialog.subtitle_adapter.setOnItemClickListener { _, _, position, _ -> |         dialog.subtitle_adapter.setOnItemClickListener { _, _, position, _ -> | ||||||
|             currentSubtitle = currentSubtitles.getOrNull(position) ?: return@setOnItemClickListener |             currentSubtitle = currentSubtitles.getOrNull(position) ?: return@setOnItemClickListener | ||||||
|  | @ -242,19 +298,11 @@ class GeneratorPlayer : FullScreenPlayer() { | ||||||
| 
 | 
 | ||||||
|         var currentLanguageTwoLetters: String = getAutoSelectLanguageISO639_1() |         var currentLanguageTwoLetters: String = getAutoSelectLanguageISO639_1() | ||||||
| 
 | 
 | ||||||
|         fun getName(entry: AbstractSubtitleEntities.SubtitleEntity): String { |  | ||||||
|             return if (entry.lang.isBlank()) { |  | ||||||
|                 entry.name |  | ||||||
|             } else { |  | ||||||
|                 val language = fromTwoLettersToLanguage(entry.lang.trim()) ?: entry.lang |  | ||||||
|                 return "$language ${entry.name}" |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         fun setSubtitlesList(list: List<AbstractSubtitleEntities.SubtitleEntity>) { |         fun setSubtitlesList(list: List<AbstractSubtitleEntities.SubtitleEntity>) { | ||||||
|             currentSubtitles = list |             currentSubtitles = list | ||||||
|             adapter?.clear() |             adapter?.clear() | ||||||
|             adapter?.addAll(currentSubtitles.map { getName(it) }) |             adapter?.addAll(currentSubtitles) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         val currentTempMeta = getMetaData() |         val currentTempMeta = getMetaData() | ||||||
|  | @ -328,7 +376,7 @@ class GeneratorPlayer : FullScreenPlayer() { | ||||||
|                     ioSafe { |                     ioSafe { | ||||||
|                         val url = api.load(currentSubtitle) ?: return@ioSafe |                         val url = api.load(currentSubtitle) ?: return@ioSafe | ||||||
|                         val subtitle = SubtitleData( |                         val subtitle = SubtitleData( | ||||||
|                             name = getName(currentSubtitle), |                             name = getName(currentSubtitle, true), | ||||||
|                             url = url, |                             url = url, | ||||||
|                             origin = SubtitleOrigin.URL, |                             origin = SubtitleOrigin.URL, | ||||||
|                             mimeType = url.toSubtitleMimeType() |                             mimeType = url.toSubtitleMimeType() | ||||||
|  | @ -846,7 +894,11 @@ class GeneratorPlayer : FullScreenPlayer() { | ||||||
|                             if (season == null) |                             if (season == null) | ||||||
|                                 " - ${ctx.getString(R.string.episode)} $episode" |                                 " - ${ctx.getString(R.string.episode)} $episode" | ||||||
|                             else |                             else | ||||||
|                                 " \"${ctx.getString(R.string.season_short)}${season}:${ctx.getString(R.string.episode_short)}${episode}\"" |                                 " \"${ctx.getString(R.string.season_short)}${season}:${ | ||||||
|  |                                     ctx.getString( | ||||||
|  |                                         R.string.episode_short | ||||||
|  |                                     ) | ||||||
|  |                                 }${episode}\"" | ||||||
|                         else "") + if (subName.isNullOrBlank() || subName == headerName) "" else " - $subName" |                         else "") + if (subName.isNullOrBlank() || subName == headerName) "" else " - $subName" | ||||||
|             } else { |             } else { | ||||||
|                 "" |                 "" | ||||||
|  |  | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | <vector android:height="24dp" android:tint="@color/check_selection_color" | ||||||
|  |     android:viewportHeight="24" android:viewportWidth="24" | ||||||
|  |     android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  |     <path android:fillColor="@android:color/white" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/> | ||||||
|  | </vector> | ||||||
							
								
								
									
										5
									
								
								app/src/main/res/drawable/ic_baseline_hearing_24.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/drawable/ic_baseline_hearing_24.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | <vector android:height="24dp" android:tint="?attr/white" | ||||||
|  |     android:viewportHeight="24" android:viewportWidth="24" | ||||||
|  |     android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  |     <path android:fillColor="@android:color/white" android:pathData="M17,20c-0.29,0 -0.56,-0.06 -0.76,-0.15 -0.71,-0.37 -1.21,-0.88 -1.71,-2.38 -0.51,-1.56 -1.47,-2.29 -2.39,-3 -0.79,-0.61 -1.61,-1.24 -2.32,-2.53C9.29,10.98 9,9.93 9,9c0,-2.8 2.2,-5 5,-5s5,2.2 5,5h2c0,-3.93 -3.07,-7 -7,-7S7,5.07 7,9c0,1.26 0.38,2.65 1.07,3.9 0.91,1.65 1.98,2.48 2.85,3.15 0.81,0.62 1.39,1.07 1.71,2.05 0.6,1.82 1.37,2.84 2.73,3.55 0.51,0.23 1.07,0.35 1.64,0.35 2.21,0 4,-1.79 4,-4h-2c0,1.1 -0.9,2 -2,2zM7.64,2.64L6.22,1.22C4.23,3.21 3,5.96 3,9s1.23,5.79 3.22,7.78l1.41,-1.41C6.01,13.74 5,11.49 5,9s1.01,-4.74 2.64,-6.36zM11.5,9c0,1.38 1.12,2.5 2.5,2.5s2.5,-1.12 2.5,-2.5 -1.12,-2.5 -2.5,-2.5 -2.5,1.12 -2.5,2.5z"/> | ||||||
|  | </vector> | ||||||
|  | @ -0,0 +1,69 @@ | ||||||
|  | <!--<CheckedTextView | ||||||
|  |         xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" | ||||||
|  |         android:id="@android:id/text1" | ||||||
|  |         android:layout_width="match_parent" | ||||||
|  |         android:layout_height="?android:attr/listPreferredItemHeightSmall" | ||||||
|  |         android:textAppearance="?android:attr/textAppearanceListItemSmall" | ||||||
|  |         android:gravity="center_vertical" | ||||||
|  |         android:textColor="?attr/textColor" | ||||||
|  |         tools:text="Example Text" | ||||||
|  |         android:background="?attr/bitDarkerGrayBackground" | ||||||
|  |         android:checkMark="?android:attr/listChoiceIndicatorSingle" | ||||||
|  |         android:paddingStart="?android:attr/listPreferredItemPaddingStart" | ||||||
|  |         android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"/> | ||||||
|  | --> | ||||||
|  | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||||
|  |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|  |     android:layout_width="match_parent" | ||||||
|  |     android:layout_height="wrap_content" | ||||||
|  |     android:minHeight="?android:attr/listPreferredItemHeightSmall" | ||||||
|  |     android:paddingVertical="10dp" | ||||||
|  |     android:orientation="horizontal"> | ||||||
|  | 
 | ||||||
|  |     <ImageView | ||||||
|  |         android:id="@+id/drawable_start" | ||||||
|  |         android:layout_width="wrap_content" | ||||||
|  |         android:layout_height="match_parent" | ||||||
|  |         android:layout_gravity="center" | ||||||
|  |         android:paddingHorizontal="10dp" | ||||||
|  |         android:src="@drawable/ic_baseline_check_24_listview" | ||||||
|  |         tools:ignore="ContentDescription" /> | ||||||
|  | 
 | ||||||
|  |     <LinearLayout | ||||||
|  |         android:layout_width="match_parent" | ||||||
|  |         android:layout_height="match_parent" | ||||||
|  |         android:layout_weight="1" | ||||||
|  |         android:gravity="center" | ||||||
|  |         android:orientation="vertical"> | ||||||
|  | 
 | ||||||
|  |         <TextView | ||||||
|  |             android:id="@+id/main_text" | ||||||
|  |             style="@style/CheckLabel" | ||||||
|  |             android:foreground="@null" | ||||||
|  |             android:minHeight="@null" | ||||||
|  |             app:drawableStartCompat="@null" | ||||||
|  |             tools:text="The Boys - S01E02 Cherry" /> | ||||||
|  | 
 | ||||||
|  |         <TextView | ||||||
|  |             android:id="@+id/secondary_text" | ||||||
|  |             style="@style/CheckLabel" | ||||||
|  |             android:foreground="@null" | ||||||
|  |             android:minHeight="@null" | ||||||
|  |             android:padding="0dp" | ||||||
|  |             android:textSize="12sp" | ||||||
|  |             app:drawableStartCompat="@null" | ||||||
|  |             tools:text="English · OpenSubtitles" /> | ||||||
|  |     </LinearLayout> | ||||||
|  | 
 | ||||||
|  |     <ImageView | ||||||
|  |         tools:src="@drawable/ic_baseline_hearing_24" | ||||||
|  |         android:id="@+id/drawable_end" | ||||||
|  |         android:layout_width="wrap_content" | ||||||
|  |         android:layout_height="match_parent" | ||||||
|  |         android:layout_gravity="center" | ||||||
|  |         android:layout_weight="0" | ||||||
|  |         android:paddingHorizontal="10dp" | ||||||
|  |         tools:ignore="ContentDescription" /> | ||||||
|  | </LinearLayout> | ||||||
|  | 
 | ||||||
							
								
								
									
										362
									
								
								app/src/main/res/values-vi/array.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										362
									
								
								app/src/main/res/values-vi/array.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,362 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <resources xmlns:tools="http://schemas.android.com/tools"> | ||||||
|  |     <array name="cast_mini_controller_control_buttons"> | ||||||
|  |         <item>@id/cast_button_type_rewind_30_seconds</item> | ||||||
|  |         <item>@id/cast_button_type_play_pause_toggle</item> | ||||||
|  |         <item>@id/cast_button_type_forward_30_seconds</item> | ||||||
|  |     </array> | ||||||
|  |     <array name="cast_expanded_controller_control_buttons"> | ||||||
|  |         <!-- Fake sources button --> | ||||||
|  |         <item>@id/cast_button_type_rewind_30_seconds</item> | ||||||
|  |         <item>@id/cast_button_type_rewind_30_seconds</item> | ||||||
|  |         <item>@id/cast_button_type_forward_30_seconds</item> | ||||||
|  |         <!-- Actually fake to make the skip op button the same style --> | ||||||
|  |         <item>@id/cast_button_type_forward_30_seconds</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="dns_pref"> | ||||||
|  |         <item>@string/none</item> | ||||||
|  |         <item>Google</item> | ||||||
|  |         <item>Cloudflare</item> | ||||||
|  |         <!--        <item>OpenDns</item>--> | ||||||
|  |         <item>AdGuard</item> | ||||||
|  |     </array> | ||||||
|  |     <array name="dns_pref_values"> | ||||||
|  |         <item>0</item> | ||||||
|  |         <item>1</item> | ||||||
|  |         <item>2</item> | ||||||
|  |         <!--        <item>3</item>--> | ||||||
|  |         <item>4</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="media_type_pref"> | ||||||
|  |         <item>Tất cả</item> | ||||||
|  |         <item>Phim lẻ và Phim bộ</item> | ||||||
|  |         <item>Anime</item> | ||||||
|  |         <item>Phim tài liệu</item> | ||||||
|  |     </array> | ||||||
|  |     <array name="media_type_pref_values"> | ||||||
|  |         <item>0</item> | ||||||
|  |         <item>1</item> | ||||||
|  |         <item>2</item> | ||||||
|  |         <item>3</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="limit_title_rez_pref_names"> | ||||||
|  |         <item>@string/resolution_and_title</item> | ||||||
|  |         <item>@string/title</item> | ||||||
|  |         <item>@string/resolution</item> | ||||||
|  |         <item>@string/none</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="limit_title_rez_pref_values"> | ||||||
|  |         <item>3</item> | ||||||
|  |         <item>2</item> | ||||||
|  |         <item>1</item> | ||||||
|  |         <item>0</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="limit_title_pref_names"> | ||||||
|  |         <item>@string/none</item> | ||||||
|  |         <item>16 ký tự</item> | ||||||
|  |         <item>32 ký tự</item> | ||||||
|  |         <item>64 ký tự</item> | ||||||
|  |         <item>128 ký tự</item> | ||||||
|  |         <item>Ẩn Tiêu đề</item> | ||||||
|  |     </array> | ||||||
|  |     <array name="limit_title_pref_values"> | ||||||
|  |         <item>0</item> | ||||||
|  |         <item>16</item> | ||||||
|  |         <item>32</item> | ||||||
|  |         <item>64</item> | ||||||
|  |         <item>128</item> | ||||||
|  |         <item>-1</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="skip_sec_values"> | ||||||
|  |         <item>5</item> | ||||||
|  |         <item>10</item> | ||||||
|  |         <item>15</item> | ||||||
|  |         <item>20</item> | ||||||
|  |         <item>25</item> | ||||||
|  |         <item>30</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="video_buffer_length_names"> | ||||||
|  |         <item>@string/automatic</item> | ||||||
|  |         <item>1 phút</item> | ||||||
|  |         <item>1 phút 30 giây</item> | ||||||
|  |         <item>2 phút</item> | ||||||
|  |         <item>2 phút 30 giây</item> | ||||||
|  |         <item>3 phút</item> | ||||||
|  |         <item>3 phút 30 giây</item> | ||||||
|  |         <item>4 phút</item> | ||||||
|  |         <item>5 phút</item> | ||||||
|  |         <item>6 phút</item> | ||||||
|  |         <item>7 phút</item> | ||||||
|  |         <item>8 phút</item> | ||||||
|  |         <item>9 phút</item> | ||||||
|  |         <item>10 phút</item> | ||||||
|  |         <item>15 phút</item> | ||||||
|  |         <item>20 phút</item> | ||||||
|  |         <item>30 phút</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="video_buffer_length_values"> | ||||||
|  |         <item>0</item> | ||||||
|  |         <item>60</item> | ||||||
|  |         <item>90</item> | ||||||
|  |         <item>120</item> | ||||||
|  |         <item>150</item> | ||||||
|  |         <item>180</item> | ||||||
|  |         <item>210</item> | ||||||
|  |         <item>240</item> | ||||||
|  |         <item>300</item> | ||||||
|  |         <item>360</item> | ||||||
|  |         <item>420</item> | ||||||
|  |         <item>480</item> | ||||||
|  |         <item>540</item> | ||||||
|  |         <item>600</item> | ||||||
|  |         <item>900</item> | ||||||
|  |         <item>1200</item> | ||||||
|  |         <item>1800</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="video_buffer_size_names"> | ||||||
|  |         <item>@string/automatic</item> | ||||||
|  |         <item>10MB</item> | ||||||
|  |         <item>20MB</item> | ||||||
|  |         <item>30MB</item> | ||||||
|  |         <item>40MB</item> | ||||||
|  |         <item>50MB</item> | ||||||
|  |         <item>60MB</item> | ||||||
|  |         <item>70MB</item> | ||||||
|  |         <item>80MB</item> | ||||||
|  |         <item>90MB</item> | ||||||
|  |         <item>100MB</item> | ||||||
|  |         <item>150MB</item> | ||||||
|  |         <item>200MB</item> | ||||||
|  |         <item>250MB</item> | ||||||
|  |         <item>300MB</item> | ||||||
|  |         <item>350MB</item> | ||||||
|  |         <item>400MB</item> | ||||||
|  |         <item>450MB</item> | ||||||
|  |         <item>500MB</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="video_buffer_size_values"> | ||||||
|  |         <item>0</item> | ||||||
|  |         <item>10</item> | ||||||
|  |         <item>20</item> | ||||||
|  |         <item>30</item> | ||||||
|  |         <item>40</item> | ||||||
|  |         <item>50</item> | ||||||
|  |         <item>60</item> | ||||||
|  |         <item>70</item> | ||||||
|  |         <item>80</item> | ||||||
|  |         <item>90</item> | ||||||
|  |         <item>100</item> | ||||||
|  |         <item>150</item> | ||||||
|  |         <item>200</item> | ||||||
|  |         <item>250</item> | ||||||
|  |         <item>300</item> | ||||||
|  |         <item>350</item> | ||||||
|  |         <item>400</item> | ||||||
|  |         <item>450</item> | ||||||
|  |         <item>500</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="poster_ui_options"> | ||||||
|  |         <item>@string/show_hd</item> | ||||||
|  |         <item>@string/show_dub</item> | ||||||
|  |         <item>@string/show_sub</item> | ||||||
|  |         <item>@string/show_title</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="poster_ui_options_values"> | ||||||
|  |         <item>@string/show_hd_key</item> | ||||||
|  |         <item>@string/show_dub_key</item> | ||||||
|  |         <item>@string/show_sub_key</item> | ||||||
|  |         <item>@string/show_title_key</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="episode_long_click_options"> | ||||||
|  |         <item>@string/episode_action_chromecast_episode</item> | ||||||
|  |         <item>@string/episode_action_chromecast_mirror</item> | ||||||
|  |         <item>@string/episode_action_play_in_app</item> | ||||||
|  |         <item>@string/episode_action_play_in_vlc</item> | ||||||
|  |         <item>@string/episode_action_play_in_browser</item> | ||||||
|  |         <item>@string/episode_action_copy_link</item> | ||||||
|  |         <item>@string/episode_action_auto_download</item> | ||||||
|  |         <item>@string/episode_action_download_mirror</item> | ||||||
|  |         <item>@string/episode_action_download_subtitle</item> | ||||||
|  |         <item>@string/episode_action_reload_links</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="episode_long_click_options_values"> | ||||||
|  |         <item>4</item> | ||||||
|  |         <item>5</item> | ||||||
|  |         <item>1</item> | ||||||
|  |         <item>2</item> | ||||||
|  |         <item>3</item> | ||||||
|  |         <item>9</item> | ||||||
|  |         <item>6</item> | ||||||
|  |         <item>7</item> | ||||||
|  |         <item>13</item> | ||||||
|  |         <item>8</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="app_layout"> | ||||||
|  |         <item>@string/automatic</item> | ||||||
|  |         <item>@string/phone_layout</item> | ||||||
|  |         <item>@string/tv_layout</item> | ||||||
|  |         <item>@string/emulator_layout</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <array name="app_layout_values"> | ||||||
|  |         <item>-1</item> | ||||||
|  |         <item>0</item> | ||||||
|  |         <item>1</item> | ||||||
|  |         <item>2</item> | ||||||
|  |     </array> | ||||||
|  | 
 | ||||||
|  |     <string-array name="themes_overlay_names"> | ||||||
|  |         <item>Mặc định</item> | ||||||
|  |         <item>Hồng nhạt</item> | ||||||
|  |         <item>Xanh lam đậm</item> | ||||||
|  |         <item>Nâu sẫm</item> | ||||||
|  |         <item>Xanh lục</item> | ||||||
|  |         <item>Xám</item> | ||||||
|  |         <item>Trắng</item> | ||||||
|  |         <item>Nâu</item> | ||||||
|  |         <item>Xanh lục nhạt</item> | ||||||
|  |         <item>Đỏ</item> | ||||||
|  |         <item>Tím</item> | ||||||
|  |         <item>Xanh lam</item> | ||||||
|  |         <item>Xanh lam nhạt</item> | ||||||
|  |         <item>Vàng</item> | ||||||
|  |         <item>Hồng</item> | ||||||
|  |         <item>Hồng đậm</item> | ||||||
|  |     </string-array> | ||||||
|  |     <string-array name="themes_overlay_names_values"> | ||||||
|  |         <item>Normal</item> | ||||||
|  |         <item>CarnationPink</item> | ||||||
|  |         <item>DarkGreen</item> | ||||||
|  |         <item>Maroon</item> | ||||||
|  |         <item>NavyBlue</item> | ||||||
|  |         <item>Grey</item> | ||||||
|  |         <item>White</item> | ||||||
|  |         <item>Brown</item> | ||||||
|  |         <item>Blue</item> | ||||||
|  |         <item>Red</item> | ||||||
|  |         <item>Purple</item> | ||||||
|  |         <item>Green</item> | ||||||
|  |         <item>GreenApple</item> | ||||||
|  |         <item>Banana</item> | ||||||
|  |         <item>Party</item> | ||||||
|  |         <item>Pink</item> | ||||||
|  |     </string-array> | ||||||
|  | 
 | ||||||
|  |     <string-array name="themes_names"> | ||||||
|  |         <item>Tối</item> | ||||||
|  |         <item>Xám</item> | ||||||
|  |         <item>Amoled</item> | ||||||
|  |         <item>Flashbang</item> | ||||||
|  |     </string-array> | ||||||
|  |     <string-array name="themes_names_values"> | ||||||
|  |         <item>AmoledLight</item> | ||||||
|  |         <item>Black</item> | ||||||
|  |         <item>Amoled</item> | ||||||
|  |         <item>Light</item> | ||||||
|  |     </string-array> | ||||||
|  | 
 | ||||||
|  |     <!--https://github.com/videolan/vlc-android/blob/72ccfb93db027b49855760001d1a930fa657c5a8/application/resources/src/main/res/values/arrays.xml#L266--> | ||||||
|  |     <string-array name="subtitles_encoding_list" tools:ignore="TypographyDashes"> | ||||||
|  |         <item>@string/automatic</item> | ||||||
|  |         <item>Universal (UTF-8)</item> | ||||||
|  |         <item>Universal (UTF-16)</item> | ||||||
|  |         <item>Universal (big endian UTF-16)</item> | ||||||
|  |         <item>Universal (little endian UTF-16)</item> | ||||||
|  |         <item>Universal, Chinese (GB18030)</item> | ||||||
|  |         <item>Western European (Latin-9)</item> | ||||||
|  |         <item>Western European (Windows-1252)</item> | ||||||
|  |         <item>Western European (IBM 00850)</item> | ||||||
|  |         <item>Eastern European (Latin-2)</item> | ||||||
|  |         <item>Eastern European (Windows-1250)</item> | ||||||
|  |         <item>Esperanto (Latin-3)</item> | ||||||
|  |         <item>Nordic (Latin-6)</item> | ||||||
|  |         <item>Cyrillic (Windows-1251)</item> | ||||||
|  |         <item>Russian (KOI8-R)</item> | ||||||
|  |         <item>Ukrainian (KOI8-U)</item> | ||||||
|  |         <item>Arabic (ISO 8859-6)</item> | ||||||
|  |         <item>Arabic (Windows-1256)</item> | ||||||
|  |         <item>Greek (ISO 8859-7)</item> | ||||||
|  |         <item>Greek (Windows-1253)</item> | ||||||
|  |         <item>Hebrew (ISO 8859-8)</item> | ||||||
|  |         <item>Hebrew (Windows-1255)</item> | ||||||
|  |         <item>Turkish (ISO 8859-9)</item> | ||||||
|  |         <item>Turkish (Windows-1254)</item> | ||||||
|  |         <item>Thai (TIS 620-2533/ISO 8859-11)</item> | ||||||
|  |         <item>Thai (Windows-874)</item> | ||||||
|  |         <item>Baltic (Latin-7)</item> | ||||||
|  |         <item>Baltic (Windows-1257)</item> | ||||||
|  |         <item>Celtic (Latin-8)</item> | ||||||
|  |         <item>South-Eastern European (Latin-10)</item> | ||||||
|  |         <item>Simplified Chinese (ISO-2022-CN-EXT)</item> | ||||||
|  |         <item>Simplified Chinese Unix (EUC-CN)</item> | ||||||
|  |         <item>Japanese (7-bits JIS/ISO-2022-JP-2)</item> | ||||||
|  |         <item>Japanese Unix (EUC-JP)</item> | ||||||
|  |         <item>Japanese (Shift JIS)</item> | ||||||
|  |         <item>Korean (EUC-KR/CP949)</item> | ||||||
|  |         <item>Korean (ISO-2022-KR)</item> | ||||||
|  |         <item>Traditional Chinese (Big5)</item> | ||||||
|  |         <item>Traditional Chinese Unix (EUC-TW)</item> | ||||||
|  |         <item>Hong-Kong Supplementary (HKSCS)</item> | ||||||
|  |         <item>Vietnamese (VISCII)</item> | ||||||
|  |         <item>Vietnamese (Windows-1258)</item> | ||||||
|  |     </string-array> | ||||||
|  |     <string-array name="subtitles_encoding_values" translatable="false" tools:ignore="TypographyDashes"> | ||||||
|  |         <item></item> | ||||||
|  |         <item>UTF-8</item> | ||||||
|  |         <item>UTF-16</item> | ||||||
|  |         <item>UTF-16BE</item> | ||||||
|  |         <item>UTF-16LE</item> | ||||||
|  |         <item>GB18030</item> | ||||||
|  |         <item>ISO-8859-15</item> | ||||||
|  |         <item>Windows-1252</item> | ||||||
|  |         <item>IBM850</item> | ||||||
|  |         <item>ISO-8859-2</item> | ||||||
|  |         <item>Windows-1250</item> | ||||||
|  |         <item>ISO-8859-3</item> | ||||||
|  |         <item>ISO-8859-10</item> | ||||||
|  |         <item>Windows-1251</item> | ||||||
|  |         <item>KOI8-R</item> | ||||||
|  |         <item>KOI8-U</item> | ||||||
|  |         <item>ISO-8859-6</item> | ||||||
|  |         <item>Windows-1256</item> | ||||||
|  |         <item>ISO-8859-7</item> | ||||||
|  |         <item>Windows-1253</item> | ||||||
|  |         <item>ISO-8859-8</item> | ||||||
|  |         <item>Windows-1255</item> | ||||||
|  |         <item>ISO-8859-9</item> | ||||||
|  |         <item>Windows-1254</item> | ||||||
|  |         <item>ISO-8859-11</item> | ||||||
|  |         <item>Windows-874</item> | ||||||
|  |         <item>ISO-8859-13</item> | ||||||
|  |         <item>Windows-1257</item> | ||||||
|  |         <item>ISO-8859-14</item> | ||||||
|  |         <item>ISO-8859-16</item> | ||||||
|  |         <item>ISO-2022-CN-EXT</item> | ||||||
|  |         <item>EUC-CN</item> | ||||||
|  |         <item>ISO-2022-JP-2</item> | ||||||
|  |         <item>EUC-JP</item> | ||||||
|  |         <item>Shift_JIS</item> | ||||||
|  |         <item>CP949</item> | ||||||
|  |         <item>ISO-2022-KR</item> | ||||||
|  |         <item>Big5</item> | ||||||
|  |         <item>ISO-2022-TW</item> | ||||||
|  |         <item>Big5-HKSCS</item> | ||||||
|  |         <item>VISCII</item> | ||||||
|  |         <item>Windows-1258</item> | ||||||
|  |     </string-array> | ||||||
|  | </resources> | ||||||
|  | @ -462,8 +462,9 @@ | ||||||
|         <item name="android:ellipsize">marquee</item> |         <item name="android:ellipsize">marquee</item> | ||||||
|         <item name="android:foreground">?attr/selectableItemBackgroundBorderless</item> |         <item name="android:foreground">?attr/selectableItemBackgroundBorderless</item> | ||||||
|         <item name="android:drawablePadding">20dp</item> |         <item name="android:drawablePadding">20dp</item> | ||||||
|         <item name="drawableTint">@color/check_selection_color</item> | <!--        <item name="drawableTint">@color/check_selection_color</item>--> | ||||||
|         <item name="drawableStartCompat">@drawable/ic_baseline_check_24</item> | <!--        Set color in the drawable instead of tint to allow multiple drawables--> | ||||||
|  |         <item name="drawableStartCompat">@drawable/ic_baseline_check_24_listview</item> | ||||||
|     </style> |     </style> | ||||||
| 
 | 
 | ||||||
|     <style name="BlackButton" parent="NiceButton"> |     <style name="BlackButton" parent="NiceButton"> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue