cloudstream/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt

376 lines
15 KiB
Kotlin
Raw Normal View History

2022-06-09 13:50:55 +00:00
package com.lagradost.cloudstream3.ui.settings
import android.content.Context
2022-06-09 13:50:55 +00:00
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.view.View
2022-06-16 22:07:07 +00:00
import android.widget.Toast
2022-06-09 13:50:55 +00:00
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
2022-06-16 22:07:07 +00:00
import com.fasterxml.jackson.annotation.JsonProperty
2022-06-09 13:50:55 +00:00
import com.hippo.unifile.UniFile
2022-06-16 22:07:07 +00:00
import com.lagradost.cloudstream3.APIHolder.allProviders
2022-06-09 13:50:55 +00:00
import com.lagradost.cloudstream3.AcraApplication
2022-06-16 22:07:07 +00:00
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
import com.lagradost.cloudstream3.CommonActivity
2022-06-16 22:07:07 +00:00
import com.lagradost.cloudstream3.CommonActivity.showToast
2022-06-09 13:50:55 +00:00
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.network.initClient
import com.lagradost.cloudstream3.ui.EasterEggMonke
2022-06-09 13:50:55 +00:00
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref
2022-08-21 20:13:53 +00:00
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom
2022-06-09 13:50:55 +00:00
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
2022-06-16 22:07:07 +00:00
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog
import com.lagradost.cloudstream3.utils.SubtitleHelper
2022-06-16 22:07:07 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
2022-06-09 13:50:55 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
2022-06-16 22:07:07 +00:00
import com.lagradost.cloudstream3.utils.USER_PROVIDER_API
2022-06-09 13:50:55 +00:00
import com.lagradost.cloudstream3.utils.VideoDownloadManager
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath
2022-06-16 22:07:07 +00:00
import kotlinx.android.synthetic.main.add_remove_sites.*
import kotlinx.android.synthetic.main.add_site_input.*
2022-06-09 13:50:55 +00:00
import java.io.File
fun getCurrentLocale(context: Context): String {
val res = context.resources
// Change locale settings in the app.
// val dm = res.displayMetrics
val conf = res.configuration
2022-11-29 19:45:00 +00:00
return conf?.locale?.toString() ?: "en"
}
// idk, if you find a way of automating this it would be great
// https://www.iemoji.com/view/emoji/1794/flags/antarctica
// Emoji Character Encoding Data --> C/C++/Java Src
// https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes leave blank for auto
val appLanguages = arrayListOf(
2022-12-25 18:49:59 +00:00
/* begin language list */
Triple("", "Spanish", "es"),
Triple("", "English", "en"),
Triple("", "Viet Nam", "vi"),
Triple("", "Dutch", "nl"),
Triple("", "French", "fr"),
Triple("", "Greek", "el"),
Triple("", "Swedish", "sv"),
Triple("", "Tagalog", "tl"),
Triple("", "Polish", "pl"),
Triple("", "Hindi", "hi"),
Triple("", "Malayalam", "ml"),
Triple("", "Norsk", "no"),
Triple("", "German", "de"),
Triple("", "Arabic", "ar"),
Triple("", "Turkish", "tr"),
Triple("", "Macedonian", "mk"),
Triple("\uD83C\uDDF5\uD83C\uDDF9", "Portuguese", "pt"),
Triple("\uD83C\uDDE7\uD83C\uDDF7", "Brazilian Portuguese", "bp"),
Triple("", "Romanian", "ro"),
Triple("", "Italian", "it"),
2022-11-29 19:45:00 +00:00
Triple("", "Chinese Simplified", "zh"),
2022-12-25 18:49:59 +00:00
Triple("\uD83C\uDDF9\uD83C\uDDFC", "Chinese Traditional", "zh-TW"),
Triple("\uD83C\uDDEE\uD83C\uDDE9", "Indonesian", "in"),
Triple("", "Czech", "cs"),
2022-09-10 16:47:42 +00:00
Triple("", "Croatian", "hr"),
Triple("", "Bulgarian", "bg"),
2022-12-18 13:31:44 +00:00
Triple("", "Bengali", "bn"),
2022-12-25 18:49:59 +00:00
/* end language list */
).sortedBy { it.second } //ye, we go alphabetical, so ppl don't put their lang on top
2022-06-09 13:50:55 +00:00
class SettingsGeneral : PreferenceFragmentCompat() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setUpToolbar(R.string.category_general)
2022-08-21 20:13:53 +00:00
setPaddingBottom()
2022-06-09 13:50:55 +00:00
}
2022-06-16 22:07:07 +00:00
data class CustomSite(
@JsonProperty("parentJavaClass") // javaClass.simpleName
val parentJavaClass: String,
@JsonProperty("name")
val name: String,
@JsonProperty("url")
val url: String,
@JsonProperty("lang")
val lang: String,
)
2022-06-09 13:50:55 +00:00
// Open file picker
private val pathPicker =
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
// It lies, it can be null if file manager quits.
if (uri == null) return@registerForActivityResult
val context = context ?: AcraApplication.context ?: return@registerForActivityResult
// RW perms for the path
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
context.contentResolver.takePersistableUriPermission(uri, flags)
val file = UniFile.fromUri(context, uri)
println("Selected URI path: $uri - Full path: ${file.filePath}")
// Stores the real URI using download_path_key
// Important that the URI is stored instead of filepath due to permissions.
PreferenceManager.getDefaultSharedPreferences(context)
.edit().putString(getString(R.string.download_path_key), uri.toString()).apply()
// From URI -> File path
// File path here is purely for cosmetic purposes in settings
(file.filePath ?: uri.toString()).let {
PreferenceManager.getDefaultSharedPreferences(context)
.edit().putString(getString(R.string.download_path_pref), it).apply()
}
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
hideKeyboard()
setPreferencesFromResource(R.xml.settins_general, rootKey)
val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext())
2022-06-16 22:07:07 +00:00
fun getCurrent(): MutableList<CustomSite> {
return getKey<Array<CustomSite>>(USER_PROVIDER_API)?.toMutableList()
?: mutableListOf()
}
getPref(R.string.locale_key)?.setOnPreferenceClickListener { pref ->
val tempLangs = appLanguages.toMutableList()
//if (beneneCount > 100) {
// tempLangs.add(Triple("\uD83E\uDD8D", "mmmm... monke", "mo"))
//}
val current = getCurrentLocale(pref.context)
val languageCodes = tempLangs.map { (_, _, iso) -> iso }
val languageNames = tempLangs.map { (emoji, name, iso) ->
val flag = emoji.ifBlank { SubtitleHelper.getFlagFromIso(iso) ?: "ERROR" }
"$flag $name"
}
val index = languageCodes.indexOf(current)
activity?.showDialog(
languageNames, index, getString(R.string.app_language), true, { }
) { languageIndex ->
try {
val code = languageCodes[languageIndex]
CommonActivity.setLocale(activity, code)
settingsManager.edit().putString(getString(R.string.locale_key), code).apply()
activity?.recreate()
} catch (e: Exception) {
logError(e)
}
}
return@setOnPreferenceClickListener true
}
2022-06-16 22:07:07 +00:00
fun showAdd() {
val providers = allProviders.distinctBy { it.javaClass }.sortedBy { it.name }
activity?.showDialog(
providers.map { "${it.name} (${it.mainUrl})" },
-1,
context?.getString(R.string.add_site_pref) ?: return,
true,
{}) { selection ->
val provider = providers.getOrNull(selection) ?: return@showDialog
val builder =
AlertDialog.Builder(context ?: return@showDialog, R.style.AlertDialogCustom)
.setView(R.layout.add_site_input)
val dialog = builder.create()
dialog.show()
dialog.text2?.text = provider.name
dialog.apply_btt?.setOnClickListener {
val name = dialog.site_name_input?.text?.toString()
val url = dialog.site_url_input?.text?.toString()
val lang = dialog.site_lang_input?.text?.toString()
val realLang = if (lang.isNullOrBlank()) provider.lang else lang
if (url.isNullOrBlank() || name.isNullOrBlank() || realLang.length != 2) {
showToast(activity, R.string.error_invalid_data, Toast.LENGTH_SHORT)
return@setOnClickListener
}
val current = getCurrent()
val newSite = CustomSite(provider.javaClass.simpleName, name, url, realLang)
current.add(newSite)
setKey(USER_PROVIDER_API, current.toTypedArray())
dialog.dismissSafe(activity)
}
dialog.cancel_btt?.setOnClickListener {
dialog.dismissSafe(activity)
}
}
}
fun showDelete() {
val current = getCurrent()
activity?.showMultiDialog(
current.map { it.name },
listOf(),
context?.getString(R.string.remove_site_pref) ?: return,
{}) { indexes ->
current.removeAll(indexes.map { current[it] })
setKey(USER_PROVIDER_API, current.toTypedArray())
}
}
fun showAddOrDelete() {
val builder =
AlertDialog.Builder(context ?: return, R.style.AlertDialogCustom)
.setView(R.layout.add_remove_sites)
val dialog = builder.create()
dialog.show()
dialog.add_site?.setOnClickListener {
showAdd()
dialog.dismissSafe(activity)
}
dialog.remove_site?.setOnClickListener {
showDelete()
dialog.dismissSafe(activity)
}
}
getPref(R.string.override_site_key)?.setOnPreferenceClickListener { _ ->
if (getCurrent().isEmpty()) {
showAdd()
} else {
showAddOrDelete()
}
return@setOnPreferenceClickListener true
}
2022-06-09 13:50:55 +00:00
getPref(R.string.legal_notice_key)?.setOnPreferenceClickListener {
val builder: AlertDialog.Builder =
AlertDialog.Builder(it.context, R.style.AlertDialogCustom)
builder.setTitle(R.string.legal_notice)
builder.setMessage(R.string.legal_notice_text)
builder.show()
return@setOnPreferenceClickListener true
}
2022-06-16 22:07:07 +00:00
2022-06-09 13:50:55 +00:00
getPref(R.string.dns_key)?.setOnPreferenceClickListener {
val prefNames = resources.getStringArray(R.array.dns_pref)
val prefValues = resources.getIntArray(R.array.dns_pref_values)
val currentDns =
settingsManager.getInt(getString(R.string.dns_pref), 0)
activity?.showBottomDialog(
prefNames.toList(),
prefValues.indexOf(currentDns),
getString(R.string.dns_pref),
true,
{}) {
settingsManager.edit().putInt(getString(R.string.dns_pref), prefValues[it]).apply()
(context ?: AcraApplication.context)?.let { ctx -> app.initClient(ctx) }
}
return@setOnPreferenceClickListener true
}
fun getDownloadDirs(): List<String> {
return normalSafeApiCall {
val defaultDir = VideoDownloadManager.getDownloadDir()?.filePath
// app_name_download_path = Cloudstream and does not change depending on release.
// DOES NOT WORK ON SCOPED STORAGE.
val secondaryDir =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) null else Environment.getExternalStorageDirectory().absolutePath +
File.separator + resources.getString(R.string.app_name_download_path)
val first = listOf(defaultDir, secondaryDir)
(try {
val currentDir = context?.getBasePath()?.let { it.first?.filePath ?: it.second }
(first +
requireContext().getExternalFilesDirs("").mapNotNull { it.path } +
currentDir)
} catch (e: Exception) {
first
}).filterNotNull().distinct()
} ?: emptyList()
}
getPref(R.string.download_path_key)?.setOnPreferenceClickListener {
val dirs = getDownloadDirs()
val currentDir =
settingsManager.getString(getString(R.string.download_path_pref), null)
?: VideoDownloadManager.getDownloadDir().toString()
activity?.showBottomDialog(
dirs + listOf("Custom"),
dirs.indexOf(currentDir),
getString(R.string.download_path_pref),
true,
{}) {
// Last = custom
if (it == dirs.size) {
try {
pathPicker.launch(Uri.EMPTY)
} catch (e: Exception) {
logError(e)
}
} else {
// Sets both visual and actual paths.
// key = used path
// pref = visual path
settingsManager.edit()
.putString(getString(R.string.download_path_key), dirs[it]).apply()
settingsManager.edit()
.putString(getString(R.string.download_path_pref), dirs[it]).apply()
}
}
return@setOnPreferenceClickListener true
}
try {
SettingsFragment.beneneCount =
settingsManager.getInt(getString(R.string.benene_count), 0)
getPref(R.string.benene_count)?.let { pref ->
pref.summary =
if (SettingsFragment.beneneCount <= 0) getString(R.string.benene_count_text_none) else getString(
R.string.benene_count_text
).format(
SettingsFragment.beneneCount
)
pref.setOnPreferenceClickListener {
try {
SettingsFragment.beneneCount++
if (SettingsFragment.beneneCount%20 == 0) {
val intent = Intent(context, EasterEggMonke::class.java)
startActivity(intent)
}
2022-06-09 13:50:55 +00:00
settingsManager.edit().putInt(
getString(R.string.benene_count),
SettingsFragment.beneneCount
)
.apply()
it.summary =
getString(R.string.benene_count_text).format(SettingsFragment.beneneCount)
} catch (e: Exception) {
logError(e)
}
return@setOnPreferenceClickListener true
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
2022-11-29 19:45:00 +00:00
}