1 /*
<lambda>null2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.systemui.inputdevice.tutorial.ui.composable
18
19 import androidx.activity.compose.BackHandler
20 import androidx.compose.foundation.focusable
21 import androidx.compose.foundation.layout.Box
22 import androidx.compose.foundation.layout.fillMaxSize
23 import androidx.compose.runtime.Composable
24 import androidx.compose.runtime.LaunchedEffect
25 import androidx.compose.runtime.getValue
26 import androidx.compose.runtime.mutableStateOf
27 import androidx.compose.runtime.remember
28 import androidx.compose.runtime.saveable.rememberSaveable
29 import androidx.compose.runtime.setValue
30 import androidx.compose.ui.Modifier
31 import androidx.compose.ui.focus.FocusRequester
32 import androidx.compose.ui.focus.focusRequester
33 import androidx.compose.ui.input.key.Key
34 import androidx.compose.ui.input.key.KeyEvent
35 import androidx.compose.ui.input.key.KeyEventType
36 import androidx.compose.ui.input.key.key
37 import androidx.compose.ui.input.key.onKeyEvent
38 import androidx.compose.ui.input.key.type
39 import com.airbnb.lottie.compose.rememberLottieDynamicProperties
40 import com.android.compose.theme.LocalAndroidColorScheme
41 import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Finished
42 import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.NotStarted
43 import com.android.systemui.res.R
44
45 @Composable
46 fun ActionKeyTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
47 BackHandler(onBack = onBack)
48 val screenConfig = buildScreenConfig()
49 var actionState: TutorialActionState by
50 rememberSaveable(stateSaver = TutorialActionState.stateSaver()) {
51 mutableStateOf(NotStarted)
52 }
53 val focusRequester = remember { FocusRequester() }
54 Box(
55 modifier =
56 Modifier.fillMaxSize()
57 .onKeyEvent { keyEvent: KeyEvent ->
58 if (keyEvent.key == Key.MetaLeft && keyEvent.type == KeyEventType.KeyUp) {
59 actionState = Finished(R.raw.action_key_success)
60 }
61 true
62 }
63 .focusRequester(focusRequester)
64 .focusable()
65 ) {
66 ActionTutorialContent(actionState, onDoneButtonClicked, screenConfig)
67 }
68 LaunchedEffect(Unit) {
69 // we need to request focus on main container so it can handle all key events immediately
70 // when it's open. Otherwise user needs to press non-modifier key before modifier key can
71 // be handled as nothing is focused
72 focusRequester.requestFocus()
73 }
74 }
75
76 @Composable
buildScreenConfignull77 private fun buildScreenConfig() =
78 TutorialScreenConfig(
79 colors = rememberScreenColors(),
80 strings =
81 TutorialScreenConfig.Strings(
82 titleResId = R.string.tutorial_action_key_title,
83 bodyResId = R.string.tutorial_action_key_guidance,
84 titleSuccessResId = R.string.tutorial_action_key_success_title,
85 bodySuccessResId = R.string.tutorial_action_key_success_body,
86 // error state for action key is not implemented yet so below should never appear
87 titleErrorResId = R.string.gesture_error_title,
88 bodyErrorResId = R.string.touchpad_action_key_error_body,
89 ),
90 animations = TutorialScreenConfig.Animations(educationResId = R.raw.action_key_edu),
91 )
92
93 @Composable
94 private fun rememberScreenColors(): TutorialScreenConfig.Colors {
95 val primaryFixedDim = LocalAndroidColorScheme.current.primaryFixedDim
96 val secondaryFixedDim = LocalAndroidColorScheme.current.secondaryFixedDim
97 val onSecondaryFixed = LocalAndroidColorScheme.current.onSecondaryFixed
98 val onSecondaryFixedVariant = LocalAndroidColorScheme.current.onSecondaryFixedVariant
99 val dynamicProperties =
100 rememberLottieDynamicProperties(
101 rememberColorFilterProperty(".primaryFixedDim", primaryFixedDim),
102 rememberColorFilterProperty(".secondaryFixedDim", secondaryFixedDim),
103 rememberColorFilterProperty(".onSecondaryFixed", onSecondaryFixed),
104 rememberColorFilterProperty(".onSecondaryFixedVariant", onSecondaryFixedVariant),
105 )
106 val screenColors =
107 remember(dynamicProperties) {
108 TutorialScreenConfig.Colors(
109 background = onSecondaryFixed,
110 title = secondaryFixedDim,
111 animationColors = dynamicProperties,
112 )
113 }
114 return screenColors
115 }
116