Merge pull request #5969 from k9mail/locale_changes
Update name/description of notification channels when app locale changes
This commit is contained in:
commit
6c325f1185
7 changed files with 142 additions and 6 deletions
|
@ -6,6 +6,7 @@ import android.content.res.Resources
|
|||
import com.fsck.k9.activity.MessageCompose
|
||||
import com.fsck.k9.controller.MessagingController
|
||||
import com.fsck.k9.external.MessageProvider
|
||||
import com.fsck.k9.notification.NotificationChannelManager
|
||||
import com.fsck.k9.ui.base.AppLanguageManager
|
||||
import com.fsck.k9.ui.base.ThemeManager
|
||||
import com.fsck.k9.ui.base.extensions.currentLocale
|
||||
|
@ -13,6 +14,7 @@ import java.util.Locale
|
|||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
@ -25,6 +27,7 @@ class App : Application() {
|
|||
private val messagingListenerProvider: MessagingListenerProvider by inject()
|
||||
private val themeManager: ThemeManager by inject()
|
||||
private val appLanguageManager: AppLanguageManager by inject()
|
||||
private val notificationChannelManager: NotificationChannelManager by inject()
|
||||
private val appCoroutineScope: CoroutineScope = GlobalScope + Dispatchers.Main
|
||||
private var appLanguageManagerInitialized = false
|
||||
|
||||
|
@ -39,6 +42,7 @@ class App : Application() {
|
|||
Core.init(this)
|
||||
MessageProvider.init()
|
||||
initializeAppLanguage()
|
||||
updateNotificationChannelsOnAppLanguageChanges()
|
||||
themeManager.init()
|
||||
|
||||
messagingListenerProvider.listeners.forEach { listener ->
|
||||
|
@ -109,6 +113,13 @@ class App : Application() {
|
|||
return resources
|
||||
}
|
||||
|
||||
private fun updateNotificationChannelsOnAppLanguageChanges() {
|
||||
appLanguageManager.appLocale
|
||||
.distinctUntilChanged()
|
||||
.onEach { notificationChannelManager.updateChannels() }
|
||||
.launchIn(appCoroutineScope)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val appConfig = AppConfig(
|
||||
componentsToDisable = listOf(MessageCompose::class.java)
|
||||
|
|
|
@ -1,2 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.fsck.k9.ui.base" />
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.fsck.k9.ui.base">
|
||||
|
||||
<application>
|
||||
|
||||
<receiver
|
||||
android:name=".locale.LocaleBroadcastReceiver"
|
||||
android:exported="false"
|
||||
android:enabled="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.fsck.k9.ui.base
|
|||
import android.content.res.Resources
|
||||
import com.fsck.k9.K9
|
||||
import com.fsck.k9.ui.base.extensions.currentLocale
|
||||
import com.fsck.k9.ui.base.locale.SystemLocaleChangeListener
|
||||
import com.fsck.k9.ui.base.locale.SystemLocaleManager
|
||||
import java.util.Locale
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -19,11 +21,20 @@ import kotlinx.coroutines.plus
|
|||
* - Notifies listeners when the app language has changed.
|
||||
*/
|
||||
class AppLanguageManager(
|
||||
private val systemLocaleManager: SystemLocaleManager,
|
||||
private val coroutineScope: CoroutineScope = GlobalScope + Dispatchers.Main
|
||||
) {
|
||||
private var currentOverrideLocale: Locale? = null
|
||||
private val _overrideLocale = MutableSharedFlow<Locale?>(replay = 1)
|
||||
private val _appLocale = MutableSharedFlow<Locale>(replay = 1)
|
||||
val overrideLocale: Flow<Locale?> = _overrideLocale
|
||||
val appLocale: Flow<Locale> = _appLocale
|
||||
|
||||
private val systemLocaleListener = SystemLocaleChangeListener {
|
||||
coroutineScope.launch {
|
||||
_appLocale.emit(systemLocale)
|
||||
}
|
||||
}
|
||||
|
||||
fun init() {
|
||||
setLocale(K9.k9Language)
|
||||
|
@ -58,8 +69,15 @@ class AppLanguageManager(
|
|||
val locale = overrideLocale ?: systemLocale
|
||||
Locale.setDefault(locale)
|
||||
|
||||
if (overrideLocale == null) {
|
||||
systemLocaleManager.addListener(systemLocaleListener)
|
||||
} else {
|
||||
systemLocaleManager.removeListener(systemLocaleListener)
|
||||
}
|
||||
|
||||
coroutineScope.launch {
|
||||
_overrideLocale.emit(overrideLocale)
|
||||
_appLocale.emit(locale)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
package com.fsck.k9.ui.base
|
||||
|
||||
import com.fsck.k9.ui.base.locale.SystemLocaleManager
|
||||
import org.koin.core.qualifier.named
|
||||
import org.koin.dsl.module
|
||||
|
||||
val uiBaseModule = module {
|
||||
single { ThemeManager(context = get(), themeProvider = get(), generalSettingsManager = get(), appCoroutineScope = get(named("AppCoroutineScope"))) }
|
||||
single { AppLanguageManager() }
|
||||
single {
|
||||
ThemeManager(
|
||||
context = get(),
|
||||
themeProvider = get(),
|
||||
generalSettingsManager = get(),
|
||||
appCoroutineScope = get(named("AppCoroutineScope"))
|
||||
)
|
||||
}
|
||||
single { AppLanguageManager(systemLocaleManager = get()) }
|
||||
single { SystemLocaleManager(context = get()) }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package com.fsck.k9.ui.base.locale
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class LocaleBroadcastReceiver : BroadcastReceiver(), KoinComponent {
|
||||
private val systemLocaleManager: SystemLocaleManager by inject()
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent?) {
|
||||
if (intent?.action == Intent.ACTION_LOCALE_CHANGED) {
|
||||
systemLocaleManager.notifyListeners()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.fsck.k9.ui.base.locale
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import java.util.concurrent.CopyOnWriteArraySet
|
||||
import timber.log.Timber
|
||||
|
||||
class SystemLocaleManager(context: Context) {
|
||||
private val packageManager = context.packageManager
|
||||
private val componentName = ComponentName(context, LocaleBroadcastReceiver::class.java)
|
||||
|
||||
private val listeners = CopyOnWriteArraySet<SystemLocaleChangeListener>()
|
||||
|
||||
@Synchronized
|
||||
fun addListener(listener: SystemLocaleChangeListener) {
|
||||
if (listeners.isEmpty()) {
|
||||
enableReceiver()
|
||||
}
|
||||
|
||||
listeners.add(listener)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun removeListener(listener: SystemLocaleChangeListener) {
|
||||
listeners.remove(listener)
|
||||
|
||||
if (listeners.isEmpty()) {
|
||||
disableReceiver()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun notifyListeners() {
|
||||
for (listener in listeners) {
|
||||
listener.onSystemLocaleChanged()
|
||||
}
|
||||
}
|
||||
|
||||
private fun enableReceiver() {
|
||||
Timber.v("Enable LocaleBroadcastReceiver")
|
||||
try {
|
||||
packageManager.setComponentEnabledSetting(
|
||||
componentName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||
PackageManager.DONT_KILL_APP
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error enabling LocaleBroadcastReceiver")
|
||||
}
|
||||
}
|
||||
|
||||
private fun disableReceiver() {
|
||||
Timber.v("Disable LocaleBroadcastReceiver")
|
||||
try {
|
||||
packageManager.setComponentEnabledSetting(
|
||||
componentName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error disabling LocaleBroadcastReceiver")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun interface SystemLocaleChangeListener {
|
||||
fun onSystemLocaleChanged()
|
||||
}
|
|
@ -38,7 +38,6 @@ import com.fsck.k9.fragment.MessageListFragment.MessageListFragmentListener
|
|||
import com.fsck.k9.helper.Contacts
|
||||
import com.fsck.k9.helper.ParcelableUtil
|
||||
import com.fsck.k9.mailstore.SearchStatusManager
|
||||
import com.fsck.k9.notification.NotificationChannelManager
|
||||
import com.fsck.k9.preferences.GeneralSettingsManager
|
||||
import com.fsck.k9.search.LocalSearch
|
||||
import com.fsck.k9.search.SearchAccount
|
||||
|
@ -90,7 +89,6 @@ open class MessageList :
|
|||
|
||||
protected val searchStatusManager: SearchStatusManager by inject()
|
||||
private val preferences: Preferences by inject()
|
||||
private val channelUtils: NotificationChannelManager by inject()
|
||||
private val defaultFolderProvider: DefaultFolderProvider by inject()
|
||||
private val accountRemover: BackgroundAccountRemover by inject()
|
||||
private val generalSettingsManager: GeneralSettingsManager by inject()
|
||||
|
@ -205,7 +203,6 @@ open class MessageList :
|
|||
initializeFragments()
|
||||
displayViews()
|
||||
initializeRecentChangesSnackbar()
|
||||
channelUtils.updateChannels()
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
checkAndRequestPermissions()
|
||||
|
|
Loading…
Reference in a new issue