Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17c69415 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[Quickswitch] UI (1/n)" into main

parents 7b51c95c 7a1e9bec
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
<!--
  ~ Copyright (C) 2025 The Android Open Source Project
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="24dp"
    android:width="24dp"
    android:autoMirrored="true"
    android:viewportHeight="960"
    android:viewportWidth="960">
    <path android:fillColor="@android:color/white"
        android:pathData="M240,800q-33,0 -56.5,-23.5T160,720q0,-33 23.5,-56.5T240,640q33,0 56.5,23.5T320,720q0,33 -23.5,56.5T240,800ZM480,800q-33,0 -56.5,-23.5T400,720q0,-33 23.5,-56.5T480,640q33,0 56.5,23.5T560,720q0,33 -23.5,56.5T480,800ZM720,800q-33,0 -56.5,-23.5T640,720q0,-33 23.5,-56.5T720,640q33,0 56.5,23.5T800,720q0,33 -23.5,56.5T720,800ZM240,560q-33,0 -56.5,-23.5T160,480q0,-33 23.5,-56.5T240,400q33,0 56.5,23.5T320,480q0,33 -23.5,56.5T240,560ZM480,560q-33,0 -56.5,-23.5T400,480q0,-33 23.5,-56.5T480,400q33,0 56.5,23.5T560,480q0,33 -23.5,56.5T480,560ZM720,560q-33,0 -56.5,-23.5T640,480q0,-33 23.5,-56.5T720,400q33,0 56.5,23.5T800,480q0,33 -23.5,56.5T720,560ZM240,320q-33,0 -56.5,-23.5T160,240q0,-33 23.5,-56.5T240,160q33,0 56.5,23.5T320,240q0,33 -23.5,56.5T240,320ZM480,320q-33,0 -56.5,-23.5T400,240q0,-33 23.5,-56.5T480,160q33,0 56.5,23.5T560,240q0,33 -23.5,56.5T480,320ZM720,320q-33,0 -56.5,-23.5T640,240q0,-33 23.5,-56.5T720,160q33,0 56.5,23.5T800,240q0,33 -23.5,56.5T720,320Z"/>
</vector>
+13 −0
Original line number Diff line number Diff line
@@ -3954,6 +3954,8 @@
    <string name="touchpad_tutorial_home_gesture_button">Go home</string>
    <!-- Label for button opening tutorial for "view recent apps" gesture on touchpad [CHAR LIMIT=NONE] -->
    <string name="touchpad_tutorial_recent_apps_gesture_button">View recent apps</string>
    <!-- Label for button opening tutorial for "switch apps" gesture on touchpad [CHAR LIMIT=NONE] -->
    <string name="touchpad_tutorial_switch_apps_gesture_button">Switch apps</string>
    <!-- Label for button finishing touchpad tutorial [CHAR LIMIT=NONE] -->
    <string name="touchpad_tutorial_done_button">Done</string>
    <!-- Screen title after gesture was not done correctly [CHAR LIMIT=NONE] -->
@@ -3991,6 +3993,17 @@
    <string name="touchpad_recent_apps_gesture_success_body">You completed the view recent apps gesture.</string>
    <!-- Text shown to the user after recent gesture was not done correctly [CHAR LIMIT=NONE] -->
    <string name="touchpad_recent_gesture_error_body">To view recent apps, swipe up and hold using three fingers on your touchpad</string>
    <!-- SWITCH APPS GESTURE -->
    <!-- Touchpad switch apps gesture action name in tutorial [CHAR LIMIT=NONE] -->
    <string name="touchpad_switch_apps_gesture_action_title">Switch apps</string>
    <!-- Touchpad switch apps gesture guidance in gestures tutorial [CHAR LIMIT=NONE] -->
    <string name="touchpad_switch_apps_gesture_guidance">Swipe left or right using four fingers on your touchpad</string>
    <!-- Screen title after switch apps gesture was done successfully [CHAR LIMIT=NONE] -->
    <string name="touchpad_switch_apps_gesture_success_title">Great job!</string>
    <!-- Text shown to the user after they complete switch apps gesture tutorial [CHAR LIMIT=NONE] -->
    <string name="touchpad_switch_apps_gesture_success_body">You completed the switch apps gesture.</string>
    <!-- Text shown to the user after switch gesture was not done correctly [CHAR LIMIT=NONE] -->
    <string name="touchpad_switch_gesture_error_body">Swipe left or right using four fingers on your touchpad to switch apps</string>

    <!-- KEYBOARD TUTORIAL-->
    <!-- Action key tutorial title [CHAR LIMIT=NONE] -->
+10 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ import com.android.systemui.touchpad.tutorial.ui.viewmodel.HomeGestureRecognizer
import com.android.systemui.touchpad.tutorial.ui.viewmodel.HomeGestureScreenViewModel
import com.android.systemui.touchpad.tutorial.ui.viewmodel.RecentAppsGestureRecognizerProvider
import com.android.systemui.touchpad.tutorial.ui.viewmodel.RecentAppsGestureScreenViewModel
import com.android.systemui.touchpad.tutorial.ui.viewmodel.SwitchAppsGestureRecognizerProvider
import com.android.systemui.touchpad.tutorial.ui.viewmodel.SwitchAppsGestureScreenViewModel
import dagger.Binds
import dagger.Module
import dagger.Provides
@@ -68,6 +70,14 @@ interface TouchpadTutorialModule {
            )
        }

        @Provides
        fun switchAppsViewModel(
            recognizerProvider: SwitchAppsGestureRecognizerProvider,
            adapterFactory: GestureRecognizerAdapter.Factory,
        ): SwitchAppsGestureScreenViewModel {
            return SwitchAppsGestureScreenViewModel(adapterFactory.create(recognizerProvider))
        }

        @Provides
        fun recentAppsViewModel(
            recognizerProvider: RecentAppsGestureRecognizerProvider,
+88 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.touchpad.tutorial.ui.composable

import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.airbnb.lottie.compose.rememberLottieDynamicProperties
import com.android.compose.theme.LocalAndroidColorScheme
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
import com.android.systemui.inputdevice.tutorial.ui.composable.rememberColorFilterProperty
import com.android.systemui.res.R
import com.android.systemui.touchpad.tutorial.ui.viewmodel.EasterEggGestureViewModel
import com.android.systemui.touchpad.tutorial.ui.viewmodel.SwitchAppsGestureScreenViewModel

@Composable
fun SwitchAppsGestureTutorialScreen(
    viewModel: SwitchAppsGestureScreenViewModel,
    easterEggGestureViewModel: EasterEggGestureViewModel,
    onDoneButtonClicked: () -> Unit,
    onBack: () -> Unit,
) {
    val screenConfig =
        TutorialScreenConfig(
            colors = rememberScreenColors(),
            strings =
                TutorialScreenConfig.Strings(
                    titleResId = R.string.touchpad_switch_apps_gesture_action_title,
                    bodyResId = R.string.touchpad_switch_apps_gesture_guidance,
                    titleSuccessResId = R.string.touchpad_switch_apps_gesture_success_title,
                    bodySuccessResId = R.string.touchpad_switch_apps_gesture_success_body,
                    titleErrorResId = R.string.gesture_error_title,
                    bodyErrorResId = R.string.touchpad_switch_gesture_error_body,
                ),
            // TODO: replace animation
            animations = TutorialScreenConfig.Animations(educationResId = R.raw.trackpad_back_edu),
        )
    GestureTutorialScreen(
        screenConfig = screenConfig,
        tutorialStateFlow = viewModel.tutorialState,
        motionEventConsumer = {
            easterEggGestureViewModel.accept(it)
            viewModel.handleEvent(it)
        },
        easterEggTriggeredFlow = easterEggGestureViewModel.easterEggTriggered,
        onEasterEggFinished = easterEggGestureViewModel::onEasterEggFinished,
        onDoneButtonClicked = onDoneButtonClicked,
        onBack = onBack,
    )
}

@Composable
private fun rememberScreenColors(): TutorialScreenConfig.Colors {
    val onTertiary = MaterialTheme.colorScheme.onTertiary
    val onTertiaryFixed = LocalAndroidColorScheme.current.onTertiaryFixed
    val onTertiaryFixedVariant = LocalAndroidColorScheme.current.onTertiaryFixedVariant
    val tertiaryFixedDim = LocalAndroidColorScheme.current.tertiaryFixedDim
    val dynamicProperties =
        rememberLottieDynamicProperties(
            rememberColorFilterProperty(".tertiaryFixedDim", tertiaryFixedDim),
            rememberColorFilterProperty(".onTertiaryFixed", onTertiaryFixed),
            rememberColorFilterProperty(".onTertiary", onTertiary),
            rememberColorFilterProperty(".onTertiaryFixedVariant", onTertiaryFixedVariant),
        )
    val screenColors =
        remember(dynamicProperties) {
            TutorialScreenConfig.Colors(
                background = onTertiaryFixed,
                title = tertiaryFixedDim,
                animationColors = dynamicProperties,
            )
        }
    return screenColors
}
+22 −4
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ fun TutorialSelectionScreen(
    onBackTutorialClicked: () -> Unit,
    onHomeTutorialClicked: () -> Unit,
    onRecentAppsTutorialClicked: () -> Unit,
    onSwitchAppsTutorialClicked: () -> Unit,
    onDoneButtonClicked: () -> Unit,
    lastSelectedScreen: Screen,
) {
@@ -86,6 +87,7 @@ fun TutorialSelectionScreen(
                    onBackTutorialClicked = onBackTutorialClicked,
                    onHomeTutorialClicked = onHomeTutorialClicked,
                    onRecentAppsTutorialClicked = onRecentAppsTutorialClicked,
                    onSwitchAppsTutorialClicked = onSwitchAppsTutorialClicked,
                    modifier = Modifier.weight(1f).padding(60.dp),
                    lastSelectedScreen,
                )
@@ -95,6 +97,7 @@ fun TutorialSelectionScreen(
                    onBackTutorialClicked = onBackTutorialClicked,
                    onHomeTutorialClicked = onHomeTutorialClicked,
                    onRecentAppsTutorialClicked = onRecentAppsTutorialClicked,
                    onSwitchAppsTutorialClicked = onSwitchAppsTutorialClicked,
                    modifier = Modifier.weight(1f).padding(60.dp),
                    lastSelectedScreen,
                )
@@ -113,6 +116,7 @@ private fun HorizontalSelectionButtons(
    onBackTutorialClicked: () -> Unit,
    onHomeTutorialClicked: () -> Unit,
    onRecentAppsTutorialClicked: () -> Unit,
    onSwitchAppsTutorialClicked: () -> Unit,
    modifier: Modifier = Modifier,
    lastSelectedScreen: Screen,
) {
@@ -121,10 +125,11 @@ private fun HorizontalSelectionButtons(
        verticalAlignment = Alignment.CenterVertically,
        modifier = modifier,
    ) {
        ThreeTutorialButtons(
        FourTutorialButtons(
            onBackTutorialClicked,
            onHomeTutorialClicked,
            onRecentAppsTutorialClicked,
            onSwitchAppsTutorialClicked,
            modifier = Modifier.weight(1f).fillMaxSize(),
            lastSelectedScreen,
        )
@@ -136,6 +141,7 @@ private fun VerticalSelectionButtons(
    onBackTutorialClicked: () -> Unit,
    onHomeTutorialClicked: () -> Unit,
    onRecentAppsTutorialClicked: () -> Unit,
    onSwitchAppsTutorialClicked: () -> Unit,
    modifier: Modifier = Modifier,
    lastSelectedScreen: Screen,
) {
@@ -144,10 +150,11 @@ private fun VerticalSelectionButtons(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = modifier,
    ) {
        ThreeTutorialButtons(
        FourTutorialButtons(
            onBackTutorialClicked,
            onHomeTutorialClicked,
            onRecentAppsTutorialClicked,
            onSwitchAppsTutorialClicked,
            modifier = Modifier.weight(1f).fillMaxSize(),
            lastSelectedScreen,
        )
@@ -155,21 +162,24 @@ private fun VerticalSelectionButtons(
}

@Composable
private fun ThreeTutorialButtons(
private fun FourTutorialButtons(
    onBackTutorialClicked: () -> Unit,
    onHomeTutorialClicked: () -> Unit,
    onRecentAppsTutorialClicked: () -> Unit,
    onSwitchAppsTutorialClicked: () -> Unit,
    modifier: Modifier = Modifier,
    lastSelectedScreen: Screen,
) {
    val homeFocusRequester = remember { FocusRequester() }
    val backFocusRequester = remember { FocusRequester() }
    val recentAppsFocusRequester = remember { FocusRequester() }
    val switchAppsFocusRequester = remember { FocusRequester() }
    LaunchedEffect(Unit) {
        when (lastSelectedScreen) {
            Screen.HOME_GESTURE -> homeFocusRequester.requestFocus()
            Screen.BACK_GESTURE -> backFocusRequester.requestFocus()
            Screen.RECENT_APPS_GESTURE -> recentAppsFocusRequester.requestFocus()
            Screen.SWITCH_APPS_GESTURE -> switchAppsFocusRequester.requestFocus()
            else -> {} // No-Op.
        }
    }
@@ -197,6 +207,14 @@ private fun ThreeTutorialButtons(
        backgroundColor = MaterialTheme.colorScheme.secondary,
        modifier = modifier.focusRequester(recentAppsFocusRequester).focusable(),
    )
    TutorialButton(
        text = stringResource(R.string.touchpad_tutorial_switch_apps_gesture_button),
        icon = ImageVector.vectorResource(id = R.drawable.touchpad_tutorial_apps_icon),
        iconColor = MaterialTheme.colorScheme.primary,
        onClick = onSwitchAppsTutorialClicked,
        backgroundColor = MaterialTheme.colorScheme.onPrimary,
        modifier = modifier.focusRequester(switchAppsFocusRequester).focusable(),
    )
}

@Composable
@@ -227,7 +245,7 @@ private fun TutorialButton(
                tint = iconColor,
            )
            Spacer(modifier = Modifier.height(16.dp))
            Text(text = text, style = MaterialTheme.typography.headlineLarge)
            Text(text = text, style = MaterialTheme.typography.headlineLarge, color = iconColor)
        }
    }
}
Loading