mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	settings update
This commit is contained in:
		
							parent
							
								
									8d14046c4a
								
							
						
					
					
						commit
						88e1719085
					
				
					 27 changed files with 1655 additions and 1183 deletions
				
			
		| 
						 | 
				
			
			@ -128,7 +128,15 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
 | 
			
		|||
            R.id.navigation_search,
 | 
			
		||||
            R.id.navigation_downloads,
 | 
			
		||||
            R.id.navigation_settings,
 | 
			
		||||
            R.id.navigation_download_child
 | 
			
		||||
            R.id.navigation_download_child,
 | 
			
		||||
            R.id.navigation_subtitles,
 | 
			
		||||
            R.id.navigation_chrome_subtitles,
 | 
			
		||||
            R.id.navigation_settings_nginx,
 | 
			
		||||
            R.id.navigation_settings_player,
 | 
			
		||||
            R.id.navigation_settings_updates,
 | 
			
		||||
            R.id.navigation_settings_ui,
 | 
			
		||||
            R.id.navigation_settings_account,
 | 
			
		||||
            R.id.navigation_settings_lang,
 | 
			
		||||
        ).contains(destination.id)
 | 
			
		||||
 | 
			
		||||
        val landscape = when (resources.configuration.orientation) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,6 @@ import androidx.appcompat.app.AppCompatActivity
 | 
			
		|||
import androidx.core.view.isVisible
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
import androidx.lifecycle.ViewModelProvider
 | 
			
		||||
import androidx.navigation.fragment.NavHostFragment
 | 
			
		||||
import androidx.recyclerview.widget.GridLayoutManager
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import com.lagradost.cloudstream3.R
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +21,7 @@ import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
 | 
			
		|||
import com.lagradost.cloudstream3.utils.DataStore
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
 | 
			
		||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
 | 
			
		||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
 | 
			
		||||
import kotlinx.android.synthetic.main.fragment_downloads.*
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +57,7 @@ class DownloadFragment : Fragment() {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onDestroy() {
 | 
			
		||||
        if(downloadDeleteEventListener != null) {
 | 
			
		||||
        if (downloadDeleteEventListener != null) {
 | 
			
		||||
            VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!!
 | 
			
		||||
            downloadDeleteEventListener = null
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -80,17 +80,26 @@ class DownloadFragment : Fragment() {
 | 
			
		|||
        }
 | 
			
		||||
        observe(downloadsViewModel.availableBytes) {
 | 
			
		||||
            download_free_txt?.text =
 | 
			
		||||
                getString(R.string.storage_size_format).format(getString(R.string.free_storage), getBytesAsText(it))
 | 
			
		||||
                getString(R.string.storage_size_format).format(
 | 
			
		||||
                    getString(R.string.free_storage),
 | 
			
		||||
                    getBytesAsText(it)
 | 
			
		||||
                )
 | 
			
		||||
            download_free?.setLayoutWidth(it)
 | 
			
		||||
        }
 | 
			
		||||
        observe(downloadsViewModel.usedBytes) {
 | 
			
		||||
            download_used_txt?.text =
 | 
			
		||||
                getString(R.string.storage_size_format).format(getString(R.string.used_storage), getBytesAsText(it))
 | 
			
		||||
                getString(R.string.storage_size_format).format(
 | 
			
		||||
                    getString(R.string.used_storage),
 | 
			
		||||
                    getBytesAsText(it)
 | 
			
		||||
                )
 | 
			
		||||
            download_used?.setLayoutWidth(it)
 | 
			
		||||
        }
 | 
			
		||||
        observe(downloadsViewModel.downloadBytes) {
 | 
			
		||||
            download_app_txt?.text =
 | 
			
		||||
                getString(R.string.storage_size_format).format(getString(R.string.app_storage), getBytesAsText(it))
 | 
			
		||||
                getString(R.string.storage_size_format).format(
 | 
			
		||||
                    getString(R.string.app_storage),
 | 
			
		||||
                    getBytesAsText(it)
 | 
			
		||||
                )
 | 
			
		||||
            download_app?.setLayoutWidth(it)
 | 
			
		||||
            download_storage_appbar?.visibility = View.VISIBLE
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -112,16 +121,21 @@ class DownloadFragment : Fragment() {
 | 
			
		|||
                            if (click.data.type.isMovieType()) {
 | 
			
		||||
                                //wont be called
 | 
			
		||||
                            } else {
 | 
			
		||||
                                val folder = DataStore.getFolderName(DOWNLOAD_EPISODE_CACHE, click.data.id.toString())
 | 
			
		||||
                                val navHostFragment = activity?.supportFragmentManager?.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment?
 | 
			
		||||
                                navHostFragment?.navController?.navigate(
 | 
			
		||||
                                    R.id.navigation_download_child,
 | 
			
		||||
                                val folder = DataStore.getFolderName(
 | 
			
		||||
                                    DOWNLOAD_EPISODE_CACHE,
 | 
			
		||||
                                    click.data.id.toString()
 | 
			
		||||
                                )
 | 
			
		||||
                                activity?.navigate(
 | 
			
		||||
                                    R.id.action_navigation_downloads_to_navigation_download_child,
 | 
			
		||||
                                    DownloadChildFragment.newInstance(click.data.name, folder)
 | 
			
		||||
                                )
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        1 -> {
 | 
			
		||||
                            (activity as AppCompatActivity?)?.loadResult(click.data.url, click.data.apiName)
 | 
			
		||||
                            (activity as AppCompatActivity?)?.loadResult(
 | 
			
		||||
                                click.data.url,
 | 
			
		||||
                                click.data.apiName
 | 
			
		||||
                            )
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1027,7 +1027,6 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
 | 
			
		|||
 | 
			
		||||
        // init variables
 | 
			
		||||
        setPlayBackSpeed(getKey(PLAYBACK_SPEED_KEY) ?: 1.0f)
 | 
			
		||||
        fastForwardTime = getKey(PLAYBACK_FASTFORWARD) ?: 10000L
 | 
			
		||||
 | 
			
		||||
        // handle tv controls
 | 
			
		||||
        playerEventListener = { eventType ->
 | 
			
		||||
| 
						 | 
				
			
			@ -1086,6 +1085,10 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
 | 
			
		|||
            context?.let { ctx ->
 | 
			
		||||
                val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx)
 | 
			
		||||
 | 
			
		||||
                fastForwardTime =
 | 
			
		||||
                    settingsManager.getInt(ctx.getString(R.string.double_tap_seek_time_key), 10)
 | 
			
		||||
                        .toLong() * 1000L
 | 
			
		||||
 | 
			
		||||
                navigationBarHeight = ctx.getNavigationBarHeight()
 | 
			
		||||
                statusBarHeight = ctx.getStatusBarHeight()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,6 +52,9 @@ class GeneratorPlayer : FullScreenPlayer() {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var titleRez = 3
 | 
			
		||||
    private var limitTitle = 0
 | 
			
		||||
 | 
			
		||||
    private lateinit var viewModel: PlayerGeneratorViewModel //by activityViewModels()
 | 
			
		||||
    private lateinit var sync: SyncViewModel
 | 
			
		||||
    private var currentLinks: Set<Pair<ExtractorLink?, ExtractorUri?>> = setOf()
 | 
			
		||||
| 
						 | 
				
			
			@ -550,12 +553,7 @@ class GeneratorPlayer : FullScreenPlayer() {
 | 
			
		|||
                tvType = meta.tvType
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        //Get limit of characters on Video Title
 | 
			
		||||
        var limitTitle = 0
 | 
			
		||||
        context?.let {
 | 
			
		||||
            val settingsManager = PreferenceManager.getDefaultSharedPreferences(it)
 | 
			
		||||
            limitTitle = settingsManager.getInt(getString(R.string.prefer_limit_title_key), 0)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Generate video title
 | 
			
		||||
        var playerVideoTitle = if (headerName != null) {
 | 
			
		||||
            (headerName +
 | 
			
		||||
| 
						 | 
				
			
			@ -577,7 +575,7 @@ class GeneratorPlayer : FullScreenPlayer() {
 | 
			
		|||
            val differenceInLength = playerVideoTitle.length - limitTitle
 | 
			
		||||
            val margin = 3 //If the difference is smaller than or equal to this value, ignore it
 | 
			
		||||
            if (limitTitle > 0 && differenceInLength > margin) {
 | 
			
		||||
                playerVideoTitle = playerVideoTitle.substring(0, limitTitle-1) + "..."
 | 
			
		||||
                playerVideoTitle = playerVideoTitle.substring(0, limitTitle - 1) + "..."
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -589,13 +587,21 @@ class GeneratorPlayer : FullScreenPlayer() {
 | 
			
		|||
    fun setPlayerDimen(widthHeight: Pair<Int, Int>?) {
 | 
			
		||||
        val extra = if (widthHeight != null) {
 | 
			
		||||
            val (width, height) = widthHeight
 | 
			
		||||
            " - ${width}x${height}"
 | 
			
		||||
            "${width}x${height}"
 | 
			
		||||
        } else {
 | 
			
		||||
            ""
 | 
			
		||||
        }
 | 
			
		||||
        player_video_title_rez?.text =
 | 
			
		||||
            (currentSelectedLink?.first?.name ?: currentSelectedLink?.second?.name
 | 
			
		||||
            ?: "NULL") + extra
 | 
			
		||||
 | 
			
		||||
        val source = currentSelectedLink?.first?.name ?: currentSelectedLink?.second?.name
 | 
			
		||||
        ?: "NULL"
 | 
			
		||||
 | 
			
		||||
        player_video_title_rez?.text = when (titleRez) {
 | 
			
		||||
            0 -> ""
 | 
			
		||||
            1 -> extra
 | 
			
		||||
            2 -> source
 | 
			
		||||
            3 -> "$source - $extra"
 | 
			
		||||
            else -> ""
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun playerDimensionsLoaded(widthHeight: Pair<Int, Int>) {
 | 
			
		||||
| 
						 | 
				
			
			@ -631,6 +637,12 @@ class GeneratorPlayer : FullScreenPlayer() {
 | 
			
		|||
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onViewCreated(view, savedInstanceState)
 | 
			
		||||
 | 
			
		||||
        context?.let { ctx ->
 | 
			
		||||
            val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx)
 | 
			
		||||
            titleRez = settingsManager.getInt(getString(R.string.prefer_limit_title_rez_key), 3)
 | 
			
		||||
            limitTitle = settingsManager.getInt(getString(R.string.prefer_limit_title_key), 0)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        unwrapBundle(savedInstanceState)
 | 
			
		||||
        unwrapBundle(arguments)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,7 +57,7 @@ const val PLAYBACK_SPEED = "playback_speed"
 | 
			
		|||
const val RESIZE_MODE_KEY = "resize_mode" // Last used resize mode
 | 
			
		||||
const val PLAYBACK_SPEED_KEY = "playback_speed" // Last used playback speed
 | 
			
		||||
const val PREFERRED_SUBS_KEY = "preferred_subtitles" // Last used resize mode
 | 
			
		||||
const val PLAYBACK_FASTFORWARD = "playback_fastforward" // Last used resize mode
 | 
			
		||||
//const val PLAYBACK_FASTFORWARD = "playback_fastforward" // Last used resize mode
 | 
			
		||||
 | 
			
		||||
/** Abstract Exoplayer logic, can be expanded to other players */
 | 
			
		||||
interface IPlayer {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1729,13 +1729,11 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
 | 
			
		|||
                    setRecommendations(d.recommendations, null)
 | 
			
		||||
                    setActors(d.actors)
 | 
			
		||||
 | 
			
		||||
                    if (SettingsFragment.accountEnabled) {
 | 
			
		||||
                        if (syncModel.addSyncs(d.syncData)) {
 | 
			
		||||
                            syncModel.updateMetaAndUser()
 | 
			
		||||
                            syncModel.updateSynced()
 | 
			
		||||
                        } else {
 | 
			
		||||
                            syncModel.addFromUrl(d.url)
 | 
			
		||||
                        }
 | 
			
		||||
                    if (syncModel.addSyncs(d.syncData)) {
 | 
			
		||||
                        syncModel.updateMetaAndUser()
 | 
			
		||||
                        syncModel.updateSynced()
 | 
			
		||||
                    } else {
 | 
			
		||||
                        syncModel.addFromUrl(d.url)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    result_meta_site?.text = d.apiName
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,149 @@
 | 
			
		|||
package com.lagradost.cloudstream3.ui.settings
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.widget.ImageView
 | 
			
		||||
import android.widget.TextView
 | 
			
		||||
import androidx.appcompat.app.AlertDialog
 | 
			
		||||
import androidx.preference.PreferenceFragmentCompat
 | 
			
		||||
import androidx.preference.PreferenceManager
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import com.lagradost.cloudstream3.R
 | 
			
		||||
import com.lagradost.cloudstream3.mvvm.logError
 | 
			
		||||
import com.lagradost.cloudstream3.syncproviders.AccountManager
 | 
			
		||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API
 | 
			
		||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.beneneCount
 | 
			
		||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
 | 
			
		||||
 | 
			
		||||
class SettingsAccount : PreferenceFragmentCompat() {
 | 
			
		||||
    private fun showLoginInfo(api: AccountManager, info: OAuth2API.LoginInfo) {
 | 
			
		||||
        val builder =
 | 
			
		||||
            AlertDialog.Builder(context ?: return, R.style.AlertDialogCustom)
 | 
			
		||||
                .setView(R.layout.account_managment)
 | 
			
		||||
        val dialog = builder.show()
 | 
			
		||||
 | 
			
		||||
        dialog.findViewById<ImageView>(R.id.account_profile_picture)?.setImage(info.profilePicture)
 | 
			
		||||
        dialog.findViewById<TextView>(R.id.account_logout)?.setOnClickListener {
 | 
			
		||||
            api.logOut()
 | 
			
		||||
            dialog.dismissSafe(activity)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        (info.name ?: context?.getString(R.string.no_data))?.let {
 | 
			
		||||
            dialog.findViewById<TextView>(R.id.account_name)?.text = it
 | 
			
		||||
        }
 | 
			
		||||
        dialog.findViewById<TextView>(R.id.account_site)?.text = api.name
 | 
			
		||||
        dialog.findViewById<TextView>(R.id.account_switch_account)?.setOnClickListener {
 | 
			
		||||
            dialog.dismissSafe(activity)
 | 
			
		||||
            showAccountSwitch(it.context, api)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun showAccountSwitch(context: Context, api: AccountManager) {
 | 
			
		||||
        val accounts = api.getAccounts() ?: return
 | 
			
		||||
 | 
			
		||||
        val builder =
 | 
			
		||||
            AlertDialog.Builder(context, R.style.AlertDialogCustom).setView(R.layout.account_switch)
 | 
			
		||||
        val dialog = builder.show()
 | 
			
		||||
 | 
			
		||||
        dialog.findViewById<TextView>(R.id.account_add)?.setOnClickListener {
 | 
			
		||||
            try {
 | 
			
		||||
                api.authenticate()
 | 
			
		||||
            } catch (e: Exception) {
 | 
			
		||||
                logError(e)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val ogIndex = api.accountIndex
 | 
			
		||||
 | 
			
		||||
        val items = ArrayList<OAuth2API.LoginInfo>()
 | 
			
		||||
 | 
			
		||||
        for (index in accounts) {
 | 
			
		||||
            api.accountIndex = index
 | 
			
		||||
            val accountInfo = api.loginInfo()
 | 
			
		||||
            if (accountInfo != null) {
 | 
			
		||||
                items.add(accountInfo)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        api.accountIndex = ogIndex
 | 
			
		||||
        val adapter = AccountAdapter(items, R.layout.account_single) {
 | 
			
		||||
            dialog?.dismissSafe(activity)
 | 
			
		||||
            api.changeAccount(it.card.accountIndex)
 | 
			
		||||
        }
 | 
			
		||||
        val list = dialog.findViewById<RecyclerView>(R.id.account_list)
 | 
			
		||||
        list?.adapter = adapter
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
 | 
			
		||||
        hideKeyboard()
 | 
			
		||||
        setPreferencesFromResource(R.xml.settings_credits_account, rootKey)
 | 
			
		||||
        val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext())
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.legal_notice_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val builder: AlertDialog.Builder = AlertDialog.Builder(it.context)
 | 
			
		||||
            builder.setTitle(R.string.legal_notice)
 | 
			
		||||
            builder.setMessage(R.string.legal_notice_text)
 | 
			
		||||
            builder.show()
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val syncApis =
 | 
			
		||||
            listOf(
 | 
			
		||||
                Pair(R.string.mal_key, OAuth2API.malApi), Pair(
 | 
			
		||||
                    R.string.anilist_key,
 | 
			
		||||
                    OAuth2API.aniListApi
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
        for ((key, api) in syncApis) {
 | 
			
		||||
            getPref(key)?.apply {
 | 
			
		||||
                title =
 | 
			
		||||
                    getString(R.string.login_format).format(api.name, getString(R.string.account))
 | 
			
		||||
                setOnPreferenceClickListener { _ ->
 | 
			
		||||
                    val info = api.loginInfo()
 | 
			
		||||
                    if (info != null) {
 | 
			
		||||
                        showLoginInfo(api, info)
 | 
			
		||||
                    } else {
 | 
			
		||||
                        try {
 | 
			
		||||
                            api.authenticate()
 | 
			
		||||
                        } catch (e: Exception) {
 | 
			
		||||
                            logError(e)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    return@setOnPreferenceClickListener true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            beneneCount = settingsManager.getInt(getString(R.string.benene_count), 0)
 | 
			
		||||
            getPref(R.string.benene_count)?.let { pref ->
 | 
			
		||||
                pref.summary =
 | 
			
		||||
                    if (beneneCount <= 0) getString(R.string.benene_count_text_none) else getString(
 | 
			
		||||
                        R.string.benene_count_text
 | 
			
		||||
                    ).format(
 | 
			
		||||
                        beneneCount
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
                pref.setOnPreferenceClickListener {
 | 
			
		||||
                    try {
 | 
			
		||||
                        beneneCount++
 | 
			
		||||
                        settingsManager.edit().putInt(getString(R.string.benene_count), beneneCount)
 | 
			
		||||
                            .apply()
 | 
			
		||||
                        it.summary = getString(R.string.benene_count_text).format(beneneCount)
 | 
			
		||||
                    } catch (e: Exception) {
 | 
			
		||||
                        logError(e)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return@setOnPreferenceClickListener true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            e.printStackTrace()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,75 +1,52 @@
 | 
			
		|||
package com.lagradost.cloudstream3.ui.settings
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import android.app.UiModeManager
 | 
			
		||||
import android.content.ClipData
 | 
			
		||||
import android.content.ClipboardManager
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.content.res.Configuration
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.os.Environment
 | 
			
		||||
import android.widget.ImageView
 | 
			
		||||
import android.widget.TextView
 | 
			
		||||
import android.widget.Toast
 | 
			
		||||
import androidx.activity.result.contract.ActivityResultContracts
 | 
			
		||||
import androidx.appcompat.app.AlertDialog
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
import androidx.preference.Preference
 | 
			
		||||
import androidx.preference.PreferenceFragmentCompat
 | 
			
		||||
import androidx.preference.PreferenceManager
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import com.hippo.unifile.UniFile
 | 
			
		||||
import com.lagradost.cloudstream3.APIHolder.apis
 | 
			
		||||
import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings
 | 
			
		||||
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
 | 
			
		||||
import com.lagradost.cloudstream3.AcraApplication
 | 
			
		||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
 | 
			
		||||
import com.lagradost.cloudstream3.CommonActivity.setLocale
 | 
			
		||||
import com.lagradost.cloudstream3.CommonActivity.showToast
 | 
			
		||||
import com.lagradost.cloudstream3.DubStatus
 | 
			
		||||
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.syncproviders.AccountManager
 | 
			
		||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API
 | 
			
		||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.aniListApi
 | 
			
		||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.malApi
 | 
			
		||||
import com.lagradost.cloudstream3.ui.APIRepository
 | 
			
		||||
import com.lagradost.cloudstream3.ui.search.SearchResultBuilder
 | 
			
		||||
import com.lagradost.cloudstream3.ui.subtitles.ChromecastSubtitlesFragment
 | 
			
		||||
import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment
 | 
			
		||||
import com.lagradost.cloudstream3.utils.BackupUtils.backup
 | 
			
		||||
import com.lagradost.cloudstream3.utils.BackupUtils.restorePrompt
 | 
			
		||||
import com.lagradost.cloudstream3.utils.HOMEPAGE_API
 | 
			
		||||
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
 | 
			
		||||
import com.lagradost.cloudstream3.utils.Qualities
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showNginxTextInputDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SubtitleHelper
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SubtitleHelper.getFlagFromIso
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
 | 
			
		||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
 | 
			
		||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath
 | 
			
		||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getDownloadDir
 | 
			
		||||
import kotlinx.android.synthetic.main.logcat.*
 | 
			
		||||
import okhttp3.internal.closeQuietly
 | 
			
		||||
import java.io.BufferedReader
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
 | 
			
		||||
import kotlinx.android.synthetic.main.main_settings.*
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.io.InputStreamReader
 | 
			
		||||
import java.io.OutputStream
 | 
			
		||||
import kotlin.concurrent.thread
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SettingsFragment : PreferenceFragmentCompat() {
 | 
			
		||||
class SettingsFragment : Fragment() {
 | 
			
		||||
    companion object {
 | 
			
		||||
        var beneneCount = 0
 | 
			
		||||
 | 
			
		||||
        fun PreferenceFragmentCompat?.getPref(id: Int): Preference? {
 | 
			
		||||
            if (this == null) return null
 | 
			
		||||
 | 
			
		||||
            return try {
 | 
			
		||||
                findPreference(getString(id))
 | 
			
		||||
            } catch (e: Exception) {
 | 
			
		||||
                logError(e)
 | 
			
		||||
                null
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun getFolderSize(dir: File): Long {
 | 
			
		||||
            var size: Long = 0
 | 
			
		||||
            dir.listFiles()?.let {
 | 
			
		||||
                for (file in it) {
 | 
			
		||||
                    size += if (file.isFile) {
 | 
			
		||||
                        // System.out.println(file.getName() + " " + file.length());
 | 
			
		||||
                        file.length()
 | 
			
		||||
                    } else getFolderSize(file)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return size
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private fun Context.getLayoutInt(): Int {
 | 
			
		||||
            val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
 | 
			
		||||
            return settingsManager.getInt(this.getString(R.string.app_layout_key), -1)
 | 
			
		||||
| 
						 | 
				
			
			@ -98,762 +75,47 @@ class SettingsFragment : PreferenceFragmentCompat() {
 | 
			
		|||
        private fun Context.isAutoTv(): Boolean {
 | 
			
		||||
            val uiModeManager = getSystemService(Context.UI_MODE_SERVICE) as UiModeManager?
 | 
			
		||||
            // AFT = Fire TV
 | 
			
		||||
            return uiModeManager?.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION || Build.MODEL.contains("AFT")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const val accountEnabled = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var beneneCount = 0
 | 
			
		||||
 | 
			
		||||
    // 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()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    // 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
 | 
			
		||||
    private val languages = arrayListOf(
 | 
			
		||||
        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("", "Portuguese (Brazil)", "pt"),
 | 
			
		||||
        Triple("", "Romanian", "ro"),
 | 
			
		||||
        Triple("", "Italian", "it"),
 | 
			
		||||
        Triple("", "Chinese", "zh"),
 | 
			
		||||
    ).sortedBy { it.second } //ye, we go alphabetical, so ppl don't put their lang on top
 | 
			
		||||
 | 
			
		||||
    private fun showAccountSwitch(context: Context, api: AccountManager) {
 | 
			
		||||
        val accounts = api.getAccounts() ?: return
 | 
			
		||||
 | 
			
		||||
        val builder =
 | 
			
		||||
            AlertDialog.Builder(context, R.style.AlertDialogCustom).setView(R.layout.account_switch)
 | 
			
		||||
        val dialog = builder.show()
 | 
			
		||||
 | 
			
		||||
        dialog.findViewById<TextView>(R.id.account_add)?.setOnClickListener {
 | 
			
		||||
            try {
 | 
			
		||||
                api.authenticate()
 | 
			
		||||
            } catch (e: Exception) {
 | 
			
		||||
                logError(e)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val ogIndex = api.accountIndex
 | 
			
		||||
 | 
			
		||||
        val items = ArrayList<OAuth2API.LoginInfo>()
 | 
			
		||||
 | 
			
		||||
        for (index in accounts) {
 | 
			
		||||
            api.accountIndex = index
 | 
			
		||||
            val accountInfo = api.loginInfo()
 | 
			
		||||
            if (accountInfo != null) {
 | 
			
		||||
                items.add(accountInfo)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        api.accountIndex = ogIndex
 | 
			
		||||
        val adapter = AccountAdapter(items, R.layout.account_single) {
 | 
			
		||||
            dialog?.dismissSafe(activity)
 | 
			
		||||
            api.changeAccount(it.card.accountIndex)
 | 
			
		||||
        }
 | 
			
		||||
        val list = dialog.findViewById<RecyclerView>(R.id.account_list)
 | 
			
		||||
        list?.adapter = adapter
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun showLoginInfo(api: AccountManager, info: OAuth2API.LoginInfo) {
 | 
			
		||||
        val builder =
 | 
			
		||||
            AlertDialog.Builder(context ?: return, R.style.AlertDialogCustom)
 | 
			
		||||
                .setView(R.layout.account_managment)
 | 
			
		||||
        val dialog = builder.show()
 | 
			
		||||
 | 
			
		||||
        dialog.findViewById<ImageView>(R.id.account_profile_picture)?.setImage(info.profilePicture)
 | 
			
		||||
        dialog.findViewById<TextView>(R.id.account_logout)?.setOnClickListener {
 | 
			
		||||
            api.logOut()
 | 
			
		||||
            dialog.dismissSafe(activity)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        (info.name ?: context?.getString(R.string.no_data))?.let {
 | 
			
		||||
            dialog.findViewById<TextView>(R.id.account_name)?.text = it
 | 
			
		||||
        }
 | 
			
		||||
        dialog.findViewById<TextView>(R.id.account_site)?.text = api.name
 | 
			
		||||
        dialog.findViewById<TextView>(R.id.account_switch_account)?.setOnClickListener {
 | 
			
		||||
            dialog.dismissSafe(activity)
 | 
			
		||||
            showAccountSwitch(it.context, api)
 | 
			
		||||
            return uiModeManager?.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION || Build.MODEL.contains(
 | 
			
		||||
                "AFT"
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getPref(id: Int): Preference? {
 | 
			
		||||
        return try {
 | 
			
		||||
            findPreference(getString(id))
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            logError(e)
 | 
			
		||||
            null
 | 
			
		||||
        }
 | 
			
		||||
    override fun onCreateView(
 | 
			
		||||
        inflater: LayoutInflater,
 | 
			
		||||
        container: ViewGroup?,
 | 
			
		||||
        savedInstanceState: Bundle?,
 | 
			
		||||
    ): View? {
 | 
			
		||||
        return inflater.inflate(R.layout.main_settings, container, false)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getFolderSize(dir: File): Long {
 | 
			
		||||
        var size: Long = 0
 | 
			
		||||
        dir.listFiles()?.let {
 | 
			
		||||
            for (file in it) {
 | 
			
		||||
                size += if (file.isFile) {
 | 
			
		||||
                    // System.out.println(file.getName() + " " + file.length());
 | 
			
		||||
                    file.length()
 | 
			
		||||
                } else getFolderSize(file)
 | 
			
		||||
            }
 | 
			
		||||
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
 | 
			
		||||
        fun navigate(id: Int) {
 | 
			
		||||
            activity?.navigate(id, Bundle())
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return size
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
 | 
			
		||||
        hideKeyboard()
 | 
			
		||||
        setPreferencesFromResource(R.xml.settings, rootKey)
 | 
			
		||||
        val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext())
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.video_buffer_length_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.video_buffer_length_names)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.video_buffer_length_values)
 | 
			
		||||
 | 
			
		||||
            val currentPrefSize =
 | 
			
		||||
                settingsManager.getInt(getString(R.string.video_buffer_length_key), 0)
 | 
			
		||||
 | 
			
		||||
            activity?.showDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentPrefSize),
 | 
			
		||||
                getString(R.string.video_buffer_length_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.video_buffer_length_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        settings_player?.setOnClickListener {
 | 
			
		||||
            navigate(R.id.action_navigation_settings_to_navigation_settings_player)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.video_buffer_size_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.video_buffer_size_names)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.video_buffer_size_values)
 | 
			
		||||
 | 
			
		||||
            val currentPrefSize =
 | 
			
		||||
                settingsManager.getInt(getString(R.string.video_buffer_size_key), 0)
 | 
			
		||||
 | 
			
		||||
            activity?.showDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentPrefSize),
 | 
			
		||||
                getString(R.string.video_buffer_size_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.video_buffer_size_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        settings_credits?.setOnClickListener {
 | 
			
		||||
            navigate(R.id.action_navigation_settings_to_navigation_settings_account)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.video_buffer_clear_key)?.let { pref ->
 | 
			
		||||
            val cacheDir = context?.cacheDir ?: return@let
 | 
			
		||||
 | 
			
		||||
            fun updateSummery() {
 | 
			
		||||
                try {
 | 
			
		||||
                    pref.summary =
 | 
			
		||||
                        getString(R.string.mb_format).format(getFolderSize(cacheDir) / (1024L * 1024L))
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            updateSummery()
 | 
			
		||||
 | 
			
		||||
            pref.setOnPreferenceClickListener {
 | 
			
		||||
                try {
 | 
			
		||||
                    cacheDir.deleteRecursively()
 | 
			
		||||
                    updateSummery()
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
                return@setOnPreferenceClickListener true
 | 
			
		||||
            }
 | 
			
		||||
        settings_ui?.setOnClickListener {
 | 
			
		||||
            navigate(R.id.action_navigation_settings_to_navigation_settings_ui)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.video_buffer_disk_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.video_buffer_size_names)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.video_buffer_size_values)
 | 
			
		||||
 | 
			
		||||
            val currentPrefSize =
 | 
			
		||||
                settingsManager.getInt(getString(R.string.video_buffer_disk_key), 0)
 | 
			
		||||
 | 
			
		||||
            activity?.showDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentPrefSize),
 | 
			
		||||
                getString(R.string.video_buffer_disk_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.video_buffer_disk_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        settings_lang?.setOnClickListener {
 | 
			
		||||
            navigate(R.id.action_navigation_settings_to_navigation_settings_lang)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.subtitle_settings_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            SubtitlesFragment.push(activity, false)
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        settings_nginx?.setOnClickListener {
 | 
			
		||||
            navigate(R.id.action_navigation_settings_to_navigation_settings_nginx)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.subtitle_settings_chromecast_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            ChromecastSubtitlesFragment.push(activity, false)
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.poster_ui_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.poster_ui_options)
 | 
			
		||||
            val keys = resources.getStringArray(R.array.poster_ui_options_values)
 | 
			
		||||
            val prefValues = keys.map {
 | 
			
		||||
                settingsManager.getBoolean(it, true)
 | 
			
		||||
            }.mapIndexedNotNull { index, b ->
 | 
			
		||||
                if (b) {
 | 
			
		||||
                    index
 | 
			
		||||
                } else null
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            activity?.showMultiDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues,
 | 
			
		||||
                getString(R.string.poster_ui_settings),
 | 
			
		||||
                {}) { list ->
 | 
			
		||||
                val edit = settingsManager.edit()
 | 
			
		||||
                for ((i, key) in keys.withIndex()) {
 | 
			
		||||
                    edit.putBoolean(key, list.contains(i))
 | 
			
		||||
                }
 | 
			
		||||
                edit.apply()
 | 
			
		||||
                SearchResultBuilder.updateCache(it.context)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        val syncApis =
 | 
			
		||||
            listOf(Pair(R.string.mal_key, malApi), Pair(R.string.anilist_key, aniListApi))
 | 
			
		||||
        for ((key, api) in syncApis) {
 | 
			
		||||
            getPref(key)?.apply {
 | 
			
		||||
                isVisible = accountEnabled
 | 
			
		||||
                title =
 | 
			
		||||
                    getString(R.string.login_format).format(api.name, getString(R.string.account))
 | 
			
		||||
                setOnPreferenceClickListener { _ ->
 | 
			
		||||
                    val info = api.loginInfo()
 | 
			
		||||
                    if (info != null) {
 | 
			
		||||
                        showLoginInfo(api, info)
 | 
			
		||||
                    } else {
 | 
			
		||||
                        try {
 | 
			
		||||
                            api.authenticate()
 | 
			
		||||
                        } catch (e: Exception) {
 | 
			
		||||
                            logError(e)
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    return@setOnPreferenceClickListener true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.legal_notice_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val builder: AlertDialog.Builder = AlertDialog.Builder(it.context)
 | 
			
		||||
            builder.setTitle(R.string.legal_notice)
 | 
			
		||||
            builder.setMessage(R.string.legal_notice_text)
 | 
			
		||||
            builder.show()
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.display_sub_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.getApiDubstatusSettings()?.let { current ->
 | 
			
		||||
                val dublist = DubStatus.values()
 | 
			
		||||
                val names = dublist.map { it.name }
 | 
			
		||||
 | 
			
		||||
                val currentList = ArrayList<Int>()
 | 
			
		||||
                for (i in current) {
 | 
			
		||||
                    currentList.add(dublist.indexOf(i))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                activity?.showMultiDialog(
 | 
			
		||||
                    names,
 | 
			
		||||
                    currentList,
 | 
			
		||||
                    getString(R.string.display_subbed_dubbed_settings),
 | 
			
		||||
                    {}) { selectedList ->
 | 
			
		||||
                    APIRepository.dubStatusActive = selectedList.map { dublist[it] }.toHashSet()
 | 
			
		||||
 | 
			
		||||
                    settingsManager.edit().putStringSet(
 | 
			
		||||
                        this.getString(R.string.display_sub_key),
 | 
			
		||||
                        selectedList.map { names[it] }.toMutableSet()
 | 
			
		||||
                    ).apply()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.provider_lang_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.getApiProviderLangSettings()?.let { current ->
 | 
			
		||||
                val allLangs = HashSet<String>()
 | 
			
		||||
                for (api in apis) {
 | 
			
		||||
                    allLangs.add(api.lang)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                val currentList = ArrayList<Int>()
 | 
			
		||||
                for (i in current) {
 | 
			
		||||
                    currentList.add(allLangs.indexOf(i))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                val names = allLangs.map {
 | 
			
		||||
                    val emoji = getFlagFromIso(it)
 | 
			
		||||
                    val name = SubtitleHelper.fromTwoLettersToLanguage(it)
 | 
			
		||||
                    val fullName = "$emoji $name"
 | 
			
		||||
                    Pair(it, fullName)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                activity?.showMultiDialog(
 | 
			
		||||
                    names.map { it.second },
 | 
			
		||||
                    currentList,
 | 
			
		||||
                    getString(R.string.provider_lang_settings),
 | 
			
		||||
                    {}) { selectedList ->
 | 
			
		||||
                    settingsManager.edit().putStringSet(
 | 
			
		||||
                        this.getString(R.string.provider_lang_key),
 | 
			
		||||
                        selectedList.map { names[it].first }.toMutableSet()
 | 
			
		||||
                    ).apply()
 | 
			
		||||
                    //APIRepository.providersActive = it.context.getApiSettings()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun getDownloadDirs(): List<String> {
 | 
			
		||||
            return normalSafeApiCall {
 | 
			
		||||
                val defaultDir = 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)
 | 
			
		||||
                    ?: 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
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.nginx_url_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.showNginxTextInputDialog(
 | 
			
		||||
                settingsManager.getString(getString(R.string.nginx_url_pref), "Nginx server url")
 | 
			
		||||
                    .toString(),
 | 
			
		||||
                settingsManager.getString(getString(R.string.nginx_url_key), "")
 | 
			
		||||
                    .toString(),  // key: the actual you use rn
 | 
			
		||||
                android.text.InputType.TYPE_TEXT_VARIATION_URI,  // uri
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putString(getString(R.string.nginx_url_key), it)
 | 
			
		||||
                    .apply()  // change the stored url in nginx_url_key to it
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.nginx_credentials)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.showNginxTextInputDialog(
 | 
			
		||||
                settingsManager.getString(
 | 
			
		||||
                    getString(R.string.nginx_credentials_title),
 | 
			
		||||
                    "Nginx Credentials"
 | 
			
		||||
                ).toString(),
 | 
			
		||||
                settingsManager.getString(getString(R.string.nginx_credentials), "")
 | 
			
		||||
                    .toString(),  // key: the actual you use rn
 | 
			
		||||
                android.text.InputType.TYPE_TEXT_VARIATION_URI,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putString(getString(R.string.nginx_credentials), it)
 | 
			
		||||
                    .apply()  // change the stored url in nginx_url_key to it
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.prefer_media_type_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.media_type_pref)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.media_type_pref_values)
 | 
			
		||||
 | 
			
		||||
            val currentPrefMedia =
 | 
			
		||||
                settingsManager.getInt(getString(R.string.prefer_media_type_key), 0)
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentPrefMedia),
 | 
			
		||||
                getString(R.string.preferred_media_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.prefer_media_type_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
 | 
			
		||||
                removeKey(HOMEPAGE_API)
 | 
			
		||||
                (context ?: AcraApplication.context)?.let { ctx -> app.initClient(ctx) }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.show_logcat_key)?.setOnPreferenceClickListener { pref ->
 | 
			
		||||
            val builder =
 | 
			
		||||
                AlertDialog.Builder(pref.context, R.style.AlertDialogCustom)
 | 
			
		||||
                    .setView(R.layout.logcat)
 | 
			
		||||
 | 
			
		||||
            val dialog = builder.create()
 | 
			
		||||
            dialog.show()
 | 
			
		||||
            val log = StringBuilder()
 | 
			
		||||
            try {
 | 
			
		||||
                //https://developer.android.com/studio/command-line/logcat
 | 
			
		||||
                val process = Runtime.getRuntime().exec("logcat -d")
 | 
			
		||||
                val bufferedReader = BufferedReader(
 | 
			
		||||
                    InputStreamReader(process.inputStream)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                var line: String?
 | 
			
		||||
                while (bufferedReader.readLine().also { line = it } != null) {
 | 
			
		||||
                    log.append(line)
 | 
			
		||||
                }
 | 
			
		||||
            } catch (e: Exception) {
 | 
			
		||||
                logError(e) // kinda ironic
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val text = log.toString()
 | 
			
		||||
            dialog.text1?.text = text
 | 
			
		||||
 | 
			
		||||
            dialog.copy_btt?.setOnClickListener {
 | 
			
		||||
                val serviceClipboard =
 | 
			
		||||
                    (activity?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?)
 | 
			
		||||
                        ?: return@setOnClickListener
 | 
			
		||||
                val clip = ClipData.newPlainText("logcat", text)
 | 
			
		||||
                serviceClipboard.setPrimaryClip(clip)
 | 
			
		||||
                dialog.dismissSafe(activity)
 | 
			
		||||
            }
 | 
			
		||||
            dialog.clear_btt?.setOnClickListener {
 | 
			
		||||
                Runtime.getRuntime().exec("logcat -c")
 | 
			
		||||
                dialog.dismissSafe(activity)
 | 
			
		||||
            }
 | 
			
		||||
            dialog.save_btt?.setOnClickListener {
 | 
			
		||||
                var fileStream: OutputStream? = null
 | 
			
		||||
                try {
 | 
			
		||||
                    fileStream =
 | 
			
		||||
                        VideoDownloadManager.setupStream(
 | 
			
		||||
                            it.context,
 | 
			
		||||
                            "logcat",
 | 
			
		||||
                            null,
 | 
			
		||||
                            "txt",
 | 
			
		||||
                            false
 | 
			
		||||
                        ).fileStream
 | 
			
		||||
                    fileStream?.writer()?.write(text)
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                } finally {
 | 
			
		||||
                    fileStream?.closeQuietly()
 | 
			
		||||
                    dialog.dismissSafe(activity)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            dialog.close_btt?.setOnClickListener {
 | 
			
		||||
                dialog.dismissSafe(activity)
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.app_layout_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.app_layout)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.app_layout_values)
 | 
			
		||||
 | 
			
		||||
            val currentLayout =
 | 
			
		||||
                settingsManager.getInt(getString(R.string.app_layout_key), -1)
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentLayout),
 | 
			
		||||
                getString(R.string.app_layout),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                try {
 | 
			
		||||
                    settingsManager.edit()
 | 
			
		||||
                        .putInt(getString(R.string.app_layout_key), prefValues[it])
 | 
			
		||||
                        .apply()
 | 
			
		||||
                    activity?.recreate()
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.backup_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.backup()
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.restore_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.restorePrompt()
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.primary_color_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.themes_overlay_names)
 | 
			
		||||
            val prefValues = resources.getStringArray(R.array.themes_overlay_names_values)
 | 
			
		||||
 | 
			
		||||
            val currentLayout =
 | 
			
		||||
                settingsManager.getString(getString(R.string.primary_color_key), prefValues.first())
 | 
			
		||||
 | 
			
		||||
            activity?.showDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentLayout),
 | 
			
		||||
                getString(R.string.primary_color_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                try {
 | 
			
		||||
                    settingsManager.edit()
 | 
			
		||||
                        .putString(getString(R.string.primary_color_key), prefValues[it])
 | 
			
		||||
                        .apply()
 | 
			
		||||
                    activity?.recreate()
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.app_theme_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.themes_names)
 | 
			
		||||
            val prefValues = resources.getStringArray(R.array.themes_names_values)
 | 
			
		||||
 | 
			
		||||
            val currentLayout =
 | 
			
		||||
                settingsManager.getString(getString(R.string.app_theme_key), prefValues.first())
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentLayout),
 | 
			
		||||
                getString(R.string.app_theme_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                try {
 | 
			
		||||
                    settingsManager.edit()
 | 
			
		||||
                        .putString(getString(R.string.app_theme_key), prefValues[it])
 | 
			
		||||
                        .apply()
 | 
			
		||||
                    activity?.recreate()
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.quality_pref_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefValues = Qualities.values().map { it.value }.reversed().toMutableList()
 | 
			
		||||
            prefValues.remove(Qualities.Unknown.value)
 | 
			
		||||
 | 
			
		||||
            val prefNames = prefValues.map { Qualities.getStringByInt(it) }
 | 
			
		||||
 | 
			
		||||
            val currentQuality =
 | 
			
		||||
                settingsManager.getInt(
 | 
			
		||||
                    getString(R.string.quality_pref_key),
 | 
			
		||||
                    Qualities.values().last().value
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentQuality),
 | 
			
		||||
                getString(R.string.watch_quality_pref),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit().putInt(getString(R.string.quality_pref_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.prefer_limit_title_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.limit_title_pref_names)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.limit_title_pref_values)
 | 
			
		||||
            val current = settingsManager.getInt(getString(R.string.prefer_limit_title_key), 0)
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(current),
 | 
			
		||||
                getString(R.string.limit_title),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.prefer_limit_title_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            beneneCount = settingsManager.getInt(getString(R.string.benene_count), 0)
 | 
			
		||||
            getPref(R.string.benene_count)?.let { pref ->
 | 
			
		||||
                pref.summary =
 | 
			
		||||
                    if (beneneCount <= 0) getString(R.string.benene_count_text_none) else getString(
 | 
			
		||||
                        R.string.benene_count_text
 | 
			
		||||
                    ).format(
 | 
			
		||||
                        beneneCount
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
                pref.setOnPreferenceClickListener {
 | 
			
		||||
                    try {
 | 
			
		||||
                        beneneCount++
 | 
			
		||||
                        settingsManager.edit().putInt(getString(R.string.benene_count), beneneCount)
 | 
			
		||||
                            .apply()
 | 
			
		||||
                        it.summary = getString(R.string.benene_count_text).format(beneneCount)
 | 
			
		||||
                    } catch (e: Exception) {
 | 
			
		||||
                        logError(e)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return@setOnPreferenceClickListener true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            e.printStackTrace()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.manual_check_update_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            thread {
 | 
			
		||||
                if (!requireActivity().runAutoUpdate(false)) {
 | 
			
		||||
                    activity?.runOnUiThread {
 | 
			
		||||
                        showToast(activity, R.string.no_update_found, Toast.LENGTH_SHORT)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.locale_key)?.setOnPreferenceClickListener { pref ->
 | 
			
		||||
            val tempLangs = languages.toMutableList()
 | 
			
		||||
            if (beneneCount > 100) {
 | 
			
		||||
                tempLangs.add(Triple("\uD83E\uDD8D", "mmmm... monke", "mo"))
 | 
			
		||||
            }
 | 
			
		||||
            val current = getCurrentLocale()
 | 
			
		||||
            val languageCodes = tempLangs.map { it.third }
 | 
			
		||||
            val languageNames = tempLangs.map { (emoji, name, iso) ->
 | 
			
		||||
                val flag = emoji.ifBlank { 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]
 | 
			
		||||
                    setLocale(activity, code)
 | 
			
		||||
                    settingsManager.edit().putString(getString(R.string.locale_key), code).apply()
 | 
			
		||||
                    activity?.recreate()
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        settings_updates?.setOnClickListener {
 | 
			
		||||
            navigate(R.id.action_navigation_settings_to_navigation_settings_updates)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getCurrentLocale(): String {
 | 
			
		||||
        val res = requireContext().resources
 | 
			
		||||
// Change locale settings in the app.
 | 
			
		||||
        // val dm = res.displayMetrics
 | 
			
		||||
        val conf = res.configuration
 | 
			
		||||
        return conf?.locale?.language ?: "en"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,175 @@
 | 
			
		|||
package com.lagradost.cloudstream3.ui.settings
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import androidx.preference.PreferenceFragmentCompat
 | 
			
		||||
import androidx.preference.PreferenceManager
 | 
			
		||||
import com.lagradost.cloudstream3.*
 | 
			
		||||
import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings
 | 
			
		||||
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
 | 
			
		||||
import com.lagradost.cloudstream3.mvvm.logError
 | 
			
		||||
import com.lagradost.cloudstream3.network.initClient
 | 
			
		||||
import com.lagradost.cloudstream3.ui.APIRepository
 | 
			
		||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref
 | 
			
		||||
import com.lagradost.cloudstream3.utils.HOMEPAGE_API
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SubtitleHelper
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
 | 
			
		||||
 | 
			
		||||
class SettingsLang : PreferenceFragmentCompat() {
 | 
			
		||||
    // 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
 | 
			
		||||
    private val languages = arrayListOf(
 | 
			
		||||
        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\uDDE7\uD83C\uDDF7", "Portuguese (Brazil)", "pt"),
 | 
			
		||||
        Triple("", "Romanian", "ro"),
 | 
			
		||||
        Triple("", "Italian", "it"),
 | 
			
		||||
        Triple("", "Chinese", "zh"),
 | 
			
		||||
    ).sortedBy { it.second } //ye, we go alphabetical, so ppl don't put their lang on top
 | 
			
		||||
 | 
			
		||||
    private fun getCurrentLocale(): String {
 | 
			
		||||
        val res = requireContext().resources
 | 
			
		||||
// Change locale settings in the app.
 | 
			
		||||
        // val dm = res.displayMetrics
 | 
			
		||||
        val conf = res.configuration
 | 
			
		||||
        return conf?.locale?.language ?: "en"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
 | 
			
		||||
        hideKeyboard()
 | 
			
		||||
        setPreferencesFromResource(R.xml.settings_media_lang, rootKey)
 | 
			
		||||
        val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext())
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.display_sub_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.getApiDubstatusSettings()?.let { current ->
 | 
			
		||||
                val dublist = DubStatus.values()
 | 
			
		||||
                val names = dublist.map { it.name }
 | 
			
		||||
 | 
			
		||||
                val currentList = ArrayList<Int>()
 | 
			
		||||
                for (i in current) {
 | 
			
		||||
                    currentList.add(dublist.indexOf(i))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                activity?.showMultiDialog(
 | 
			
		||||
                    names,
 | 
			
		||||
                    currentList,
 | 
			
		||||
                    getString(R.string.display_subbed_dubbed_settings),
 | 
			
		||||
                    {}) { selectedList ->
 | 
			
		||||
                    APIRepository.dubStatusActive = selectedList.map { dublist[it] }.toHashSet()
 | 
			
		||||
 | 
			
		||||
                    settingsManager.edit().putStringSet(
 | 
			
		||||
                        this.getString(R.string.display_sub_key),
 | 
			
		||||
                        selectedList.map { names[it] }.toMutableSet()
 | 
			
		||||
                    ).apply()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.prefer_media_type_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.media_type_pref)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.media_type_pref_values)
 | 
			
		||||
 | 
			
		||||
            val currentPrefMedia =
 | 
			
		||||
                settingsManager.getInt(getString(R.string.prefer_media_type_key), 0)
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentPrefMedia),
 | 
			
		||||
                getString(R.string.preferred_media_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.prefer_media_type_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
 | 
			
		||||
                AcraApplication.removeKey(HOMEPAGE_API)
 | 
			
		||||
                (context ?: AcraApplication.context)?.let { ctx -> app.initClient(ctx) }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.locale_key)?.setOnPreferenceClickListener { pref ->
 | 
			
		||||
            val tempLangs = languages.toMutableList()
 | 
			
		||||
            //if (beneneCount > 100) {
 | 
			
		||||
            //    tempLangs.add(Triple("\uD83E\uDD8D", "mmmm... monke", "mo"))
 | 
			
		||||
            //}
 | 
			
		||||
            val current = getCurrentLocale()
 | 
			
		||||
            val languageCodes = tempLangs.map { it.third }
 | 
			
		||||
            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
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.provider_lang_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.getApiProviderLangSettings()?.let { current ->
 | 
			
		||||
                val allLangs = HashSet<String>()
 | 
			
		||||
                for (api in APIHolder.apis) {
 | 
			
		||||
                    allLangs.add(api.lang)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                val currentList = ArrayList<Int>()
 | 
			
		||||
                for (i in current) {
 | 
			
		||||
                    currentList.add(allLangs.indexOf(i))
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                val names = allLangs.map {
 | 
			
		||||
                    val emoji = SubtitleHelper.getFlagFromIso(it)
 | 
			
		||||
                    val name = SubtitleHelper.fromTwoLettersToLanguage(it)
 | 
			
		||||
                    val fullName = "$emoji $name"
 | 
			
		||||
                    Pair(it, fullName)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                activity?.showMultiDialog(
 | 
			
		||||
                    names.map { it.second },
 | 
			
		||||
                    currentList,
 | 
			
		||||
                    getString(R.string.provider_lang_settings),
 | 
			
		||||
                    {}) { selectedList ->
 | 
			
		||||
                    settingsManager.edit().putStringSet(
 | 
			
		||||
                        this.getString(R.string.provider_lang_key),
 | 
			
		||||
                        selectedList.map { names[it].first }.toMutableSet()
 | 
			
		||||
                    ).apply()
 | 
			
		||||
                    //APIRepository.providersActive = it.context.getApiSettings()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
package com.lagradost.cloudstream3.ui.settings
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import androidx.preference.PreferenceFragmentCompat
 | 
			
		||||
import androidx.preference.PreferenceManager
 | 
			
		||||
import com.lagradost.cloudstream3.AcraApplication
 | 
			
		||||
import com.lagradost.cloudstream3.R
 | 
			
		||||
import com.lagradost.cloudstream3.app
 | 
			
		||||
import com.lagradost.cloudstream3.network.initClient
 | 
			
		||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref
 | 
			
		||||
import com.lagradost.cloudstream3.utils.HOMEPAGE_API
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showNginxTextInputDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
 | 
			
		||||
 | 
			
		||||
class SettingsNginx : PreferenceFragmentCompat() {
 | 
			
		||||
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
 | 
			
		||||
        hideKeyboard()
 | 
			
		||||
        setPreferencesFromResource(R.xml.settings_nginx, rootKey)
 | 
			
		||||
        val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext())
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.nginx_credentials)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.showNginxTextInputDialog(
 | 
			
		||||
                settingsManager.getString(
 | 
			
		||||
                    getString(R.string.nginx_credentials_title),
 | 
			
		||||
                    "Nginx Credentials"
 | 
			
		||||
                ).toString(),
 | 
			
		||||
                settingsManager.getString(getString(R.string.nginx_credentials), "")
 | 
			
		||||
                    .toString(),  // key: the actual you use rn
 | 
			
		||||
                android.text.InputType.TYPE_TEXT_VARIATION_URI,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putString(getString(R.string.nginx_credentials), it)
 | 
			
		||||
                    .apply()  // change the stored url in nginx_url_key to it
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.nginx_url_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.showNginxTextInputDialog(
 | 
			
		||||
                settingsManager.getString(getString(R.string.nginx_url_pref), "Nginx server url")
 | 
			
		||||
                    .toString(),
 | 
			
		||||
                settingsManager.getString(getString(R.string.nginx_url_key), "")
 | 
			
		||||
                    .toString(),  // key: the actual you use rn
 | 
			
		||||
                android.text.InputType.TYPE_TEXT_VARIATION_URI,  // uri
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putString(getString(R.string.nginx_url_key), it)
 | 
			
		||||
                    .apply()  // change the stored url in nginx_url_key to it
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,295 @@
 | 
			
		|||
package com.lagradost.cloudstream3.ui.settings
 | 
			
		||||
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.os.Environment
 | 
			
		||||
import androidx.activity.result.contract.ActivityResultContracts
 | 
			
		||||
import androidx.preference.PreferenceFragmentCompat
 | 
			
		||||
import androidx.preference.PreferenceManager
 | 
			
		||||
import com.hippo.unifile.UniFile
 | 
			
		||||
import com.lagradost.cloudstream3.AcraApplication
 | 
			
		||||
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.settings.SettingsFragment.Companion.getFolderSize
 | 
			
		||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref
 | 
			
		||||
import com.lagradost.cloudstream3.ui.subtitles.ChromecastSubtitlesFragment
 | 
			
		||||
import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment
 | 
			
		||||
import com.lagradost.cloudstream3.utils.Qualities
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
 | 
			
		||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
 | 
			
		||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath
 | 
			
		||||
import java.io.File
 | 
			
		||||
 | 
			
		||||
class SettingsPlayer : PreferenceFragmentCompat() {
 | 
			
		||||
    // 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.settings_player, rootKey)
 | 
			
		||||
        val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext())
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.video_buffer_length_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.video_buffer_length_names)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.video_buffer_length_values)
 | 
			
		||||
 | 
			
		||||
            val currentPrefSize =
 | 
			
		||||
                settingsManager.getInt(getString(R.string.video_buffer_length_key), 0)
 | 
			
		||||
 | 
			
		||||
            activity?.showDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentPrefSize),
 | 
			
		||||
                getString(R.string.video_buffer_length_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.video_buffer_length_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
        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
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.prefer_limit_title_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.limit_title_pref_names)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.limit_title_pref_values)
 | 
			
		||||
            val current = settingsManager.getInt(getString(R.string.prefer_limit_title_key), 0)
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(current),
 | 
			
		||||
                getString(R.string.limit_title),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.prefer_limit_title_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /*(getPref(R.string.double_tap_seek_time_key) as? SeekBarPreference?)?.let {
 | 
			
		||||
 | 
			
		||||
        }*/
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.prefer_limit_title_rez_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.limit_title_rez_pref_names)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.limit_title_rez_pref_values)
 | 
			
		||||
            val current = settingsManager.getInt(getString(R.string.prefer_limit_title_rez_key), 3)
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(current),
 | 
			
		||||
                getString(R.string.limit_title_rez),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.prefer_limit_title_rez_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.quality_pref_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefValues = Qualities.values().map { it.value }.reversed().toMutableList()
 | 
			
		||||
            prefValues.remove(Qualities.Unknown.value)
 | 
			
		||||
 | 
			
		||||
            val prefNames = prefValues.map { Qualities.getStringByInt(it) }
 | 
			
		||||
 | 
			
		||||
            val currentQuality =
 | 
			
		||||
                settingsManager.getInt(
 | 
			
		||||
                    getString(R.string.quality_pref_key),
 | 
			
		||||
                    Qualities.values().last().value
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentQuality),
 | 
			
		||||
                getString(R.string.watch_quality_pref),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit().putInt(getString(R.string.quality_pref_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.subtitle_settings_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            SubtitlesFragment.push(activity, false)
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.subtitle_settings_chromecast_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            ChromecastSubtitlesFragment.push(activity, false)
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.video_buffer_disk_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.video_buffer_size_names)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.video_buffer_size_values)
 | 
			
		||||
 | 
			
		||||
            val currentPrefSize =
 | 
			
		||||
                settingsManager.getInt(getString(R.string.video_buffer_disk_key), 0)
 | 
			
		||||
 | 
			
		||||
            activity?.showDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentPrefSize),
 | 
			
		||||
                getString(R.string.video_buffer_disk_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.video_buffer_disk_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
        getPref(R.string.video_buffer_size_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.video_buffer_size_names)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.video_buffer_size_values)
 | 
			
		||||
 | 
			
		||||
            val currentPrefSize =
 | 
			
		||||
                settingsManager.getInt(getString(R.string.video_buffer_size_key), 0)
 | 
			
		||||
 | 
			
		||||
            activity?.showDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentPrefSize),
 | 
			
		||||
                getString(R.string.video_buffer_size_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                settingsManager.edit()
 | 
			
		||||
                    .putInt(getString(R.string.video_buffer_size_key), prefValues[it])
 | 
			
		||||
                    .apply()
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.video_buffer_clear_key)?.let { pref ->
 | 
			
		||||
            val cacheDir = context?.cacheDir ?: return@let
 | 
			
		||||
 | 
			
		||||
            fun updateSummery() {
 | 
			
		||||
                try {
 | 
			
		||||
                    pref.summary =
 | 
			
		||||
                        getString(R.string.mb_format).format(getFolderSize(cacheDir) / (1024L * 1024L))
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            updateSummery()
 | 
			
		||||
 | 
			
		||||
            pref.setOnPreferenceClickListener {
 | 
			
		||||
                try {
 | 
			
		||||
                    cacheDir.deleteRecursively()
 | 
			
		||||
                    updateSummery()
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
                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
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,123 @@
 | 
			
		|||
package com.lagradost.cloudstream3.ui.settings
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import androidx.preference.PreferenceFragmentCompat
 | 
			
		||||
import androidx.preference.PreferenceManager
 | 
			
		||||
import com.lagradost.cloudstream3.R
 | 
			
		||||
import com.lagradost.cloudstream3.mvvm.logError
 | 
			
		||||
import com.lagradost.cloudstream3.ui.search.SearchResultBuilder
 | 
			
		||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
 | 
			
		||||
 | 
			
		||||
class SettingsUI : PreferenceFragmentCompat() {
 | 
			
		||||
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
 | 
			
		||||
        hideKeyboard()
 | 
			
		||||
        setPreferencesFromResource(R.xml.settins_ui, rootKey)
 | 
			
		||||
        val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext())
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.poster_ui_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.poster_ui_options)
 | 
			
		||||
            val keys = resources.getStringArray(R.array.poster_ui_options_values)
 | 
			
		||||
            val prefValues = keys.map {
 | 
			
		||||
                settingsManager.getBoolean(it, true)
 | 
			
		||||
            }.mapIndexedNotNull { index, b ->
 | 
			
		||||
                if (b) {
 | 
			
		||||
                    index
 | 
			
		||||
                } else null
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            activity?.showMultiDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues,
 | 
			
		||||
                getString(R.string.poster_ui_settings),
 | 
			
		||||
                {}) { list ->
 | 
			
		||||
                val edit = settingsManager.edit()
 | 
			
		||||
                for ((i, key) in keys.withIndex()) {
 | 
			
		||||
                    edit.putBoolean(key, list.contains(i))
 | 
			
		||||
                }
 | 
			
		||||
                edit.apply()
 | 
			
		||||
                SearchResultBuilder.updateCache(it.context)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.app_layout_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.app_layout)
 | 
			
		||||
            val prefValues = resources.getIntArray(R.array.app_layout_values)
 | 
			
		||||
 | 
			
		||||
            val currentLayout =
 | 
			
		||||
                settingsManager.getInt(getString(R.string.app_layout_key), -1)
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentLayout),
 | 
			
		||||
                getString(R.string.app_layout),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                try {
 | 
			
		||||
                    settingsManager.edit()
 | 
			
		||||
                        .putInt(getString(R.string.app_layout_key), prefValues[it])
 | 
			
		||||
                        .apply()
 | 
			
		||||
                    activity?.recreate()
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.app_theme_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.themes_names)
 | 
			
		||||
            val prefValues = resources.getStringArray(R.array.themes_names_values)
 | 
			
		||||
 | 
			
		||||
            val currentLayout =
 | 
			
		||||
                settingsManager.getString(getString(R.string.app_theme_key), prefValues.first())
 | 
			
		||||
 | 
			
		||||
            activity?.showBottomDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentLayout),
 | 
			
		||||
                getString(R.string.app_theme_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                try {
 | 
			
		||||
                    settingsManager.edit()
 | 
			
		||||
                        .putString(getString(R.string.app_theme_key), prefValues[it])
 | 
			
		||||
                        .apply()
 | 
			
		||||
                    activity?.recreate()
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
        getPref(R.string.primary_color_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            val prefNames = resources.getStringArray(R.array.themes_overlay_names)
 | 
			
		||||
            val prefValues = resources.getStringArray(R.array.themes_overlay_names_values)
 | 
			
		||||
 | 
			
		||||
            val currentLayout =
 | 
			
		||||
                settingsManager.getString(getString(R.string.primary_color_key), prefValues.first())
 | 
			
		||||
 | 
			
		||||
            activity?.showDialog(
 | 
			
		||||
                prefNames.toList(),
 | 
			
		||||
                prefValues.indexOf(currentLayout),
 | 
			
		||||
                getString(R.string.primary_color_settings),
 | 
			
		||||
                true,
 | 
			
		||||
                {}) {
 | 
			
		||||
                try {
 | 
			
		||||
                    settingsManager.edit()
 | 
			
		||||
                        .putString(getString(R.string.primary_color_key), prefValues[it])
 | 
			
		||||
                        .apply()
 | 
			
		||||
                    activity?.recreate()
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,118 @@
 | 
			
		|||
package com.lagradost.cloudstream3.ui.settings
 | 
			
		||||
 | 
			
		||||
import android.content.ClipData
 | 
			
		||||
import android.content.ClipboardManager
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.widget.Toast
 | 
			
		||||
import androidx.appcompat.app.AlertDialog
 | 
			
		||||
import androidx.preference.PreferenceFragmentCompat
 | 
			
		||||
import androidx.preference.PreferenceManager
 | 
			
		||||
import com.lagradost.cloudstream3.CommonActivity
 | 
			
		||||
import com.lagradost.cloudstream3.R
 | 
			
		||||
import com.lagradost.cloudstream3.mvvm.logError
 | 
			
		||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref
 | 
			
		||||
import com.lagradost.cloudstream3.utils.BackupUtils.backup
 | 
			
		||||
import com.lagradost.cloudstream3.utils.BackupUtils.restorePrompt
 | 
			
		||||
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
 | 
			
		||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
 | 
			
		||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
 | 
			
		||||
import kotlinx.android.synthetic.main.logcat.*
 | 
			
		||||
import okhttp3.internal.closeQuietly
 | 
			
		||||
import java.io.BufferedReader
 | 
			
		||||
import java.io.InputStreamReader
 | 
			
		||||
import java.io.OutputStream
 | 
			
		||||
import kotlin.concurrent.thread
 | 
			
		||||
 | 
			
		||||
class SettingsUpdates : PreferenceFragmentCompat() {
 | 
			
		||||
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
 | 
			
		||||
        hideKeyboard()
 | 
			
		||||
        setPreferencesFromResource(R.xml.settings_updates, rootKey)
 | 
			
		||||
        val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.backup_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.backup()
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.restore_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            activity?.restorePrompt()
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
        getPref(R.string.show_logcat_key)?.setOnPreferenceClickListener { pref ->
 | 
			
		||||
            val builder =
 | 
			
		||||
                AlertDialog.Builder(pref.context, R.style.AlertDialogCustom)
 | 
			
		||||
                    .setView(R.layout.logcat)
 | 
			
		||||
 | 
			
		||||
            val dialog = builder.create()
 | 
			
		||||
            dialog.show()
 | 
			
		||||
            val log = StringBuilder()
 | 
			
		||||
            try {
 | 
			
		||||
                //https://developer.android.com/studio/command-line/logcat
 | 
			
		||||
                val process = Runtime.getRuntime().exec("logcat -d")
 | 
			
		||||
                val bufferedReader = BufferedReader(
 | 
			
		||||
                    InputStreamReader(process.inputStream)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                var line: String?
 | 
			
		||||
                while (bufferedReader.readLine().also { line = it } != null) {
 | 
			
		||||
                    log.append(line)
 | 
			
		||||
                }
 | 
			
		||||
            } catch (e: Exception) {
 | 
			
		||||
                logError(e) // kinda ironic
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val text = log.toString()
 | 
			
		||||
            dialog.text1?.text = text
 | 
			
		||||
 | 
			
		||||
            dialog.copy_btt?.setOnClickListener {
 | 
			
		||||
                val serviceClipboard =
 | 
			
		||||
                    (activity?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?)
 | 
			
		||||
                        ?: return@setOnClickListener
 | 
			
		||||
                val clip = ClipData.newPlainText("logcat", text)
 | 
			
		||||
                serviceClipboard.setPrimaryClip(clip)
 | 
			
		||||
                dialog.dismissSafe(activity)
 | 
			
		||||
            }
 | 
			
		||||
            dialog.clear_btt?.setOnClickListener {
 | 
			
		||||
                Runtime.getRuntime().exec("logcat -c")
 | 
			
		||||
                dialog.dismissSafe(activity)
 | 
			
		||||
            }
 | 
			
		||||
            dialog.save_btt?.setOnClickListener {
 | 
			
		||||
                var fileStream: OutputStream? = null
 | 
			
		||||
                try {
 | 
			
		||||
                    fileStream =
 | 
			
		||||
                        VideoDownloadManager.setupStream(
 | 
			
		||||
                            it.context,
 | 
			
		||||
                            "logcat",
 | 
			
		||||
                            null,
 | 
			
		||||
                            "txt",
 | 
			
		||||
                            false
 | 
			
		||||
                        ).fileStream
 | 
			
		||||
                    fileStream?.writer()?.write(text)
 | 
			
		||||
                } catch (e: Exception) {
 | 
			
		||||
                    logError(e)
 | 
			
		||||
                } finally {
 | 
			
		||||
                    fileStream?.closeQuietly()
 | 
			
		||||
                    dialog.dismissSafe(activity)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            dialog.close_btt?.setOnClickListener {
 | 
			
		||||
                dialog.dismissSafe(activity)
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        getPref(R.string.manual_check_update_key)?.setOnPreferenceClickListener {
 | 
			
		||||
            thread {
 | 
			
		||||
                if (!requireActivity().runAutoUpdate(false)) {
 | 
			
		||||
                    activity?.runOnUiThread {
 | 
			
		||||
                        CommonActivity.showToast(activity, R.string.no_update_found, Toast.LENGTH_SHORT)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return@setOnPreferenceClickListener true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -302,7 +302,8 @@ object UIHelper {
 | 
			
		|||
        return result
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun Context.fixPaddingStatusbar(v: View) {
 | 
			
		||||
    fun Context?.fixPaddingStatusbar(v: View?) {
 | 
			
		||||
        if (v == null || this == null) return
 | 
			
		||||
        v.setPadding(
 | 
			
		||||
            v.paddingLeft,
 | 
			
		||||
            v.paddingTop + getStatusBarHeight(),
 | 
			
		||||
| 
						 | 
				
			
			@ -385,7 +386,7 @@ object UIHelper {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    fun hideKeyboard(view: View?) {
 | 
			
		||||
        if(view == null) return
 | 
			
		||||
        if (view == null) return
 | 
			
		||||
 | 
			
		||||
        val inputMethodManager =
 | 
			
		||||
            view.context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										76
									
								
								app/src/main/res/layout/main_settings.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								app/src/main/res/layout/main_settings.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
        xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:background="?attr/primaryBlackBackground"
 | 
			
		||||
        android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
    <ScrollView
 | 
			
		||||
            app:layout_constraintTop_toTopOf="parent"
 | 
			
		||||
            app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content">
 | 
			
		||||
 | 
			
		||||
        <LinearLayout
 | 
			
		||||
                android:orientation="vertical"
 | 
			
		||||
                android:gravity="center_vertical"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content">
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                    android:nextFocusDown="@id/settings_lang"
 | 
			
		||||
 | 
			
		||||
                    android:id="@+id/settings_player"
 | 
			
		||||
                    style="@style/SettingsItem"
 | 
			
		||||
                    android:text="@string/category_player" />
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                    android:nextFocusUp="@id/settings_player"
 | 
			
		||||
                    android:nextFocusDown="@id/settings_ui"
 | 
			
		||||
 | 
			
		||||
                    android:id="@+id/settings_lang"
 | 
			
		||||
                    style="@style/SettingsItem"
 | 
			
		||||
                    android:text="@string/category_preferred_media_and_lang" />
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                    android:nextFocusUp="@id/settings_lang"
 | 
			
		||||
                    android:nextFocusDown="@id/settings_nginx"
 | 
			
		||||
 | 
			
		||||
                    android:id="@+id/settings_ui"
 | 
			
		||||
                    style="@style/SettingsItem"
 | 
			
		||||
                    android:text="@string/category_ui" />
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                    android:nextFocusUp="@id/settings_ui"
 | 
			
		||||
                    android:nextFocusDown="@id/settings_updates"
 | 
			
		||||
 | 
			
		||||
                    android:id="@+id/settings_nginx"
 | 
			
		||||
                    style="@style/SettingsItem"
 | 
			
		||||
                    android:text="@string/category_nginx" />
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                    android:nextFocusUp="@id/settings_nginx"
 | 
			
		||||
                    android:nextFocusDown="@id/settings_credits"
 | 
			
		||||
 | 
			
		||||
                    android:id="@+id/settings_updates"
 | 
			
		||||
                    style="@style/SettingsItem"
 | 
			
		||||
                    android:text="@string/category_updates" />
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                    android:nextFocusUp="@id/settings_updates"
 | 
			
		||||
 | 
			
		||||
                    android:id="@+id/settings_credits"
 | 
			
		||||
                    style="@style/SettingsItem"
 | 
			
		||||
                    android:text="@string/category_credits" />
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                    android:padding="10dp"
 | 
			
		||||
                    android:gravity="center"
 | 
			
		||||
                    android:layout_gravity="center"
 | 
			
		||||
                    android:textColor="?attr/textColor"
 | 
			
		||||
                    android:text="@string/app_version"
 | 
			
		||||
                    android:layout_width="wrap_content"
 | 
			
		||||
                    android:layout_height="wrap_content" />
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
    </ScrollView>
 | 
			
		||||
</androidx.constraintlayout.widget.ConstraintLayout>
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +86,69 @@
 | 
			
		|||
                android:defaultValue="true" />
 | 
			
		||||
    </action>
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_settings_player"
 | 
			
		||||
            android:name="com.lagradost.cloudstream3.ui.settings.SettingsPlayer"
 | 
			
		||||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim">
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_settings_player_to_navigation_subtitles"
 | 
			
		||||
                app:destination="@id/navigation_subtitles"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_settings_player_to_navigation_chrome_subtitles"
 | 
			
		||||
                app:destination="@id/navigation_chrome_subtitles"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
    </fragment>
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_settings_ui"
 | 
			
		||||
            android:name="com.lagradost.cloudstream3.ui.settings.SettingsUI"
 | 
			
		||||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_settings_lang"
 | 
			
		||||
            android:name="com.lagradost.cloudstream3.ui.settings.SettingsLang"
 | 
			
		||||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_settings_nginx"
 | 
			
		||||
            android:name="com.lagradost.cloudstream3.ui.settings.SettingsNginx"
 | 
			
		||||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_settings_updates"
 | 
			
		||||
            android:name="com.lagradost.cloudstream3.ui.settings.SettingsUpdates"
 | 
			
		||||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_settings_account"
 | 
			
		||||
            android:name="com.lagradost.cloudstream3.ui.settings.SettingsAccount"
 | 
			
		||||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
 | 
			
		||||
    <action
 | 
			
		||||
            android:id="@+id/global_to_navigation_quick_search"
 | 
			
		||||
            app:destination="@id/navigation_quick_search"
 | 
			
		||||
| 
						 | 
				
			
			@ -103,30 +166,6 @@
 | 
			
		|||
                android:defaultValue="@null" />
 | 
			
		||||
    </action>
 | 
			
		||||
 | 
			
		||||
    <action
 | 
			
		||||
            android:id="@+id/global_to_navigation_settings"
 | 
			
		||||
            app:destination="@id/navigation_settings"
 | 
			
		||||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
 | 
			
		||||
    <action
 | 
			
		||||
            android:id="@+id/global_to_navigation_downloads"
 | 
			
		||||
            app:destination="@id/navigation_downloads"
 | 
			
		||||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
 | 
			
		||||
    <action
 | 
			
		||||
            android:id="@+id/global_to_navigation_search"
 | 
			
		||||
            app:destination="@id/navigation_search"
 | 
			
		||||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_home"
 | 
			
		||||
            android:name="com.lagradost.cloudstream3.ui.home.HomeFragment"
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +174,22 @@
 | 
			
		|||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim">
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_home_to_navigation_results"
 | 
			
		||||
                app:destination="@id/navigation_results"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_home_to_navigation_quick_search"
 | 
			
		||||
                app:destination="@id/navigation_quick_search"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
    </fragment>
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_search"
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +199,15 @@
 | 
			
		|||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim">
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_search_to_navigation_results"
 | 
			
		||||
                app:destination="@id/navigation_results"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
    </fragment>
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_downloads"
 | 
			
		||||
| 
						 | 
				
			
			@ -159,7 +221,11 @@
 | 
			
		|||
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_downloads_to_navigation_download_child"
 | 
			
		||||
                app:destination="@id/navigation_download_child">
 | 
			
		||||
                app:destination="@id/navigation_download_child"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim">
 | 
			
		||||
            <argument
 | 
			
		||||
                    android:name="name"
 | 
			
		||||
                    app:argType="string" />
 | 
			
		||||
| 
						 | 
				
			
			@ -167,6 +233,20 @@
 | 
			
		|||
                    android:name="folder"
 | 
			
		||||
                    app:argType="string" />
 | 
			
		||||
        </action>
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_downloads_to_navigation_results"
 | 
			
		||||
                app:destination="@id/navigation_results"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_downloads_to_navigation_player"
 | 
			
		||||
                app:destination="@id/navigation_player"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
    </fragment>
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_settings"
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +256,50 @@
 | 
			
		|||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim">
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_settings_to_navigation_settings_nginx"
 | 
			
		||||
                app:destination="@id/navigation_settings_nginx"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_settings_to_navigation_settings_ui"
 | 
			
		||||
                app:destination="@id/navigation_settings_ui"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_settings_to_navigation_settings_lang"
 | 
			
		||||
                app:destination="@id/navigation_settings_lang"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_settings_to_navigation_settings_player"
 | 
			
		||||
                app:destination="@id/navigation_settings_player"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_settings_to_navigation_settings_updates"
 | 
			
		||||
                app:destination="@id/navigation_settings_updates"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_settings_to_navigation_settings_account"
 | 
			
		||||
                app:destination="@id/navigation_settings_account"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
    </fragment>
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_subtitles"
 | 
			
		||||
| 
						 | 
				
			
			@ -215,8 +338,15 @@
 | 
			
		|||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim"
 | 
			
		||||
            android:label="@string/title_settings" />
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim">
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_download_child_to_navigation_player"
 | 
			
		||||
                app:destination="@id/navigation_player"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
    </fragment>
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_results"
 | 
			
		||||
| 
						 | 
				
			
			@ -225,7 +355,22 @@
 | 
			
		|||
            app:enterAnim="@anim/enter_anim"
 | 
			
		||||
            app:exitAnim="@anim/exit_anim"
 | 
			
		||||
            app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
            app:popExitAnim="@anim/exit_anim">
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_results_to_navigation_quick_search"
 | 
			
		||||
                app:destination="@id/navigation_quick_search"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
        <action
 | 
			
		||||
                android:id="@+id/action_navigation_results_to_navigation_player"
 | 
			
		||||
                app:destination="@id/navigation_player"
 | 
			
		||||
                app:enterAnim="@anim/enter_anim"
 | 
			
		||||
                app:exitAnim="@anim/exit_anim"
 | 
			
		||||
                app:popEnterAnim="@anim/enter_anim"
 | 
			
		||||
                app:popExitAnim="@anim/exit_anim" />
 | 
			
		||||
    </fragment>
 | 
			
		||||
 | 
			
		||||
    <fragment
 | 
			
		||||
            android:id="@+id/navigation_player"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -182,7 +182,7 @@
 | 
			
		|||
    <string name="backup_failed_error_format">Yedekleme hatası %s</string>
 | 
			
		||||
 | 
			
		||||
    <string name="search">Ara</string>
 | 
			
		||||
    <string name="nginx_category">Nginx Ayarları</string>
 | 
			
		||||
    <string name="category_nginx">Nginx Ayarları</string>
 | 
			
		||||
    <string name="nginx_credentials_title">Nginx Kimlik Bilgileri</string>
 | 
			
		||||
    <string name="nginx_credentials_summary">Örnekteki formatta yazmalısın havalıkullanıcıadım:güvenlişifrem123</string>
 | 
			
		||||
    <string name="nginx_info_title">Nginx nedir?</string>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,6 +42,20 @@
 | 
			
		|||
        <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 characters</item>
 | 
			
		||||
| 
						 | 
				
			
			@ -59,6 +73,15 @@
 | 
			
		|||
        <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>1min</item>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@
 | 
			
		|||
    <string name="subtitle_settings_chromecast_key" translatable="false">subtitle_settings_chromecast_key</string>
 | 
			
		||||
    <string name="quality_pref_key" translatable="false">quality_pref_key</string>
 | 
			
		||||
    <string name="prefer_limit_title_key" translatable="false">prefer_limit_title_key</string>
 | 
			
		||||
    <string name="prefer_limit_title_rez_key" translatable="false">prefer_limit_title_rez_key</string>
 | 
			
		||||
    <string name="video_buffer_size_key" translatable="false">video_buffer_size_key</string>
 | 
			
		||||
    <string name="video_buffer_length_key" translatable="false">video_buffer_length_key</string>
 | 
			
		||||
    <string name="video_buffer_clear_key" translatable="false">video_buffer_clear_key</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +27,7 @@
 | 
			
		|||
    <string name="pip_enabled_key" translatable="false">pip_enabled_key</string>
 | 
			
		||||
    <string name="double_tap_enabled_key" translatable="false">double_tap_enabled_key</string>
 | 
			
		||||
    <string name="double_tap_pause_enabled_key" translatable="false">double_tap_pause_enabled_key</string>
 | 
			
		||||
    <string name="double_tap_seek_time_key" translatable="false">double_tap_seek_time_key</string>
 | 
			
		||||
    <string name="swipe_vertical_enabled_key" translatable="false">swipe_vertical_enabled_key</string>
 | 
			
		||||
    <string name="display_sub_key" translatable="false">display_sub_key</string>
 | 
			
		||||
    <string name="show_fillers_key" translatable="false">show_fillers_key</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -213,6 +215,7 @@
 | 
			
		|||
    <string name="swipe_to_change_settings_des">Swipe on the left or right side to change brightness or volume</string>
 | 
			
		||||
    <string name="double_tap_to_seek_settings">Double tap to seek</string>
 | 
			
		||||
    <string name="double_tap_to_pause_settings">Double tap to pause</string>
 | 
			
		||||
    <string name="double_tap_to_seek_amount_settings">Player seek amount</string>
 | 
			
		||||
    <string name="double_tap_to_seek_settings_des">Tap twice on the right or left side to seek forwards or backwards
 | 
			
		||||
    </string>
 | 
			
		||||
    <string name="double_tap_to_pause_settings_des">Tap in the middle to pause</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -236,7 +239,9 @@
 | 
			
		|||
    <string name="backup_failed_error_format">Error backing up %s</string>
 | 
			
		||||
 | 
			
		||||
    <string name="search">Search</string>
 | 
			
		||||
    <string name="nginx_category">Nginx Settings</string>
 | 
			
		||||
    <string name="category_nginx">Nginx</string>
 | 
			
		||||
    <string name="category_credits">Credits and account</string>
 | 
			
		||||
    <string name="category_updates">Updates and backup</string>
 | 
			
		||||
    <string name="nginx_credentials_title">Nginx Credential</string>
 | 
			
		||||
    <string name="nginx_credentials_summary">You have to use the following format mycoolusername:mysecurepassword123</string>
 | 
			
		||||
    <string name="nginx_info_title">What is Nginx ?</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -365,7 +370,9 @@
 | 
			
		|||
    <string name="skip_update">Skip this Update</string>
 | 
			
		||||
    <string name="update">Update</string>
 | 
			
		||||
    <string name="watch_quality_pref">Preferred watch quality</string>
 | 
			
		||||
    <string name="limit_title">Video player title max chars.</string>
 | 
			
		||||
    <string name="limit_title">Video player title max chars</string>
 | 
			
		||||
    <string name="limit_title_rez">Video player resolution</string>
 | 
			
		||||
 | 
			
		||||
    <string name="video_buffer_size_settings">Video buffer size</string>
 | 
			
		||||
    <string name="video_buffer_length_settings">Video buffer length</string>
 | 
			
		||||
    <string name="video_buffer_disk_settings">Video cache on disk</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -408,9 +415,11 @@
 | 
			
		|||
    <string name="general">General</string>
 | 
			
		||||
    <string name="random_button_settings">Random Button</string>
 | 
			
		||||
    <string name="random_button_settings_desc">Show random button on Homepage</string>
 | 
			
		||||
    <string name="provider_lang_settings">Provider Languages</string>
 | 
			
		||||
    <string name="provider_lang_settings">Provider languages</string>
 | 
			
		||||
    <string name="app_layout">App Layout</string>
 | 
			
		||||
    <string name="preferred_media_settings">Preferred Media</string>
 | 
			
		||||
    <string name="preferred_media_settings">Preferred media</string>
 | 
			
		||||
    <string name="category_preferred_media_and_lang">Preferred media and language</string>
 | 
			
		||||
    <string name="category_ui">User interface</string>
 | 
			
		||||
 | 
			
		||||
    <string name="automatic">Auto</string>
 | 
			
		||||
    <string name="tv_layout">TV layout</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -507,4 +516,8 @@
 | 
			
		|||
    <string name="quality_webrip">Web</string>
 | 
			
		||||
 | 
			
		||||
    <string name="poster_image">Poster Image</string>
 | 
			
		||||
    <string name="category_player">Player</string>
 | 
			
		||||
    <string name="resolution_and_title">Resolution and title</string>
 | 
			
		||||
    <string name="title">Title</string>
 | 
			
		||||
    <string name="resolution">Resolution</string>
 | 
			
		||||
</resources>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,313 +0,0 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
        xmlns:app="http://schemas.android.com/apk/res-auto">
 | 
			
		||||
    <PreferenceCategory />
 | 
			
		||||
    <PreferenceCategory
 | 
			
		||||
            android:key="video"
 | 
			
		||||
            android:title="Player"
 | 
			
		||||
            app:isPreferenceVisible="true">
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/subtitle_settings_key"
 | 
			
		||||
                android:title="@string/player_subtitles_settings"
 | 
			
		||||
                android:icon="@drawable/ic_outline_subtitles_24"
 | 
			
		||||
                app:summary="@string/player_subtitles_settings_des" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/subtitle_settings_chromecast_key"
 | 
			
		||||
                android:title="@string/chromecast_subtitles_settings"
 | 
			
		||||
                android:icon="@drawable/ic_outline_subtitles_24"
 | 
			
		||||
                app:summary="@string/chromecast_subtitles_settings_des" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/quality_pref_key"
 | 
			
		||||
                android:title="@string/watch_quality_pref"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_hd_24" />
 | 
			
		||||
        <Preference
 | 
			
		||||
            android:key="@string/prefer_limit_title_key"
 | 
			
		||||
            android:title="@string/limit_title"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_text_format_24" />
 | 
			
		||||
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_picture_in_picture_alt_24"
 | 
			
		||||
                app:key="@string/pip_enabled_key"
 | 
			
		||||
                android:title="@string/picture_in_picture"
 | 
			
		||||
                android:summary="@string/picture_in_picture_des"
 | 
			
		||||
                app:defaultValue="true" />
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_aspect_ratio_24"
 | 
			
		||||
                app:key="@string/player_resize_enabled_key"
 | 
			
		||||
                android:title="@string/player_size_settings"
 | 
			
		||||
                android:summary="@string/player_size_settings_des"
 | 
			
		||||
                app:defaultValue="true" />
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_speed_24"
 | 
			
		||||
                app:key="@string/playback_speed_enabled_key"
 | 
			
		||||
                android:title="@string/eigengraumode_settings"
 | 
			
		||||
                android:summary="@string/eigengraumode_settings_des"
 | 
			
		||||
                app:defaultValue="false" />
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_ondemand_video_24"
 | 
			
		||||
                app:key="@string/swipe_enabled_key"
 | 
			
		||||
                android:title="@string/swipe_to_seek_settings"
 | 
			
		||||
                android:summary="@string/swipe_to_seek_settings_des"
 | 
			
		||||
                app:defaultValue="true" />
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_ondemand_video_24"
 | 
			
		||||
                app:key="@string/swipe_vertical_enabled_key"
 | 
			
		||||
                android:title="@string/swipe_to_change_settings"
 | 
			
		||||
                android:summary="@string/swipe_to_change_settings_des"
 | 
			
		||||
                app:defaultValue="true" />
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_touch_app_24"
 | 
			
		||||
                app:key="@string/double_tap_enabled_key"
 | 
			
		||||
                android:title="@string/double_tap_to_seek_settings"
 | 
			
		||||
                android:summary="@string/double_tap_to_seek_settings_des"
 | 
			
		||||
                app:defaultValue="false" />
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/netflix_pause"
 | 
			
		||||
                app:key="@string/double_tap_pause_enabled_key"
 | 
			
		||||
                android:title="@string/double_tap_to_pause_settings"
 | 
			
		||||
                android:summary="@string/double_tap_to_pause_settings_des"
 | 
			
		||||
                app:defaultValue="false" />
 | 
			
		||||
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/baseline_sync_24"
 | 
			
		||||
                app:key="@string/episode_sync_enabled_key"
 | 
			
		||||
                android:title="@string/episode_sync_settings"
 | 
			
		||||
                android:summary="@string/episode_sync_settings_des"
 | 
			
		||||
                app:defaultValue="true" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/video_buffer_disk_key"
 | 
			
		||||
                android:title="@string/video_buffer_disk_settings"
 | 
			
		||||
                android:summary="@string/video_disk_description"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_storage_24" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/video_buffer_size_key"
 | 
			
		||||
                android:title="@string/video_buffer_size_settings"
 | 
			
		||||
                android:summary="@string/video_ram_description"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_storage_24" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/video_buffer_length_key"
 | 
			
		||||
                android:title="@string/video_buffer_length_settings"
 | 
			
		||||
                android:summary="@string/video_ram_description"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_storage_24" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/video_buffer_clear_key"
 | 
			
		||||
                android:title="@string/video_buffer_clear_settings"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_delete_outline_24" />
 | 
			
		||||
        <!--
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_brightness_7_24"
 | 
			
		||||
                app:key="@string/use_system_brightness_key"
 | 
			
		||||
                android:title="@string/use_system_brightness_settings"
 | 
			
		||||
                android:summary="@string/use_system_brightness_settings_des"
 | 
			
		||||
                app:defaultValue="false"
 | 
			
		||||
        />
 | 
			
		||||
        -->
 | 
			
		||||
    </PreferenceCategory>
 | 
			
		||||
    <PreferenceCategory
 | 
			
		||||
            android:key="general"
 | 
			
		||||
            android:title="@string/general"
 | 
			
		||||
            app:isPreferenceVisible="true">
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_play_arrow_24"
 | 
			
		||||
            app:key="@string/random_button_key"
 | 
			
		||||
            android:title="@string/random_button_settings"
 | 
			
		||||
            android:summary="@string/random_button_settings_desc"
 | 
			
		||||
            app:defaultValue="false" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_language_24"
 | 
			
		||||
                android:key="@string/provider_lang_key"
 | 
			
		||||
                android:title="@string/provider_lang_settings" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/locale_key"
 | 
			
		||||
                android:title="@string/app_language"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_language_24" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/prefer_media_type_key"
 | 
			
		||||
                android:title="@string/preferred_media_settings"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_play_arrow_24" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/display_sub_key"
 | 
			
		||||
                android:title="@string/display_subbed_dubbed_settings"
 | 
			
		||||
                android:icon="@drawable/ic_outline_voice_over_off_24" />
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:key="@string/show_fillers_key"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_skip_next_24"
 | 
			
		||||
                android:title="@string/show_fillers_settings"
 | 
			
		||||
                android:defaultValue="false" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/dns_key"
 | 
			
		||||
                android:title="@string/dns_pref"
 | 
			
		||||
                android:summary="@string/dns_pref_summary"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_dns_24" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/download_path_key"
 | 
			
		||||
                android:title="@string/download_path_pref"
 | 
			
		||||
                android:icon="@drawable/netflix_download" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_tv_24"
 | 
			
		||||
                android:key="@string/app_layout_key"
 | 
			
		||||
                android:title="@string/app_layout" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_color_lens_24"
 | 
			
		||||
                android:key="@string/primary_color_key"
 | 
			
		||||
                android:title="@string/primary_color_settings" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_color_lens_24"
 | 
			
		||||
                android:key="@string/app_theme_key"
 | 
			
		||||
                android:title="@string/app_theme_settings" />
 | 
			
		||||
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:defaultValue="true"
 | 
			
		||||
                android:icon="@drawable/baseline_grid_view_24"
 | 
			
		||||
                android:key="@string/bottom_title_key"
 | 
			
		||||
                android:summary="@string/bottom_title_settings_des"
 | 
			
		||||
                android:title="@string/bottom_title_settings" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:icon="@drawable/ic_baseline_tv_24"
 | 
			
		||||
                android:key="@string/poster_ui_key"
 | 
			
		||||
                android:title="@string/poster_ui_settings" />
 | 
			
		||||
    </PreferenceCategory>
 | 
			
		||||
    <PreferenceCategory
 | 
			
		||||
            android:key="search"
 | 
			
		||||
            android:title="@string/search"
 | 
			
		||||
            app:isPreferenceVisible="true">
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/search_icon"
 | 
			
		||||
                app:key="advanced_search"
 | 
			
		||||
                android:title="@string/advanced_search"
 | 
			
		||||
                android:summary="@string/advanced_search_des"
 | 
			
		||||
                app:defaultValue="true" />
 | 
			
		||||
    </PreferenceCategory>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <PreferenceCategory
 | 
			
		||||
        android:key="@string/nginx_category"
 | 
			
		||||
        android:title="@string/nginx_category"
 | 
			
		||||
        app:isPreferenceVisible="true">
 | 
			
		||||
        <Preference
 | 
			
		||||
            android:key="@string/nginx_url_key"
 | 
			
		||||
            android:title="@string/nginx_url_pref"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_play_arrow_24" />
 | 
			
		||||
        <Preference
 | 
			
		||||
            android:key="@string/nginx_credentials"
 | 
			
		||||
            android:title="@string/nginx_credentials_title"
 | 
			
		||||
            android:icon="@drawable/video_locked"
 | 
			
		||||
            android:summary="@string/nginx_credentials_summary"/>
 | 
			
		||||
        <Preference
 | 
			
		||||
            android:key="@string/nginx_info"
 | 
			
		||||
            android:title="@string/nginx_info_title"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_play_arrow_24"
 | 
			
		||||
	        android:summary="@string/nginx_info_summary" >
 | 
			
		||||
            <intent
 | 
			
		||||
                android:action="android.intent.action.VIEW"
 | 
			
		||||
                android:data="https://www.sarlays.com/use-nginx-with-cloudstream/" />
 | 
			
		||||
        </Preference>
 | 
			
		||||
    </PreferenceCategory>
 | 
			
		||||
 | 
			
		||||
    <PreferenceCategory
 | 
			
		||||
            android:key="info"
 | 
			
		||||
            android:title="@string/settings_info"
 | 
			
		||||
            app:isPreferenceVisible="true">
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/legal_notice_key"
 | 
			
		||||
                android:title="@string/legal_notice"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_warning_24" />
 | 
			
		||||
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:key="acra.disable"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_bug_report_24"
 | 
			
		||||
                android:title="@string/pref_disable_acra"
 | 
			
		||||
                android:summaryOff="@string/bug_report_settings_off"
 | 
			
		||||
                android:summaryOn="@string/bug_report_settings_on"
 | 
			
		||||
                android:defaultValue="false" />
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                app:key="@string/auto_update_key"
 | 
			
		||||
                android:title="@string/updates_settings"
 | 
			
		||||
                android:summary="@string/updates_settings_des"
 | 
			
		||||
                app:defaultValue="true"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_notifications_active_24" />
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                app:key="@string/prerelease_update_key"
 | 
			
		||||
                android:title="@string/uprereleases_settings"
 | 
			
		||||
                android:summary="@string/uprereleases_settings_des"
 | 
			
		||||
                app:defaultValue="false"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_developer_mode_24" />
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:title="@string/check_for_update"
 | 
			
		||||
                app:summary="@string/app_version"
 | 
			
		||||
                app:key="@string/manual_check_update_key"
 | 
			
		||||
                app:icon="@drawable/ic_baseline_system_update_24" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:icon="@drawable/baseline_save_as_24"
 | 
			
		||||
                android:key="@string/backup_key"
 | 
			
		||||
                android:title="@string/backup_settings" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:icon="@drawable/baseline_restore_page_24"
 | 
			
		||||
                android:key="@string/restore_key"
 | 
			
		||||
                android:title="@string/restore_settings" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/show_logcat_key"
 | 
			
		||||
                android:title="@string/show_log_cat"
 | 
			
		||||
                android:icon="@drawable/baseline_description_24" />
 | 
			
		||||
 | 
			
		||||
        <!--<SwitchPreference
 | 
			
		||||
                android:defaultValue="false"
 | 
			
		||||
                android:key="@string/log_enabled_key"
 | 
			
		||||
                android:title="@string/toggle_logcat"
 | 
			
		||||
                android:summary="@string/toggle_logcat_des"
 | 
			
		||||
                android:icon="@drawable/baseline_description_24" />-->
 | 
			
		||||
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
                android:icon="@drawable/netflix_download"
 | 
			
		||||
                android:key="@string/killswitch_key"
 | 
			
		||||
                android:defaultValue="true"
 | 
			
		||||
                android:summary="@string/killswitch_settings_des"
 | 
			
		||||
                android:title="@string/killswitch_settings" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/mal_key"
 | 
			
		||||
                android:icon="@drawable/mal_logo" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/anilist_key"
 | 
			
		||||
                android:icon="@drawable/ic_anilist_icon" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:title="@string/github"
 | 
			
		||||
                android:icon="@drawable/ic_github_logo"
 | 
			
		||||
                app:summary="https://github.com/LagradOst/CloudStream-3">
 | 
			
		||||
            <intent
 | 
			
		||||
                    android:action="android.intent.action.VIEW"
 | 
			
		||||
                    android:data="https://github.com/LagradOst/CloudStream-3" />
 | 
			
		||||
        </Preference>
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:title="@string/lightnovel"
 | 
			
		||||
                android:icon="@drawable/quick_novel_icon"
 | 
			
		||||
                app:summary="https://github.com/LagradOst/QuickNovel">
 | 
			
		||||
            <intent
 | 
			
		||||
                    android:action="android.intent.action.VIEW"
 | 
			
		||||
                    android:data="https://github.com/LagradOst/QuickNovel" />
 | 
			
		||||
        </Preference>
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:title="@string/discord"
 | 
			
		||||
                android:icon="@drawable/ic_baseline_discord_24"
 | 
			
		||||
                app:summary="https://discord.gg/5Hus6fM">
 | 
			
		||||
            <intent
 | 
			
		||||
                    android:action="android.intent.action.VIEW"
 | 
			
		||||
                    android:data="https://discord.gg/5Hus6fM" />
 | 
			
		||||
        </Preference>
 | 
			
		||||
        <Preference
 | 
			
		||||
                android:key="@string/benene_count"
 | 
			
		||||
                android:title="@string/benene"
 | 
			
		||||
                android:icon="@drawable/benene"
 | 
			
		||||
                app:summary="@string/benene_des" />
 | 
			
		||||
    </PreferenceCategory>
 | 
			
		||||
</PreferenceScreen>
 | 
			
		||||
							
								
								
									
										47
									
								
								app/src/main/res/xml/settings_credits_account.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/src/main/res/xml/settings_credits_account.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
        xmlns:app="http://schemas.android.com/apk/res-auto">
 | 
			
		||||
    <PreferenceCategory app:icon="@color/transparent" />
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/mal_key"
 | 
			
		||||
            android:icon="@drawable/mal_logo" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/anilist_key"
 | 
			
		||||
            android:icon="@drawable/ic_anilist_icon" />
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/legal_notice_key"
 | 
			
		||||
            android:title="@string/legal_notice"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_warning_24" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:title="@string/github"
 | 
			
		||||
            android:icon="@drawable/ic_github_logo"
 | 
			
		||||
            app:summary="https://github.com/LagradOst/CloudStream-3">
 | 
			
		||||
        <intent
 | 
			
		||||
                android:action="android.intent.action.VIEW"
 | 
			
		||||
                android:data="https://github.com/LagradOst/CloudStream-3" />
 | 
			
		||||
    </Preference>
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:title="@string/lightnovel"
 | 
			
		||||
            android:icon="@drawable/quick_novel_icon"
 | 
			
		||||
            app:summary="https://github.com/LagradOst/QuickNovel">
 | 
			
		||||
        <intent
 | 
			
		||||
                android:action="android.intent.action.VIEW"
 | 
			
		||||
                android:data="https://github.com/LagradOst/QuickNovel" />
 | 
			
		||||
    </Preference>
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:title="@string/discord"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_discord_24"
 | 
			
		||||
            app:summary="https://discord.gg/5Hus6fM">
 | 
			
		||||
        <intent
 | 
			
		||||
                android:action="android.intent.action.VIEW"
 | 
			
		||||
                android:data="https://discord.gg/5Hus6fM" />
 | 
			
		||||
    </Preference>
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/benene_count"
 | 
			
		||||
            android:title="@string/benene"
 | 
			
		||||
            android:icon="@drawable/benene"
 | 
			
		||||
            app:summary="@string/benene_des" />
 | 
			
		||||
</PreferenceScreen>
 | 
			
		||||
							
								
								
									
										23
									
								
								app/src/main/res/xml/settings_media_lang.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/src/main/res/xml/settings_media_lang.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
        xmlns:app="http://schemas.android.com/apk/res-auto">
 | 
			
		||||
    <PreferenceCategory app:icon="@color/transparent" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/locale_key"
 | 
			
		||||
            android:title="@string/app_language"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_language_24" />
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_language_24"
 | 
			
		||||
            android:key="@string/provider_lang_key"
 | 
			
		||||
            android:title="@string/provider_lang_settings" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/prefer_media_type_key"
 | 
			
		||||
            android:title="@string/preferred_media_settings"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_play_arrow_24" />
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/display_sub_key"
 | 
			
		||||
            android:title="@string/display_subbed_dubbed_settings"
 | 
			
		||||
            android:icon="@drawable/ic_outline_voice_over_off_24" />
 | 
			
		||||
</PreferenceScreen>
 | 
			
		||||
							
								
								
									
										24
									
								
								app/src/main/res/xml/settings_nginx.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/src/main/res/xml/settings_nginx.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
        xmlns:app="http://schemas.android.com/apk/res-auto">
 | 
			
		||||
    <PreferenceCategory app:icon="@color/transparent" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/nginx_url_key"
 | 
			
		||||
            android:title="@string/nginx_url_pref"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_play_arrow_24" />
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/nginx_credentials"
 | 
			
		||||
            android:title="@string/nginx_credentials_title"
 | 
			
		||||
            android:icon="@drawable/video_locked"
 | 
			
		||||
            android:summary="@string/nginx_credentials_summary" />
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/nginx_info"
 | 
			
		||||
            android:title="@string/nginx_info_title"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_play_arrow_24"
 | 
			
		||||
            android:summary="@string/nginx_info_summary">
 | 
			
		||||
        <intent
 | 
			
		||||
                android:action="android.intent.action.VIEW"
 | 
			
		||||
                android:data="https://www.sarlays.com/use-nginx-with-cloudstream/" />
 | 
			
		||||
    </Preference>
 | 
			
		||||
</PreferenceScreen>
 | 
			
		||||
							
								
								
									
										127
									
								
								app/src/main/res/xml/settings_player.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								app/src/main/res/xml/settings_player.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,127 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
        xmlns:app="http://schemas.android.com/apk/res-auto">
 | 
			
		||||
    <PreferenceCategory app:icon="@color/transparent" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/subtitle_settings_key"
 | 
			
		||||
            android:title="@string/player_subtitles_settings"
 | 
			
		||||
            android:icon="@drawable/ic_outline_subtitles_24"
 | 
			
		||||
            app:summary="@string/player_subtitles_settings_des" />
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/subtitle_settings_chromecast_key"
 | 
			
		||||
            android:title="@string/chromecast_subtitles_settings"
 | 
			
		||||
            android:icon="@drawable/ic_outline_subtitles_24"
 | 
			
		||||
            app:summary="@string/chromecast_subtitles_settings_des" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/dns_key"
 | 
			
		||||
            android:title="@string/dns_pref"
 | 
			
		||||
            android:summary="@string/dns_pref_summary"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_dns_24" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/download_path_key"
 | 
			
		||||
            android:title="@string/download_path_pref"
 | 
			
		||||
            android:icon="@drawable/netflix_download" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/quality_pref_key"
 | 
			
		||||
            android:title="@string/watch_quality_pref"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_hd_24" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/prefer_limit_title_key"
 | 
			
		||||
            android:title="@string/limit_title"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_text_format_24" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/prefer_limit_title_rez_key"
 | 
			
		||||
            android:title="@string/limit_title_rez"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_text_format_24" />
 | 
			
		||||
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_picture_in_picture_alt_24"
 | 
			
		||||
            app:key="@string/pip_enabled_key"
 | 
			
		||||
            android:title="@string/picture_in_picture"
 | 
			
		||||
            android:summary="@string/picture_in_picture_des"
 | 
			
		||||
            app:defaultValue="true" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_aspect_ratio_24"
 | 
			
		||||
            app:key="@string/player_resize_enabled_key"
 | 
			
		||||
            android:title="@string/player_size_settings"
 | 
			
		||||
            android:summary="@string/player_size_settings_des"
 | 
			
		||||
            app:defaultValue="true" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_speed_24"
 | 
			
		||||
            app:key="@string/playback_speed_enabled_key"
 | 
			
		||||
            android:title="@string/eigengraumode_settings"
 | 
			
		||||
            android:summary="@string/eigengraumode_settings_des"
 | 
			
		||||
            app:defaultValue="false" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_ondemand_video_24"
 | 
			
		||||
            app:key="@string/swipe_enabled_key"
 | 
			
		||||
            android:title="@string/swipe_to_seek_settings"
 | 
			
		||||
            android:summary="@string/swipe_to_seek_settings_des"
 | 
			
		||||
            app:defaultValue="true" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_ondemand_video_24"
 | 
			
		||||
            app:key="@string/swipe_vertical_enabled_key"
 | 
			
		||||
            android:title="@string/swipe_to_change_settings"
 | 
			
		||||
            android:summary="@string/swipe_to_change_settings_des"
 | 
			
		||||
            app:defaultValue="true" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_touch_app_24"
 | 
			
		||||
            app:key="@string/double_tap_enabled_key"
 | 
			
		||||
            android:title="@string/double_tap_to_seek_settings"
 | 
			
		||||
            android:summary="@string/double_tap_to_seek_settings_des"
 | 
			
		||||
            app:defaultValue="false" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/netflix_pause"
 | 
			
		||||
            app:key="@string/double_tap_pause_enabled_key"
 | 
			
		||||
            android:title="@string/double_tap_to_pause_settings"
 | 
			
		||||
            android:summary="@string/double_tap_to_pause_settings_des"
 | 
			
		||||
            app:defaultValue="false" />
 | 
			
		||||
 | 
			
		||||
    <SeekBarPreference
 | 
			
		||||
            app:icon="@drawable/go_forward_30"
 | 
			
		||||
            app:adjustable="true"
 | 
			
		||||
            android:defaultValue="10"
 | 
			
		||||
            app:min="5"
 | 
			
		||||
            app:seekBarIncrement="5"
 | 
			
		||||
            app:showSeekBarValue="true"
 | 
			
		||||
            android:max="60"
 | 
			
		||||
            app:key="@string/double_tap_seek_time_key"
 | 
			
		||||
            android:title="@string/double_tap_to_seek_amount_settings"
 | 
			
		||||
            app:defaultValue="false" />
 | 
			
		||||
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/baseline_sync_24"
 | 
			
		||||
            app:key="@string/episode_sync_enabled_key"
 | 
			
		||||
            android:title="@string/episode_sync_settings"
 | 
			
		||||
            android:summary="@string/episode_sync_settings_des"
 | 
			
		||||
            app:defaultValue="true" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/video_buffer_disk_key"
 | 
			
		||||
            android:title="@string/video_buffer_disk_settings"
 | 
			
		||||
            android:summary="@string/video_disk_description"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_storage_24" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/video_buffer_size_key"
 | 
			
		||||
            android:title="@string/video_buffer_size_settings"
 | 
			
		||||
            android:summary="@string/video_ram_description"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_storage_24" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/video_buffer_length_key"
 | 
			
		||||
            android:title="@string/video_buffer_length_settings"
 | 
			
		||||
            android:summary="@string/video_ram_description"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_storage_24" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/video_buffer_clear_key"
 | 
			
		||||
            android:title="@string/video_buffer_clear_settings"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_delete_outline_24" />
 | 
			
		||||
</PreferenceScreen>
 | 
			
		||||
							
								
								
									
										51
									
								
								app/src/main/res/xml/settings_updates.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/src/main/res/xml/settings_updates.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,51 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
        xmlns:app="http://schemas.android.com/apk/res-auto">
 | 
			
		||||
    <PreferenceCategory app:icon="@color/transparent" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:title="@string/check_for_update"
 | 
			
		||||
            app:summary="@string/app_version"
 | 
			
		||||
            app:key="@string/manual_check_update_key"
 | 
			
		||||
            app:icon="@drawable/ic_baseline_system_update_24" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:icon="@drawable/baseline_save_as_24"
 | 
			
		||||
            android:key="@string/backup_key"
 | 
			
		||||
            android:title="@string/backup_settings" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:icon="@drawable/baseline_restore_page_24"
 | 
			
		||||
            android:key="@string/restore_key"
 | 
			
		||||
            android:title="@string/restore_settings" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:key="@string/show_logcat_key"
 | 
			
		||||
            android:title="@string/show_log_cat"
 | 
			
		||||
            android:icon="@drawable/baseline_description_24" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:key="acra.disable"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_bug_report_24"
 | 
			
		||||
            android:title="@string/pref_disable_acra"
 | 
			
		||||
            android:summaryOff="@string/bug_report_settings_off"
 | 
			
		||||
            android:summaryOn="@string/bug_report_settings_on"
 | 
			
		||||
            android:defaultValue="false" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            app:key="@string/auto_update_key"
 | 
			
		||||
            android:title="@string/updates_settings"
 | 
			
		||||
            android:summary="@string/updates_settings_des"
 | 
			
		||||
            app:defaultValue="true"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_notifications_active_24" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            app:key="@string/prerelease_update_key"
 | 
			
		||||
            android:title="@string/uprereleases_settings"
 | 
			
		||||
            android:summary="@string/uprereleases_settings_des"
 | 
			
		||||
            app:defaultValue="false"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_developer_mode_24" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/netflix_download"
 | 
			
		||||
            android:key="@string/killswitch_key"
 | 
			
		||||
            android:defaultValue="true"
 | 
			
		||||
            android:summary="@string/killswitch_settings_des"
 | 
			
		||||
            android:title="@string/killswitch_settings" />
 | 
			
		||||
</PreferenceScreen>
 | 
			
		||||
							
								
								
									
										45
									
								
								app/src/main/res/xml/settins_ui.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/src/main/res/xml/settins_ui.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
        xmlns:app="http://schemas.android.com/apk/res-auto">
 | 
			
		||||
    <PreferenceCategory app:icon="@color/transparent" />
 | 
			
		||||
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_color_lens_24"
 | 
			
		||||
            android:key="@string/primary_color_key"
 | 
			
		||||
            android:title="@string/primary_color_settings" />
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_color_lens_24"
 | 
			
		||||
            android:key="@string/app_theme_key"
 | 
			
		||||
            android:title="@string/app_theme_settings" />
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_tv_24"
 | 
			
		||||
            android:key="@string/app_layout_key"
 | 
			
		||||
            android:title="@string/app_layout" />
 | 
			
		||||
    <Preference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_tv_24"
 | 
			
		||||
            android:key="@string/poster_ui_key"
 | 
			
		||||
            android:title="@string/poster_ui_settings" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/search_icon"
 | 
			
		||||
            app:key="advanced_search"
 | 
			
		||||
            android:title="@string/advanced_search"
 | 
			
		||||
            android:summary="@string/advanced_search_des"
 | 
			
		||||
            app:defaultValue="true" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:defaultValue="true"
 | 
			
		||||
            android:icon="@drawable/baseline_grid_view_24"
 | 
			
		||||
            android:key="@string/bottom_title_key"
 | 
			
		||||
            android:summary="@string/bottom_title_settings_des"
 | 
			
		||||
            android:title="@string/bottom_title_settings" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:key="@string/show_fillers_key"
 | 
			
		||||
            android:icon="@drawable/ic_baseline_skip_next_24"
 | 
			
		||||
            android:title="@string/show_fillers_settings"
 | 
			
		||||
            android:defaultValue="false" />
 | 
			
		||||
    <SwitchPreference
 | 
			
		||||
            android:icon="@drawable/ic_baseline_play_arrow_24"
 | 
			
		||||
            app:key="@string/random_button_key"
 | 
			
		||||
            android:title="@string/random_button_settings"
 | 
			
		||||
            android:summary="@string/random_button_settings_desc"
 | 
			
		||||
            app:defaultValue="false" />
 | 
			
		||||
</PreferenceScreen>
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue