diff --git a/tools/lint/lint.xml b/tools/lint/lint.xml index 8b4b6ef617..3d3b073749 100644 --- a/tools/lint/lint.xml +++ b/tools/lint/lint.xml @@ -80,6 +80,7 @@ + diff --git a/vector-app/src/main/java/im/vector/app/VectorApplication.kt b/vector-app/src/main/java/im/vector/app/VectorApplication.kt index ee04d908e8..5e789d9504 100644 --- a/vector-app/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector-app/src/main/java/im/vector/app/VectorApplication.kt @@ -109,6 +109,7 @@ class VectorApplication : @Inject lateinit var fcmHelper: FcmHelper @Inject lateinit var buildMeta: BuildMeta @Inject lateinit var leakDetector: LeakDetector + @Inject lateinit var vectorLocale: VectorLocale // font thread handler private var fontThreadHandler: Handler? = null @@ -159,7 +160,7 @@ class VectorApplication : R.array.com_google_android_gms_fonts_certs ) FontsContractCompat.requestFont(this, fontRequest, emojiCompatFontProvider, getFontThreadHandler()) - VectorLocale.init(this, buildMeta) + vectorLocale.init() ThemeUtils.init(this) vectorConfiguration.applyToApplicationContext() diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt index b4ba384f8f..fbcfd69610 100644 --- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt +++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt @@ -84,6 +84,7 @@ import im.vector.app.features.rageshake.RageShake import im.vector.app.features.session.SessionListener import im.vector.app.features.settings.FontScalePreferences import im.vector.app.features.settings.FontScalePreferencesImpl +import im.vector.app.features.settings.VectorLocale import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.themes.ActivityOtherThemes import im.vector.app.features.themes.ThemeUtils @@ -155,6 +156,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver @Inject lateinit var rageShake: RageShake @Inject lateinit var buildMeta: BuildMeta @Inject lateinit var fontScalePreferences: FontScalePreferences + @Inject lateinit var vectorLocale: VectorLocale // For debug only @Inject lateinit var debugReceiver: DebugReceiver @@ -177,7 +179,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver override fun attachBaseContext(base: Context) { val fontScalePreferences = FontScalePreferencesImpl(PreferenceManager.getDefaultSharedPreferences(base), AndroidSystemSettingsProvider(base)) - val vectorConfiguration = VectorConfiguration(this, fontScalePreferences) + val vectorConfiguration = VectorConfiguration(this, fontScalePreferences, vectorLocale) super.attachBaseContext(vectorConfiguration.getLocalisedContext(base)) } diff --git a/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt b/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt index b0da4f0e18..bdb6cfb0d0 100644 --- a/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt +++ b/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt @@ -49,6 +49,7 @@ class JitsiService @Inject constructor( private val themeProvider: ThemeProvider, private val jitsiJWTFactory: JitsiJWTFactory, private val clock: Clock, + private val vectorLocale: VectorLocale, ) { companion object { @@ -163,7 +164,7 @@ class JitsiService @Inject constructor( if (widgetSessionId.length > 8) { widgetSessionId = widgetSessionId.substring(0, 7) } - roomId.substring(1, roomId.indexOf(":") - 1) + widgetSessionId.lowercase(VectorLocale.applicationLocale) + roomId.substring(1, roomId.indexOf(":") - 1) + widgetSessionId.lowercase(vectorLocale.applicationLocale) } } diff --git a/vector/src/main/java/im/vector/app/features/call/dialpad/CallDialPadBottomSheet.kt b/vector/src/main/java/im/vector/app/features/call/dialpad/CallDialPadBottomSheet.kt index 8bf2ce47bd..be38f7d509 100644 --- a/vector/src/main/java/im/vector/app/features/call/dialpad/CallDialPadBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/call/dialpad/CallDialPadBottomSheet.kt @@ -20,12 +20,15 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.extensions.addChildFragment import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.databinding.BottomSheetCallDialPadBinding import im.vector.app.features.settings.VectorLocale +import javax.inject.Inject +@AndroidEntryPoint class CallDialPadBottomSheet : VectorBaseBottomSheetDialogFragment() { companion object { @@ -41,6 +44,8 @@ class CallDialPadBottomSheet : VectorBaseBottomSheetDialogFragment() { } } - sectionsPagerAdapter = CallTransferPagerAdapter(this) + sectionsPagerAdapter = CallTransferPagerAdapter(this, vectorLocale) views.callTransferViewPager.adapter = sectionsPagerAdapter TabLayoutMediator(views.callTransferTabLayout, views.callTransferViewPager) { tab, position -> diff --git a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt index 3ec8f61978..f5ab172585 100644 --- a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt +++ b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt @@ -27,7 +27,8 @@ import im.vector.app.features.userdirectory.UserListFragment import im.vector.app.features.userdirectory.UserListFragmentArgs class CallTransferPagerAdapter( - private val fragmentActivity: FragmentActivity + private val fragmentActivity: FragmentActivity, + private val vectorLocale: VectorLocale, ) : FragmentStateAdapter(fragmentActivity) { companion object { @@ -61,7 +62,7 @@ class CallTransferPagerAdapter( arguments = Bundle().apply { putBoolean(DialPadFragment.EXTRA_ENABLE_DELETE, true) putBoolean(DialPadFragment.EXTRA_ENABLE_OK, false) - putString(DialPadFragment.EXTRA_REGION_CODE, VectorLocale.applicationLocale.country) + putString(DialPadFragment.EXTRA_REGION_CODE, vectorLocale.applicationLocale.country) } } } diff --git a/vector/src/main/java/im/vector/app/features/configuration/VectorConfiguration.kt b/vector/src/main/java/im/vector/app/features/configuration/VectorConfiguration.kt index a3d801e534..f67706dbd7 100644 --- a/vector/src/main/java/im/vector/app/features/configuration/VectorConfiguration.kt +++ b/vector/src/main/java/im/vector/app/features/configuration/VectorConfiguration.kt @@ -33,21 +33,22 @@ import javax.inject.Inject */ class VectorConfiguration @Inject constructor( private val context: Context, - private val fontScalePreferences: FontScalePreferences + private val fontScalePreferences: FontScalePreferences, + private val vectorLocale: VectorLocale, ) { fun onConfigurationChanged() { - if (Locale.getDefault().toString() != VectorLocale.applicationLocale.toString()) { + if (Locale.getDefault().toString() != vectorLocale.applicationLocale.toString()) { Timber.v("## onConfigurationChanged(): the locale has been updated to ${Locale.getDefault()}") - Timber.v("## onConfigurationChanged(): restore the expected value ${VectorLocale.applicationLocale}") - Locale.setDefault(VectorLocale.applicationLocale) + Timber.v("## onConfigurationChanged(): restore the expected value ${vectorLocale.applicationLocale}") + Locale.setDefault(vectorLocale.applicationLocale) } // Night mode may have changed ThemeUtils.init(context) } fun applyToApplicationContext() { - val locale = VectorLocale.applicationLocale + val locale = vectorLocale.applicationLocale val fontScale = fontScalePreferences.getResolvedFontScaleValue() Locale.setDefault(locale) @@ -67,7 +68,7 @@ class VectorConfiguration @Inject constructor( */ fun getLocalisedContext(context: Context): Context { try { - val locale = VectorLocale.applicationLocale + val locale = vectorLocale.applicationLocale // create new configuration passing old configuration from original Context val configuration = Configuration(context.resources.configuration) @@ -107,7 +108,7 @@ class VectorConfiguration @Inject constructor( * @return the local status value */ fun getHash(): String { - return (VectorLocale.applicationLocale.toString() + + return (vectorLocale.applicationLocale.toString() + "_" + fontScalePreferences.getResolvedFontScaleValue().preferenceValue + "_" + ThemeUtils.getApplicationTheme(context)) } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt index cf92afcc2e..4ee6126fb7 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep2Fragment.kt @@ -32,6 +32,7 @@ import im.vector.app.databinding.FragmentKeysBackupSetupStep2Binding import im.vector.app.features.settings.VectorLocale import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import javax.inject.Inject @AndroidEntryPoint class KeysBackupSetupStep2Fragment : @@ -43,6 +44,8 @@ class KeysBackupSetupStep2Fragment : private val zxcvbn = Zxcvbn() + @Inject lateinit var vectorLocale: VectorLocale + private fun onPassphraseChanged() { viewModel.passphrase.value = views.keysBackupSetupStep2PassphraseEnterEdittext.text.toString() viewModel.confirmPassphraseError.value = null @@ -78,12 +81,12 @@ class KeysBackupSetupStep2Fragment : views.keysBackupSetupStep2PassphraseStrengthLevel.strength = score if (score in 1..3) { - val warning = strength.feedback?.getWarning(VectorLocale.applicationLocale) + val warning = strength.feedback?.getWarning(vectorLocale.applicationLocale) if (warning != null) { views.keysBackupSetupStep2PassphraseEnterTil.error = warning } - val suggestions = strength.feedback?.getSuggestions(VectorLocale.applicationLocale) + val suggestions = strength.feedback?.getSuggestions(vectorLocale.applicationLocale) if (suggestions != null) { views.keysBackupSetupStep2PassphraseEnterTil.error = suggestions.firstOrNull() } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapEnterPassphraseFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapEnterPassphraseFragment.kt index 43cc25f195..de04e59245 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapEnterPassphraseFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapEnterPassphraseFragment.kt @@ -34,6 +34,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import reactivecircus.flowbinding.android.widget.editorActionEvents import reactivecircus.flowbinding.android.widget.textChanges +import javax.inject.Inject @AndroidEntryPoint class BootstrapEnterPassphraseFragment : @@ -43,6 +44,8 @@ class BootstrapEnterPassphraseFragment : return FragmentBootstrapEnterPassphraseBinding.inflate(inflater, container, false) } + @Inject lateinit var vectorLocale: VectorLocale + val sharedViewModel: BootstrapSharedViewModel by parentFragmentViewModel() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -105,8 +108,8 @@ class BootstrapEnterPassphraseFragment : views.ssssPassphraseSecurityProgress.strength = score if (score in 1..3) { val hint = - strength.feedback?.getWarning(VectorLocale.applicationLocale)?.takeIf { it.isNotBlank() } - ?: strength.feedback?.getSuggestions(VectorLocale.applicationLocale)?.firstOrNull() + strength.feedback?.getWarning(vectorLocale.applicationLocale)?.takeIf { it.isNotBlank() } + ?: strength.feedback?.getSuggestions(vectorLocale.applicationLocale)?.firstOrNull() if (hint != null && hint != views.ssssPassphraseEnterTil.error.toString()) { views.ssssPassphraseEnterTil.error = hint } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index 8eab759fcd..e4fa267af6 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -75,6 +75,7 @@ class HomeDetailFragment : @Inject lateinit var callManager: WebRtcCallManager @Inject lateinit var vectorPreferences: VectorPreferences @Inject lateinit var spaceStateHandler: SpaceStateHandler + @Inject lateinit var vectorLocale: VectorLocale private val viewModel: HomeDetailViewModel by fragmentViewModel() private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel() @@ -378,7 +379,7 @@ class HomeDetailFragment : arguments = Bundle().apply { putBoolean(DialPadFragment.EXTRA_ENABLE_DELETE, true) putBoolean(DialPadFragment.EXTRA_ENABLE_OK, true) - putString(DialPadFragment.EXTRA_REGION_CODE, VectorLocale.applicationLocale.country) + putString(DialPadFragment.EXTRA_REGION_CODE, vectorLocale.applicationLocale.country) } applyCallback() } diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index eefbf63a12..d22f3f9b58 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -80,6 +80,7 @@ class BugReporter @Inject constructor( private val buildMeta: BuildMeta, private val processInfo: ProcessInfo, private val sdkIntProvider: BuildVersionSdkIntProvider, + private val vectorLocale: VectorLocale, ) { var inMultiWindowMode = false @@ -294,7 +295,7 @@ class BugReporter @Inject constructor( Build.VERSION.INCREMENTAL + "-" + Build.VERSION.CODENAME ) .addFormDataPart("locale", Locale.getDefault().toString()) - .addFormDataPart("app_language", VectorLocale.applicationLocale.toString()) + .addFormDataPart("app_language", vectorLocale.applicationLocale.toString()) .addFormDataPart("default_app_language", systemLocaleProvider.getSystemLocale().toString()) .addFormDataPart("theme", ThemeUtils.getApplicationTheme(context)) .addFormDataPart("server_version", serverVersion) diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorLocale.kt b/vector/src/main/java/im/vector/app/features/settings/VectorLocale.kt index 4666d586d3..438434ed3c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorLocale.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorLocale.kt @@ -27,19 +27,27 @@ import kotlinx.coroutines.withContext import timber.log.Timber import java.util.IllformedLocaleException import java.util.Locale +import javax.inject.Inject +import javax.inject.Singleton /** * Object to manage the Locale choice of the user. */ -object VectorLocale { - private const val APPLICATION_LOCALE_COUNTRY_KEY = "APPLICATION_LOCALE_COUNTRY_KEY" - private const val APPLICATION_LOCALE_VARIANT_KEY = "APPLICATION_LOCALE_VARIANT_KEY" - private const val APPLICATION_LOCALE_LANGUAGE_KEY = "APPLICATION_LOCALE_LANGUAGE_KEY" - private const val APPLICATION_LOCALE_SCRIPT_KEY = "APPLICATION_LOCALE_SCRIPT_KEY" +@Singleton +class VectorLocale @Inject constructor( + private val context: Context, + private val buildMeta: BuildMeta, +) { + companion object { + private const val APPLICATION_LOCALE_COUNTRY_KEY = "APPLICATION_LOCALE_COUNTRY_KEY" + private const val APPLICATION_LOCALE_VARIANT_KEY = "APPLICATION_LOCALE_VARIANT_KEY" + private const val APPLICATION_LOCALE_LANGUAGE_KEY = "APPLICATION_LOCALE_LANGUAGE_KEY" + private const val APPLICATION_LOCALE_SCRIPT_KEY = "APPLICATION_LOCALE_SCRIPT_KEY" + private const val ISO_15924_LATN = "Latn" + } private val defaultLocale = Locale("en", "US") - private const val ISO_15924_LATN = "Latn" /** * The cache of supported application languages. @@ -52,15 +60,10 @@ object VectorLocale { var applicationLocale = defaultLocale private set - private lateinit var context: Context - private lateinit var buildMeta: BuildMeta - /** - * Init this object. + * Init this singleton. */ - fun init(context: Context, buildMeta: BuildMeta) { - this.context = context - this.buildMeta = buildMeta + fun init() { val preferences = DefaultSharedPreferences.getInstance(context) if (preferences.contains(APPLICATION_LOCALE_LANGUAGE_KEY)) { diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt index 3c8ec56713..073d5f7468 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt @@ -46,6 +46,7 @@ class VectorSettingsPreferencesFragment : @Inject lateinit var vectorPreferences: VectorPreferences @Inject lateinit var fontScalePreferences: FontScalePreferences @Inject lateinit var vectorFeatures: VectorFeatures + @Inject lateinit var vectorLocale: VectorLocale override var titleRes = R.string.settings_preferences override val preferenceXmlRes = R.xml.vector_settings_preferences @@ -198,7 +199,7 @@ class VectorSettingsPreferencesFragment : private fun setUserInterfacePreferences() { // Selected language - selectedLanguagePreference.summary = VectorLocale.localeToLocalisedString(VectorLocale.applicationLocale) + selectedLanguagePreference.summary = vectorLocale.localeToLocalisedString(vectorLocale.applicationLocale) // Text size textSizePreference.summary = getString(fontScalePreferences.getResolvedFontScaleValue().nameResId) diff --git a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt index 9853b28aae..0cbfef7495 100644 --- a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerController.kt @@ -37,13 +37,15 @@ import javax.inject.Inject class LocalePickerController @Inject constructor( private val vectorPreferences: VectorPreferences, private val stringProvider: StringProvider, - private val errorFormatter: ErrorFormatter + private val errorFormatter: ErrorFormatter, + private val vectorLocale: VectorLocale, ) : TypedEpoxyController() { var listener: Listener? = null override fun buildModels(data: LocalePickerViewState?) { val list = data?.locales ?: return + val currentLocale = data.currentLocale ?: return val host = this profileSectionItem { @@ -51,10 +53,10 @@ class LocalePickerController @Inject constructor( title(host.stringProvider.getString(R.string.choose_locale_current_locale_title)) } localeItem { - id(data.currentLocale.toString()) - title(VectorLocale.localeToLocalisedString(data.currentLocale).safeCapitalize(data.currentLocale)) + id(currentLocale.toString()) + title(host.vectorLocale.localeToLocalisedString(currentLocale).safeCapitalize(currentLocale)) if (host.vectorPreferences.developerMode()) { - subtitle(VectorLocale.localeToLocalisedStringInfo(data.currentLocale)) + subtitle(host.vectorLocale.localeToLocalisedStringInfo(currentLocale)) } clickListener { host.listener?.onUseCurrentClicked() } } @@ -78,13 +80,13 @@ class LocalePickerController @Inject constructor( } } else { list() - .filter { it.toString() != data.currentLocale.toString() } + .filter { it.toString() != currentLocale.toString() } .forEach { locale -> localeItem { id(locale.toString()) - title(VectorLocale.localeToLocalisedString(locale).safeCapitalize(locale)) + title(host.vectorLocale.localeToLocalisedString(locale).safeCapitalize(locale)) if (host.vectorPreferences.developerMode()) { - subtitle(VectorLocale.localeToLocalisedStringInfo(locale)) + subtitle(host.vectorLocale.localeToLocalisedStringInfo(locale)) } clickListener { host.listener?.onLocaleClicked(locale) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt index 0bbbc323e0..c38f9b5b87 100644 --- a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewModel.kt @@ -30,7 +30,8 @@ import kotlinx.coroutines.launch class LocalePickerViewModel @AssistedInject constructor( @Assisted initialState: LocalePickerViewState, - private val vectorConfiguration: VectorConfiguration + private val vectorConfiguration: VectorConfiguration, + private val vectorLocale: VectorLocale, ) : VectorViewModel(initialState) { @AssistedFactory @@ -39,8 +40,13 @@ class LocalePickerViewModel @AssistedInject constructor( } init { + setState { + copy( + currentLocale = vectorLocale.applicationLocale + ) + } viewModelScope.launch { - val result = VectorLocale.getSupportedLocales() + val result = vectorLocale.getSupportedLocales() setState { copy( @@ -59,7 +65,7 @@ class LocalePickerViewModel @AssistedInject constructor( } private fun handleSelectLocale(action: LocalePickerAction.SelectLocale) { - VectorLocale.saveApplicationLocale(action.locale) + vectorLocale.saveApplicationLocale(action.locale) vectorConfiguration.applyToApplicationContext() _viewEvents.post(LocalePickerViewEvents.RestartActivity) } diff --git a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewState.kt b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewState.kt index 8cb5978393..f981e7a444 100644 --- a/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewState.kt +++ b/vector/src/main/java/im/vector/app/features/settings/locale/LocalePickerViewState.kt @@ -19,10 +19,9 @@ package im.vector.app.features.settings.locale import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized -import im.vector.app.features.settings.VectorLocale import java.util.Locale data class LocalePickerViewState( - val currentLocale: Locale = VectorLocale.applicationLocale, + val currentLocale: Locale? = null, val locales: Async> = Uninitialized ) : MavericksState