Simplify locale override (#5509)

This commit is contained in:
Ivan Iskandar 2021-07-08 05:11:52 +07:00 committed by GitHub
parent 49cdcc644c
commit 37d30eb887
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 45 additions and 110 deletions

View file

@ -7,7 +7,6 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Configuration
import android.os.Build
import android.webkit.WebView
import androidx.core.app.NotificationManagerCompat
@ -28,7 +27,6 @@ import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.system.notification
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@ -68,8 +66,6 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
setupAcra()
setupNotificationChannels()
LocaleHelper.updateConfiguration(this, resources.configuration)
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
// Show notification to disable Incognito Mode when it's enabled
@ -106,11 +102,6 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
MultiDex.install(this)
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
LocaleHelper.updateConfiguration(this, newConfig, true)
}
override fun newImageLoader(): ImageLoader {
return ImageLoader.Builder(this).apply {
componentRegistry {

View file

@ -4,7 +4,6 @@ import android.os.Bundle
import androidx.viewbinding.ViewBinding
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
import eu.kanade.tachiyomi.util.system.LocaleHelper
import nucleus.view.NucleusAppCompatActivity
abstract class BaseRxActivity<VB : ViewBinding, P : BasePresenter<*>> : NucleusAppCompatActivity<P>() {
@ -14,11 +13,6 @@ abstract class BaseRxActivity<VB : ViewBinding, P : BasePresenter<*>> : NucleusA
lateinit var binding: VB
init {
@Suppress("LeakingThis")
LocaleHelper.updateConfiguration(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

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.appcompat.app.AppCompatDelegate
@ -8,6 +9,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.view.setSecureScreen
import kotlinx.coroutines.flow.launchIn
import uy.kohesive.injekt.Injekt
@ -18,6 +20,10 @@ abstract class BaseThemedActivity : AppCompatActivity() {
val preferences: PreferencesHelper by injectLazy()
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.createLocaleWrapper(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
applyThemePreferences(preferences)

View file

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.ui.base.activity
import android.content.Context
import android.os.Bundle
import androidx.viewbinding.ViewBinding
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
@ -12,9 +13,8 @@ abstract class BaseViewBindingActivity<VB : ViewBinding> : BaseThemedActivity()
@Suppress("LeakingThis")
private val secureActivityDelegate = SecureActivityDelegate(this)
init {
@Suppress("LeakingThis")
LocaleHelper.updateConfiguration(this)
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.createLocaleWrapper(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {

View file

@ -232,11 +232,7 @@ class SettingsGeneralController : SettingsController() {
summary = "%s"
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,11 +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 androidx.core.os.ConfigurationCompat
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.browse.source.SourcePresenter
@ -15,36 +15,10 @@ import java.util.Locale
/**
* Utility class to change the application's language in runtime.
*/
@Suppress("DEPRECATION")
object LocaleHelper {
private val preferences: PreferencesHelper by injectLazy()
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
*/
@ -60,18 +34,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))
}
/**
@ -87,57 +78,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 = ConfigurationCompat.getLocales(config)[0]
}
if (configChange) {
val configLocale = ConfigurationCompat.getLocales(config)[0]
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 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.locale = locale
} else {
newConfig.setLocale(locale)
}
return newConfig
return getLocale(pref)
}
}