Fixes i18n issue with shortcut names.

Some lock screen shortcut names were not updating to their translated
names when the user changed system language, remaining with the old
language in Settings and in Wallpaper Picker.

This CL fixes that issue.

The cause for the issue was how some pickerName properties were
implemented using a getter and some were constants, without a getter.
The constant ones were not being translated.

The approach in the CL is to actually move from a property to a method
call. This way, there is no choice but to recalculate the name of the
affordance every time; closing the door on the reintroduction of this
issue when a new config implementation is added with the developer
skipping the getter.

Fix: 280077350
Fix: 280829365
Fix: 278858630
Test: changed languages and verified that the shortcut names are updated
to the new language in both "Wallpaper & style" and in Display > Lock
screen

Change-Id: I2d3e3a621b6f24c42c1600ce4af17617dd52560a
This commit is contained in:
Alejandro Nijamkin
2023-05-30 16:52:02 -07:00
parent 79d9f58d95
commit 18bd504bce
14 changed files with 67 additions and 58 deletions

View File

@@ -52,8 +52,7 @@ constructor(
override val key: String
get() = BuiltInKeyguardQuickAffordanceKeys.CAMERA
override val pickerName: String
get() = context.getString(R.string.accessibility_camera_button)
override fun pickerName(): String = context.getString(R.string.accessibility_camera_button)
override val pickerIconResourceId: Int
get() = R.drawable.ic_camera

View File

@@ -99,7 +99,7 @@ constructor(
override val key: String = BuiltInKeyguardQuickAffordanceKeys.DO_NOT_DISTURB
override val pickerName: String = context.getString(R.string.quick_settings_dnd_label)
override fun pickerName(): String = context.getString(R.string.quick_settings_dnd_label)
override val pickerIconResourceId: Int = R.drawable.ic_do_not_disturb

View File

@@ -75,8 +75,7 @@ constructor(
override val key: String
get() = BuiltInKeyguardQuickAffordanceKeys.FLASHLIGHT
override val pickerName: String
get() = context.getString(R.string.quick_settings_flashlight_label)
override fun pickerName(): String = context.getString(R.string.quick_settings_flashlight_label)
override val pickerIconResourceId: Int
get() = R.drawable.ic_flashlight_off

View File

@@ -54,7 +54,7 @@ constructor(
override val key: String = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS
override val pickerName: String by lazy { context.getString(component.getTileTitleId()) }
override fun pickerName(): String = context.getString(component.getTileTitleId())
override val pickerIconResourceId: Int by lazy { component.getTileImageId() }

View File

@@ -31,8 +31,6 @@ interface KeyguardQuickAffordanceConfig {
/** Unique identifier for this quick affordance. It must be globally unique. */
val key: String
val pickerName: String
val pickerIconResourceId: Int
/**
@@ -42,6 +40,12 @@ interface KeyguardQuickAffordanceConfig {
*/
val lockScreenState: Flow<LockScreenState>
/**
* Returns a user-visible [String] that should be shown as the name for the option in the
* wallpaper picker / settings app to select this quick affordance.
*/
fun pickerName(): String
/**
* Returns the [PickerScreenState] representing the affordance in the settings or selector
* experience.

View File

@@ -34,6 +34,7 @@ import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.RingerModeTracker
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
@@ -45,30 +46,32 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
@SysUISingleton
class MuteQuickAffordanceConfig @Inject constructor(
context: Context,
private val userTracker: UserTracker,
private val userFileManager: UserFileManager,
private val ringerModeTracker: RingerModeTracker,
private val audioManager: AudioManager,
@Application private val coroutineScope: CoroutineScope,
@Main private val mainDispatcher: CoroutineDispatcher,
@Background private val backgroundDispatcher: CoroutineDispatcher,
class MuteQuickAffordanceConfig
@Inject
constructor(
private val context: Context,
private val userTracker: UserTracker,
private val userFileManager: UserFileManager,
private val ringerModeTracker: RingerModeTracker,
private val audioManager: AudioManager,
@Application private val coroutineScope: CoroutineScope,
@Main private val mainDispatcher: CoroutineDispatcher,
@Background private val backgroundDispatcher: CoroutineDispatcher,
) : KeyguardQuickAffordanceConfig {
private var previousNonSilentMode: Int = DEFAULT_LAST_NON_SILENT_VALUE
override val key: String = BuiltInKeyguardQuickAffordanceKeys.MUTE
override val pickerName: String = context.getString(R.string.volume_ringer_status_silent)
override fun pickerName(): String = context.getString(R.string.volume_ringer_status_silent)
override val pickerIconResourceId: Int = R.drawable.ic_notifications_silence
override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> =
ringerModeTracker.ringerModeInternal.asFlow()
ringerModeTracker.ringerModeInternal
.asFlow()
.onStart { getLastNonSilentRingerMode() }
.distinctUntilChanged()
.onEach { mode ->
@@ -78,17 +81,14 @@ class MuteQuickAffordanceConfig @Inject constructor(
}
}
.map { mode ->
val (activationState, contentDescriptionRes) = when {
audioManager.isVolumeFixed ->
ActivationState.NotSupported to
R.string.volume_ringer_hint_mute
mode == AudioManager.RINGER_MODE_SILENT ->
ActivationState.Active to
R.string.volume_ringer_hint_mute
else ->
ActivationState.Inactive to
R.string.volume_ringer_hint_unmute
}
val (activationState, contentDescriptionRes) =
when {
audioManager.isVolumeFixed ->
ActivationState.NotSupported to R.string.volume_ringer_hint_mute
mode == AudioManager.RINGER_MODE_SILENT ->
ActivationState.Active to R.string.volume_ringer_hint_mute
else -> ActivationState.Inactive to R.string.volume_ringer_hint_unmute
}
KeyguardQuickAffordanceConfig.LockScreenState.Visible(
Icon.Resource(
@@ -130,32 +130,35 @@ class MuteQuickAffordanceConfig @Inject constructor(
}
/**
* Gets the last non-silent ringer mode from shared-preferences if it exists. This is
* cached by [MuteQuickAffordanceCoreStartable] while this affordance is selected
* Gets the last non-silent ringer mode from shared-preferences if it exists. This is cached by
* [MuteQuickAffordanceCoreStartable] while this affordance is selected
*/
private suspend fun getLastNonSilentRingerMode(): Int =
withContext(backgroundDispatcher) {
userFileManager.getSharedPreferences(
userFileManager
.getSharedPreferences(
MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME,
Context.MODE_PRIVATE,
userTracker.userId
).getInt(
)
.getInt(
LAST_NON_SILENT_RINGER_MODE_KEY,
ringerModeTracker.ringerModeInternal.value ?: DEFAULT_LAST_NON_SILENT_VALUE
)
)
}
private fun <T> LiveData<T>.asFlow(): Flow<T?> =
conflatedCallbackFlow {
val observer = Observer { value: T -> trySend(value) }
observeForever(observer)
send(value)
awaitClose { removeObserver(observer) }
}.flowOn(mainDispatcher)
val observer = Observer { value: T -> trySend(value) }
observeForever(observer)
send(value)
awaitClose { removeObserver(observer) }
}
.flowOn(mainDispatcher)
companion object {
const val LAST_NON_SILENT_RINGER_MODE_KEY = "key_last_non_silent_ringer_mode"
const val MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME = "quick_affordance_mute_ringer_mode_cache"
private const val DEFAULT_LAST_NON_SILENT_VALUE = AudioManager.RINGER_MODE_NORMAL
}
}
}

View File

@@ -42,7 +42,7 @@ constructor(
override val key: String = BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER
override val pickerName = context.getString(R.string.qr_code_scanner_title)
override fun pickerName(): String = context.getString(R.string.qr_code_scanner_title)
override val pickerIconResourceId = R.drawable.ic_qr_code_scanner
@@ -53,6 +53,7 @@ constructor(
override fun onQRCodeScannerActivityChanged() {
trySendWithFailureLogging(state(), TAG)
}
override fun onQRCodeScannerPreferenceChanged() {
trySendWithFailureLogging(state(), TAG)
}

View File

@@ -51,7 +51,7 @@ constructor(
override val key: String = BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET
override val pickerName: String = context.getString(R.string.accessibility_wallet_button)
override fun pickerName(): String = context.getString(R.string.accessibility_wallet_button)
override val pickerIconResourceId = R.drawable.ic_wallet_lockscreen

View File

@@ -62,8 +62,7 @@ constructor(
override val key: String
get() = BuiltInKeyguardQuickAffordanceKeys.VIDEO_CAMERA
override val pickerName: String
get() = context.getString(R.string.video_camera)
override fun pickerName(): String = context.getString(R.string.video_camera)
override val pickerIconResourceId: Int
get() = R.drawable.ic_videocam

View File

@@ -170,7 +170,7 @@ constructor(
pickerState as? KeyguardQuickAffordanceConfig.PickerScreenState.Disabled
KeyguardQuickAffordancePickerRepresentation(
id = config.key,
name = config.pickerName,
name = config.pickerName(),
iconResourceId = config.pickerIconResourceId,
isEnabled =
pickerState is KeyguardQuickAffordanceConfig.PickerScreenState.Default,
@@ -234,7 +234,9 @@ constructor(
pw.println(" $slotId$selectionText (capacity = $capacity)")
}
pw.println("Available affordances on device:")
configs.forEach { config -> pw.println(" ${config.key} (\"${config.pickerName}\")") }
configs.forEach { config ->
pw.println(" ${config.key} (\"${config.pickerName()}\")")
}
}
}

View File

@@ -73,7 +73,7 @@ constructor(
private val pickerNameResourceId = R.string.note_task_button_label
override val pickerName: String = context.getString(pickerNameResourceId)
override fun pickerName(): String = context.getString(pickerNameResourceId)
override val pickerIconResourceId = R.drawable.ic_note_task_shortcut_keyguard

View File

@@ -28,7 +28,7 @@ import kotlinx.coroutines.yield
@RoboPilotTest
class FakeKeyguardQuickAffordanceConfig(
override val key: String,
override val pickerName: String = key,
private val pickerName: String = key,
override val pickerIconResourceId: Int = 0,
) : KeyguardQuickAffordanceConfig {
@@ -41,6 +41,8 @@ class FakeKeyguardQuickAffordanceConfig(
override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> =
_lockScreenState
override fun pickerName(): String = pickerName
override fun onTriggered(
expandable: Expandable?,
): OnTriggeredResult {

View File

@@ -189,12 +189,12 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() {
listOf(
KeyguardQuickAffordancePickerRepresentation(
id = config1.key,
name = config1.pickerName,
name = config1.pickerName(),
iconResourceId = config1.pickerIconResourceId,
),
KeyguardQuickAffordancePickerRepresentation(
id = config2.key,
name = config2.pickerName,
name = config2.pickerName(),
iconResourceId = config2.pickerIconResourceId,
),
)

View File

@@ -435,7 +435,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
listOf(
KeyguardQuickAffordancePickerRepresentation(
id = homeControls.key,
name = homeControls.pickerName,
name = homeControls.pickerName(),
iconResourceId = homeControls.pickerIconResourceId,
),
),
@@ -469,7 +469,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
listOf(
KeyguardQuickAffordancePickerRepresentation(
id = quickAccessWallet.key,
name = quickAccessWallet.pickerName,
name = quickAccessWallet.pickerName(),
iconResourceId = quickAccessWallet.pickerIconResourceId,
),
),
@@ -506,7 +506,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
listOf(
KeyguardQuickAffordancePickerRepresentation(
id = quickAccessWallet.key,
name = quickAccessWallet.pickerName,
name = quickAccessWallet.pickerName(),
iconResourceId = quickAccessWallet.pickerIconResourceId,
),
),
@@ -514,7 +514,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
listOf(
KeyguardQuickAffordancePickerRepresentation(
id = qrCodeScanner.key,
name = qrCodeScanner.pickerName,
name = qrCodeScanner.pickerName(),
iconResourceId = qrCodeScanner.pickerIconResourceId,
),
),
@@ -570,7 +570,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
listOf(
KeyguardQuickAffordancePickerRepresentation(
id = quickAccessWallet.key,
name = quickAccessWallet.pickerName,
name = quickAccessWallet.pickerName(),
iconResourceId = quickAccessWallet.pickerIconResourceId,
),
),
@@ -665,7 +665,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
listOf(
KeyguardQuickAffordancePickerRepresentation(
id = quickAccessWallet.key,
name = quickAccessWallet.pickerName,
name = quickAccessWallet.pickerName(),
iconResourceId = quickAccessWallet.pickerIconResourceId,
),
),