diff options
| author | 2024-10-29 17:20:16 +0000 | |
|---|---|---|
| committer | 2024-10-29 17:20:16 +0000 | |
| commit | 5e3b033cb7d491bde9dd4ce7d2b219e04cc1fd44 (patch) | |
| tree | a87e080804a020ffe66106eb83169ffe1ac5be60 | |
| parent | bd88cf430b85f5b379ef1e42fd88ac02e0ab400c (diff) | |
| parent | 9838809d352686682db13c5bec9fc2e09a6926cf (diff) | |
Merge "ActionButtonModel refactor" into main
8 files changed, 79 insertions, 65 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt index d08df26ea8da..3b72df7fdd56 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt @@ -73,6 +73,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.semantics @@ -639,7 +640,7 @@ private fun ActionArea(viewModel: BouncerSceneContentViewModel, modifier: Modifi val appearMoveAnimatable = remember { Animatable(0f) } val appearAnimationInitialOffset = with(LocalDensity.current) { 80.dp.toPx() } - actionButton?.let { actionButtonViewModel -> + actionButton?.let { actionButtonModel -> LaunchedEffect(Unit) { appearFadeInAnimatable.animateTo( targetValue = 1f, @@ -678,12 +679,14 @@ private fun ActionArea(viewModel: BouncerSceneContentViewModel, modifier: Modifi .background(color = MaterialTheme.colorScheme.tertiaryContainer) .semantics { role = Role.Button } .combinedClickable( - onClick = { actionButtonViewModel.onClick() }, - onLongClick = actionButtonViewModel.onLongClick?.let { { it.invoke() } }, + onClick = { actionButton?.let { viewModel.onActionButtonClicked(it) } }, + onLongClick = { + actionButton?.let { viewModel.onActionButtonLongClicked(it) } + }, ) ) { Text( - text = actionButtonViewModel.label, + text = stringResource(id = actionButtonModel.labelResId), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onTertiaryContainer, modifier = Modifier.align(Alignment.Center).padding(ButtonDefaults.ContentPadding), diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt index e3b5f34c8e5a..566cd70598de 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt @@ -27,6 +27,7 @@ import com.android.internal.util.emergencyAffordanceManager import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel +import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.EnableSceneContainer @@ -83,7 +84,7 @@ class BouncerActionButtonInteractorTest : SysuiTestCase() { overrideResource(R.string.lockscreen_return_to_call, MESSAGE_RETURN_TO_CALL) overrideResource( R.bool.config_enable_emergency_call_while_sim_locked, - ENABLE_EMERGENCY_CALL_WHILE_SIM_LOCKED + ENABLE_EMERGENCY_CALL_WHILE_SIM_LOCKED, ) whenever(selectedUserInteractor.getSelectedUserId()).thenReturn(currentUserId) whenever(emergencyAffordanceManager.needsEmergencyAffordance()) @@ -123,11 +124,11 @@ class BouncerActionButtonInteractorTest : SysuiTestCase() { kosmos.fakeTelephonyRepository.setIsInCall(true) assertThat(actionButton).isNotNull() - assertThat(actionButton?.label).isEqualTo(MESSAGE_RETURN_TO_CALL) - assertThat(actionButton?.onClick).isNotNull() - assertThat(actionButton?.onLongClick).isNull() + assertThat(actionButton?.labelResId).isEqualTo(R.string.lockscreen_return_to_call) + assertThat(actionButton) + .isInstanceOf(BouncerActionButtonModel.ReturnToCallButtonModel::class.java) - actionButton?.onClick?.invoke() + underTest.onReturnToCallButtonClicked() runCurrent() assertThat(metricsLogger.logs.size).isEqualTo(1) @@ -150,11 +151,11 @@ class BouncerActionButtonInteractorTest : SysuiTestCase() { kosmos.fakeTelephonyRepository.setIsInCall(false) assertThat(actionButton).isNotNull() - assertThat(actionButton?.label).isEqualTo(MESSAGE_EMERGENCY_CALL) - assertThat(actionButton?.onClick).isNotNull() - assertThat(actionButton?.onLongClick).isNotNull() + assertThat(actionButton?.labelResId).isEqualTo(R.string.lockscreen_emergency_call) + assertThat(actionButton) + .isInstanceOf(BouncerActionButtonModel.EmergencyButtonModel::class.java) - actionButton?.onClick?.invoke() + underTest.onEmergencyButtonClicked() runCurrent() assertThat(metricsLogger.logs.size).isEqualTo(1) @@ -167,12 +168,12 @@ class BouncerActionButtonInteractorTest : SysuiTestCase() { // ActivityStarter interface here. verify(emergencyAffordanceManager, never()).performEmergencyCall() - actionButton?.onLongClick?.invoke() + underTest.onEmergencyButtonLongClicked() verify(emergencyAffordanceManager).performEmergencyCall() } @Test - fun noCall_insecureAuthMethodButSecureSim_emergencyCallButton() = + fun noCall_insecureAuthMethodButSecureSim_emergencyCallButtonIsActionButton() = testScope.runTest { val underTest = kosmos.bouncerActionButtonInteractor val actionButton by collectLastValue(underTest.actionButton) @@ -184,9 +185,9 @@ class BouncerActionButtonInteractorTest : SysuiTestCase() { runCurrent() assertThat(actionButton).isNotNull() - assertThat(actionButton?.label).isEqualTo(MESSAGE_EMERGENCY_CALL) - assertThat(actionButton?.onClick).isNotNull() - assertThat(actionButton?.onLongClick).isNotNull() + assertThat(actionButton?.labelResId).isEqualTo(R.string.lockscreen_emergency_call) + assertThat(actionButton) + .isInstanceOf(BouncerActionButtonModel.EmergencyButtonModel::class.java) } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt index d2bf9b888ef0..9db201465cf2 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt @@ -332,7 +332,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { assertWithMessage("Bouncer action button not visible") .that(bouncerActionButton) .isNotNull() - bouncerActionButton?.onClick?.invoke() + kosmos.bouncerSceneContentViewModel.onActionButtonClicked(bouncerActionButton!!) runCurrent() // TODO(b/369765704): Assert that an activity was started once we use ActivityStarter. @@ -354,7 +354,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { assertWithMessage("Bouncer action button not visible during call") .that(bouncerActionButton) .isNotNull() - bouncerActionButton?.onClick?.invoke() + kosmos.bouncerSceneContentViewModel.onActionButtonClicked(bouncerActionButton!!) runCurrent() verify(kosmos.mockTelecomManager).showInCallScreen(any()) diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt index da01c583db0a..b95ce69d1aa6 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt @@ -30,7 +30,6 @@ import com.android.internal.util.EmergencyAffordanceManager import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor import com.android.systemui.bouncer.data.repository.EmergencyServicesRepository import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel -import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background @@ -75,7 +74,6 @@ constructor( private val metricsLogger: MetricsLogger, private val dozeLogger: DozeLogger, private val sceneInteractor: Lazy<SceneInteractor>, - private val bouncerHapticPlayer: BouncerHapticPlayer, ) { /** The bouncer action button. If `null`, the button should not be shown. */ val actionButton: Flow<BouncerActionButtonModel?> = @@ -90,43 +88,38 @@ constructor( ) .map { when { - isReturnToCallButton() -> returnToCallButtonModel - isEmergencyCallButton() -> emergencyCallButtonModel + isReturnToCallButton() -> + BouncerActionButtonModel.ReturnToCallButtonModel( + labelResourceId = R.string.lockscreen_return_to_call + ) + isEmergencyCallButton() -> + BouncerActionButtonModel.EmergencyButtonModel( + labelResourceId = R.string.lockscreen_emergency_call + ) else -> null // Do not show the button. } } .distinctUntilChanged() } - private val returnToCallButtonModel: BouncerActionButtonModel by lazy { - BouncerActionButtonModel( - label = applicationContext.getString(R.string.lockscreen_return_to_call), - onClick = { - prepareToPerformAction() - returnToCall() - }, - onLongClick = null, - ) + fun onReturnToCallButtonClicked() { + prepareToPerformAction() + returnToCall() } - private val emergencyCallButtonModel: BouncerActionButtonModel by lazy { - BouncerActionButtonModel( - label = applicationContext.getString(R.string.lockscreen_emergency_call), - onClick = { - // TODO(b/373930432): haptics should be played at the UI layer -> refactor - bouncerHapticPlayer.playEmergencyButtonClickFeedback() - prepareToPerformAction() - dozeLogger.logEmergencyCall() - startEmergencyDialerActivity() - }, - // TODO(b/369767936): The long click detector doesn't work properly, investigate. - onLongClick = { - if (emergencyAffordanceManager.needsEmergencyAffordance()) { - prepareToPerformAction() - emergencyAffordanceManager.performEmergencyCall() - } - }, - ) + fun onEmergencyButtonClicked() { + prepareToPerformAction() + dozeLogger.logEmergencyCall() + startEmergencyDialerActivity() + } + + fun onEmergencyButtonLongClicked() { + if (emergencyAffordanceManager.needsEmergencyAffordance()) { + prepareToPerformAction() + + // TODO(b/369767936): Check that !longPressWasDragged before invoking. + emergencyAffordanceManager.performEmergencyCall() + } } private fun startEmergencyDialerActivity() { diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerActionButtonModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerActionButtonModel.kt index 7f1730cb2abd..69f37e138cba 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerActionButtonModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/model/BouncerActionButtonModel.kt @@ -16,17 +16,16 @@ package com.android.systemui.bouncer.shared.model -/** Models the action button on the bouncer. */ -data class BouncerActionButtonModel( - /** The text to be shown on the button. */ - val label: String, +import androidx.annotation.StringRes - /** The action to perform when the user clicks on the button. */ - val onClick: () -> Unit, +/** Models the action button on the bouncer. */ +sealed class BouncerActionButtonModel( + /** The resource Id of the text to be shown on the button. */ + @StringRes val labelResId: Int +) { + data class EmergencyButtonModel(@StringRes private val labelResourceId: Int) : + BouncerActionButtonModel(labelResourceId) - /** - * The action to perform when the user long-clicks on the button. When not provided, long-clicks - * will be treated as regular clicks. - */ - val onLongClick: (() -> Unit)? = null, -) + data class ReturnToCallButtonModel(@StringRes private val labelResourceId: Int) : + BouncerActionButtonModel(labelResourceId) +} diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt index 0d7be8c9c9af..cc79311725ab 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt @@ -65,6 +65,7 @@ constructor( private val passwordViewModelFactory: PasswordBouncerViewModel.Factory, private val bouncerHapticPlayer: BouncerHapticPlayer, private val keyguardMediaKeyInteractor: KeyguardMediaKeyInteractor, + private val bouncerActionButtonInteractor: BouncerActionButtonInteractor, ) : ExclusiveActivatable() { private val _selectedUserImage = MutableStateFlow<Bitmap?>(null) val selectedUserImage: StateFlow<Bitmap?> = _selectedUserImage.asStateFlow() @@ -344,6 +345,24 @@ constructor( ?: false } + fun onActionButtonClicked(actionButtonModel: BouncerActionButtonModel) { + when (actionButtonModel) { + is BouncerActionButtonModel.EmergencyButtonModel -> { + bouncerHapticPlayer.playEmergencyButtonClickFeedback() + bouncerActionButtonInteractor.onEmergencyButtonClicked() + } + is BouncerActionButtonModel.ReturnToCallButtonModel -> { + bouncerActionButtonInteractor.onReturnToCallButtonClicked() + } + } + } + + fun onActionButtonLongClicked(actionButtonModel: BouncerActionButtonModel) { + if (actionButtonModel is BouncerActionButtonModel.EmergencyButtonModel) { + bouncerActionButtonInteractor.onEmergencyButtonLongClicked() + } + } + data class DialogViewModel( val text: String, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt index 77ec83871016..3087d01a2479 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt @@ -23,7 +23,6 @@ import com.android.internal.logging.metricsLogger import com.android.internal.util.emergencyAffordanceManager import com.android.systemui.authentication.domain.interactor.authenticationInteractor import com.android.systemui.bouncer.data.repository.emergencyServicesRepository -import com.android.systemui.haptics.msdl.bouncerHapticPlayer import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.testDispatcher @@ -53,6 +52,5 @@ val Kosmos.bouncerActionButtonInteractor by Fixture { metricsLogger = metricsLogger, dozeLogger = mock(), sceneInteractor = { sceneInteractor }, - bouncerHapticPlayer, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt index c77d0aab653d..e0d1d16bcf55 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt @@ -62,6 +62,7 @@ val Kosmos.bouncerSceneContentViewModel by Fixture { passwordViewModelFactory = passwordBouncerViewModelFactory, bouncerHapticPlayer = bouncerHapticPlayer, keyguardMediaKeyInteractor = keyguardMediaKeyInteractor, + bouncerActionButtonInteractor = bouncerActionButtonInteractor, ) } |