Merge pull request #5969 from k9mail/locale_changes

Update name/description of notification channels when app locale changes
This commit is contained in:
cketti 2022-03-21 17:47:47 +01:00 committed by GitHub
commit 6c325f1185
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 142 additions and 6 deletions

View file

@ -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)

View file

@ -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>

View file

@ -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)
}
}

View file

@ -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()) }
}

View file

@ -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()
}
}
}

View file

@ -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()
}

View file

@ -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()