summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author William Leshner <wleshner@google.com> 2025-02-06 12:22:13 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-02-06 12:22:13 -0800
commit1253632dc083fa1b092935627abf5b0932211ab0 (patch)
treeba756af147c89de54eeb77e08a3aae85b2dabf73
parent7272c9605f197329c6fc7994cf78100c7e21821d (diff)
parent98278c5d57953828296b4405af92bcebe611601a (diff)
Merge "Animate the "go to dream" button tooltip." into main
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt63
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt11
3 files changed, 77 insertions, 9 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt
index a840a6f0476f..acaf43a62f43 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalToDreamButtonSection.kt
@@ -16,6 +16,12 @@
package com.android.systemui.communal.ui.compose.section
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.core.MutableTransitionState
+import androidx.compose.animation.expandVertically
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
@@ -28,6 +34,11 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.CornerRadius
@@ -52,6 +63,8 @@ import com.android.systemui.communal.ui.viewmodel.CommunalToDreamButtonViewModel
import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.res.R
import javax.inject.Inject
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.delay
class CommunalToDreamButtonSection
@Inject
@@ -75,16 +88,54 @@ constructor(
val buttonSize = dimensionResource(R.dimen.communal_to_dream_button_size)
if (viewModel.shouldShowTooltip) {
+ val tooltipVisibleState = remember { MutableTransitionState(false) }
+
Column(
modifier =
Modifier.widthIn(max = tooltipMaxWidth).pointerInput(Unit) {
- observeTaps { viewModel.setDreamButtonTooltipDismissed() }
+ observeTaps {
+ if (tooltipVisibleState.isCurrentlyVisible()) {
+ tooltipVisibleState.targetState = false
+ }
+ }
}
) {
- Tooltip(
- pointerOffsetDp = buttonSize.div(2),
- text = stringResource(R.string.glanceable_hub_to_dream_button_tooltip),
- )
+ var waitingToShowTooltip by remember { mutableStateOf(true) }
+
+ LaunchedEffect(tooltipVisibleState.targetState) {
+ delay(3.seconds)
+ tooltipVisibleState.targetState = true
+ waitingToShowTooltip = false
+ }
+
+ // This LaunchedEffect is used to wait for the tooltip dismiss animation to
+ // complete before setting the tooltip dismissed. Otherwise, the composable would
+ // be removed before the animation can start.
+ LaunchedEffect(
+ tooltipVisibleState.currentState,
+ tooltipVisibleState.isIdle,
+ waitingToShowTooltip,
+ ) {
+ if (
+ !waitingToShowTooltip &&
+ !tooltipVisibleState.currentState &&
+ tooltipVisibleState.isIdle
+ ) {
+ viewModel.setDreamButtonTooltipDismissed()
+ }
+ }
+
+ AnimatedVisibility(
+ visibleState = tooltipVisibleState,
+ enter = fadeIn() + expandVertically(expandFrom = Alignment.Bottom),
+ exit = fadeOut() + shrinkVertically(shrinkTowards = Alignment.Bottom),
+ ) {
+ Tooltip(
+ pointerOffsetDp = buttonSize.div(2),
+ text = stringResource(R.string.glanceable_hub_to_dream_button_tooltip),
+ )
+ }
+
GoToDreamButton(
modifier = Modifier.width(buttonSize).height(buttonSize).align(Alignment.End)
) {
@@ -98,6 +149,8 @@ constructor(
}
}
+ private fun MutableTransitionState<Boolean>.isCurrentlyVisible() = currentState && isIdle
+
companion object {
private val tooltipMaxWidth = 350.dp
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt
index b747705fa3a2..9fab652e2375 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt
@@ -126,13 +126,23 @@ class CommunalToDreamButtonViewModelTest : SysuiTestCase() {
}
@Test
- fun shouldShowDreamButtonTooltip_trueWhenNotDismissed() =
+ fun shouldShowDreamButtonTooltip_trueWhenNotDismissedAndHubOnboardingDismissed() =
kosmos.runTest {
+ setSelectedUser(MAIN_USER)
+ fakeCommunalPrefsRepository.setHubOnboardingDismissed(MAIN_USER)
runCurrent()
+
assertThat(underTest.shouldShowTooltip).isTrue()
}
@Test
+ fun shouldShowDreamButtonTooltip_falseWhenNotDismissedAndHubOnboardingNotDismissed() =
+ kosmos.runTest {
+ runCurrent()
+ assertThat(underTest.shouldShowTooltip).isFalse()
+ }
+
+ @Test
fun shouldShowDreamButtonTooltip_falseWhenDismissed() =
kosmos.runTest {
setSelectedUser(MAIN_USER)
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt
index 7e683c45e525..b531d159acde 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt
@@ -30,6 +30,8 @@ import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.Hydrator
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
+import com.android.systemui.util.kotlin.BooleanFlowOperators.not
import com.android.systemui.util.kotlin.isDevicePluggedIn
import com.android.systemui.util.kotlin.sample
import dagger.assisted.AssistedFactory
@@ -40,7 +42,6 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -68,12 +69,16 @@ constructor(
source = batteryController.isDevicePluggedIn().distinctUntilChanged(),
)
- /** Return whether the dream button tooltip has been dismissed. */
+ /** Return whether to show the dream button tooltip. */
val shouldShowTooltip: Boolean by
hydrator.hydratedStateOf(
traceName = "shouldShowTooltip",
initialValue = false,
- source = prefsInteractor.isDreamButtonTooltipDismissed.map { !it },
+ source =
+ allOf(
+ not(prefsInteractor.isDreamButtonTooltipDismissed),
+ prefsInteractor.isHubOnboardingDismissed,
+ ),
)
/** Set the dream button tooltip to be dismissed. */