Simplify locale override (#5509)

Closes #906
This commit is contained in:
Ivan Iskandar 2021-07-08 05:11:52 +07:00 committed by Jays2Kings
parent 70529c85a8
commit ae65677a37
6 changed files with 48 additions and 119 deletions

View File

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi
import android.app.Application
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
@ -14,7 +13,6 @@ import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
import eu.kanade.tachiyomi.util.system.LocaleHelper
import org.acra.ACRA
import org.acra.config.httpSender
import org.acra.data.StringFormat
@ -54,7 +52,6 @@ open class App : Application(), LifecycleObserver {
setupAcra()
setupNotificationChannels()
LocaleHelper.updateConfiguration(this, resources.configuration)
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
// Reset Incognito Mode on relaunch
@ -75,11 +72,6 @@ open class App : Application(), LifecycleObserver {
MultiDex.install(this)
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
LocaleHelper.updateConfiguration(this, newConfig, true)
}
protected open fun setupAcra() {
initAcra {
reportFormat = StringFormat.JSON

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.ui.base.activity
import android.content.Context
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
@ -17,9 +18,8 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
lateinit var binding: VB
val isBindingInitialized get() = this::binding.isInitialized
init {
@Suppress("LeakingThis")
LocaleHelper.updateConfiguration(this)
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.createLocaleWrapper(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.ui.base.activity
import android.content.Context
import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
@ -11,9 +12,8 @@ abstract class BaseRxActivity<P : BasePresenter<*>> : NucleusAppCompatActivity<P
val scope = lifecycleScope
init {
@Suppress("LeakingThis")
LocaleHelper.updateConfiguration(this)
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.createLocaleWrapper(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -1,15 +1,21 @@
package eu.kanade.tachiyomi.ui.base.activity
import android.content.Context
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.util.system.setThemeAndNight
import eu.kanade.tachiyomi.util.system.LocaleHelper
import uy.kohesive.injekt.injectLazy
abstract class BaseThemedActivity : AppCompatActivity() {
val preferences: PreferencesHelper by injectLazy()
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.createLocaleWrapper(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
setThemeAndNight(preferences)
super.onCreate(savedInstanceState)

View File

@ -252,11 +252,7 @@ class SettingsGeneralController : SettingsController() {
defaultValue = ""
onChange { newValue ->
val activity = activity ?: return@onChange false
val app = activity.application
LocaleHelper.changeLocale(newValue.toString())
LocaleHelper.updateConfiguration(app, app.resources.configuration)
activity.recreate()
activity?.recreate()
true
}
}

View File

@ -1,10 +1,11 @@
package eu.kanade.tachiyomi.util.system
import android.app.Application
import android.content.Context
import android.content.ContextWrapper
import android.content.res.Configuration
import android.os.Build
import android.view.ContextThemeWrapper
import android.os.LocaleList
import androidx.core.os.LocaleListCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.source.SourcePresenter
@ -14,7 +15,6 @@ import java.util.Locale
/**
* Utility class to change the application's language in runtime.
*/
@Suppress("DEPRECATION")
object LocaleHelper {
/**
@ -22,34 +22,6 @@ object LocaleHelper {
*/
private val preferences: PreferencesHelper by injectLazy()
/**
* The system's locale.
*/
private var systemLocale: Locale? = null
/**
* The application's locale. When it's null, the system locale is used.
*/
private var appLocale = getLocaleFromString(preferences.lang().get())
/**
* The currently applied locale. Used to avoid losing the selected language after a non locale
* configuration change to the application.
*/
private var currentLocale: Locale? = null
/**
* Returns the locale for the value stored in preferences, or null if it's system language.
*
* @param pref the string value stored in preferences.
*/
fun getLocaleFromString(pref: String?): Locale? {
if (pref.isNullOrEmpty()) {
return null
}
return getLocale(pref)
}
/**
* Returns Display name of a string language code
*/
@ -65,18 +37,35 @@ object LocaleHelper {
/**
* Returns Display name of a string language code
*
* @param lang empty for system language
*/
fun getDisplayName(lang: String?): String {
return when (lang) {
null -> ""
"" -> {
systemLocale!!.getDisplayName(systemLocale).capitalize()
}
else -> {
val locale = getLocale(lang)
locale.getDisplayName(locale).capitalize()
}
if (lang == null) {
return ""
}
val locale = if (lang.isEmpty()) {
LocaleListCompat.getAdjustedDefault()[0]
} else {
getLocale(lang)
}
return locale.getDisplayName(locale).replaceFirstChar { it.uppercase(locale) }
}
/**
* Creates a ContextWrapper using selected Locale
*/
fun createLocaleWrapper(context: Context): ContextWrapper {
val appLocale = getLocaleFromString(preferences.lang().get())
val newConfiguration = Configuration(context.resources.configuration)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val localeList = LocaleList(appLocale)
newConfiguration.setLocales(localeList)
} else {
newConfiguration.setLocale(appLocale)
}
return ContextWrapper(context.createConfigurationContext(newConfiguration))
}
/*Return Locale from string language code
@ -92,68 +81,14 @@ object LocaleHelper {
}
/**
* Changes the application's locale with a new preference.
* Returns the locale for the value stored in preferences, defaults to main system language.
*
* @param pref the new value stored in preferences.
* @param pref the string value stored in preferences.
*/
fun changeLocale(pref: String) {
appLocale = getLocaleFromString(pref)
}
/**
* Updates the app's language to an activity.
*/
fun updateConfiguration(wrapper: ContextThemeWrapper) {
if (appLocale != null) {
val config = Configuration(preferences.context.resources.configuration)
config.setLocale(appLocale)
wrapper.applyOverrideConfiguration(config)
private fun getLocaleFromString(pref: String?): Locale {
if (pref.isNullOrEmpty()) {
return LocaleListCompat.getDefault()[0]
}
}
/**
* Updates the app's language to the application.
*/
fun updateConfiguration(app: Application, config: Configuration, configChange: Boolean = false) {
if (systemLocale == null) {
systemLocale = getConfigLocale(config)
}
if (configChange) {
val configLocale = getConfigLocale(config)
if (currentLocale == configLocale) {
return
}
systemLocale = configLocale
}
currentLocale = appLocale ?: systemLocale ?: Locale.getDefault()
val newConfig = updateConfigLocale(config, currentLocale!!)
val resources = app.resources
resources.updateConfiguration(newConfig, resources.displayMetrics)
Locale.setDefault(currentLocale)
}
/**
* Returns the locale applied in the given configuration.
*/
private fun getConfigLocale(config: Configuration): Locale {
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
config.locale
} else {
config.locales[0]
}
}
/**
* Returns a new configuration with the given locale applied.
*/
private fun updateConfigLocale(config: Configuration, locale: Locale): Configuration {
val newConfig = Configuration(config)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
newConfig.setLocale(locale)
} else {
newConfig.setLocale(locale)
}
return newConfig
return getLocale(pref)
}
}