summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
author Josh <jmokut@google.com> 2024-09-18 15:51:14 +0000
committer Josh <jmokut@google.com> 2024-09-19 16:53:54 +0000
commitc07e6f8ed283a44ac540bd182ad688079458b469 (patch)
tree48a8310e650b546a4d23948eb2ccce67e28b9887 /packages
parent3d404328e80d703407a8b2393c9d254e50eb742a (diff)
Migrated shortcut helper bottom sheet to compose
go/shortcut-helper-bottom-sheet-compose-migration Test: None Flag: com.android.systemui.keyboard_shortcut_helper_rewrite Fixes: 366152089 Fix: 362733881 Fix: 355153229 Fix: 362730283 Fix: 362740106 Fix: 362735926 Fix: 362732358 Change-Id: I47d25c9288a7243997d60c353241914fff75073b
Diffstat (limited to 'packages')
-rw-r--r--packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml4
-rw-r--r--packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml28
-rw-r--r--packages/SystemUI/res/values-sw600dp-land/dimens.xml4
-rw-r--r--packages/SystemUI/res/values/dimens.xml4
-rw-r--r--packages/SystemUI/res/values/strings.xml6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelperUtils.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt202
8 files changed, 127 insertions, 170 deletions
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
index 84f7a5133593..6c8db91d49bb 100644
--- a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
@@ -28,8 +28,4 @@
<!-- Overload default clock widget parameters -->
<dimen name="widget_big_font_size">100dp</dimen>
<dimen name="widget_label_font_size">18sp</dimen>
-
- <!-- New keyboard shortcut helper -->
- <dimen name="shortcut_helper_width">704dp</dimen>
- <dimen name="shortcut_helper_height">1208dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml b/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml
deleted file mode 100644
index a15532f7aed2..000000000000
--- a/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/shortcut_helper_sheet_container"
- android:layout_gravity="center_horizontal|bottom"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <FrameLayout
- android:id="@+id/shortcut_helper_sheet"
- style="@style/ShortcutHelperBottomSheet"
- android:layout_width="@dimen/shortcut_helper_width"
- android:layout_height="@dimen/shortcut_helper_height"
- android:orientation="vertical"
- app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
-
- <!-- Drag handle for accessibility -->
- <com.google.android.material.bottomsheet.BottomSheetDragHandleView
- android:id="@+id/drag_handle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <androidx.compose.ui.platform.ComposeView
- android:id="@+id/shortcut_helper_compose_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </FrameLayout>
-</androidx.coordinatorlayout.widget.CoordinatorLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index 3efe7a560d94..2a27b47e54ca 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -26,10 +26,6 @@
<dimen name="keyguard_clock_top_margin">8dp</dimen>
<dimen name="keyguard_smartspace_top_offset">0dp</dimen>
- <!-- New keyboard shortcut helper -->
- <dimen name="shortcut_helper_width">864dp</dimen>
- <dimen name="shortcut_helper_height">728dp</dimen>
-
<!-- QS-->
<dimen name="qs_panel_padding_top">16dp</dimen>
<dimen name="qs_panel_padding">24dp</dimen>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 00846cb10378..e94248dc72ce 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1005,10 +1005,6 @@
<dimen name="ksh_app_item_minimum_height">64dp</dimen>
<dimen name="ksh_category_separator_margin">16dp</dimen>
- <!-- New keyboard shortcut helper -->
- <dimen name="shortcut_helper_width">412dp</dimen>
- <dimen name="shortcut_helper_height">728dp</dimen>
-
<!-- The size of corner radius of the arrow in the onboarding toast. -->
<dimen name="recents_onboarding_toast_arrow_corner_radius">2dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ba3822bd3c23..a3db7761f59d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3711,6 +3711,12 @@
[CHAR LIMIT=NONE]
-->
<string name="shortcut_helper_key_combinations_or_separator">or</string>
+ <!-- Content description of the drag handle that allows to swipe to dismiss the shortcut helper.
+ The helper is a component that shows the user which keyboard shortcuts they can
+ use. The helper shows shortcuts in categories, which can be collapsed or expanded.
+ [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_content_description_drag_handle">Drag handle</string>
+
<!-- Keyboard touchpad tutorial scheduler-->
<!-- Notification title for launching keyboard tutorial [CHAR_LIMIT=100] -->
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
index 4bf552e0f1e3..93cd1cf487b0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
@@ -36,6 +36,7 @@ import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.FlowRowScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -71,8 +72,6 @@ import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
-import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass
-import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
@@ -116,7 +115,6 @@ import androidx.compose.ui.util.fastForEach
import androidx.compose.ui.util.fastForEachIndexed
import androidx.compose.ui.zIndex
import com.android.compose.ui.graphics.painter.rememberDrawablePainter
-import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.systemui.keyboard.shortcut.shared.model.Shortcut
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
@@ -188,10 +186,7 @@ private fun ActiveShortcutHelper(
}
}
-@Composable
-private fun shouldUseSinglePane() =
- LocalWindowSizeClass.current.widthSizeClass == WindowWidthSizeClass.Compact ||
- LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Compact
+@Composable private fun shouldUseSinglePane() = hasCompactWindowSize()
@Composable
private fun ShortcutHelperSinglePane(
@@ -425,7 +420,7 @@ private fun ShortcutHelperTwoPane(
onKeyboardSettingsClicked: () -> Unit,
) {
val selectedCategory = categories.fastFirstOrNull { it.type == selectedCategoryType }
- Column(modifier = modifier.fillMaxSize().padding(start = 24.dp, end = 24.dp, top = 26.dp)) {
+ Column(modifier = modifier.fillMaxSize().padding(horizontal = 24.dp)) {
TitleBar()
Spacer(modifier = Modifier.height(12.dp))
Row(Modifier.fillMaxWidth()) {
@@ -801,6 +796,8 @@ private fun TitleBar() {
style = MaterialTheme.typography.headlineSmall,
)
},
+ windowInsets = WindowInsets(top = 0.dp, bottom = 0.dp, left = 0.dp, right = 0.dp),
+ expandedHeight = 64.dp,
)
}
@@ -835,6 +832,7 @@ private fun ShortcutsSearchBar(onQueryChange: (String) -> Unit) {
onSearch = {},
leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) },
placeholder = { Text(text = stringResource(R.string.shortcut_helper_search_placeholder)) },
+ windowInsets = WindowInsets(top = 0.dp, bottom = 0.dp, left = 0.dp, right = 0.dp),
content = {},
)
}
@@ -847,9 +845,7 @@ private fun KeyboardSettings(horizontalPadding: Dp, verticalPadding: Dp, onClick
shape = RoundedCornerShape(24.dp),
color = Color.Transparent,
modifier =
- Modifier.semantics { role = Role.Button }
- .fillMaxWidth()
- .padding(horizontal = 12.dp),
+ Modifier.semantics { role = Role.Button }.fillMaxWidth().padding(horizontal = 12.dp),
interactionSource = interactionSource,
interactionsConfig =
InteractionsConfig(
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelperUtils.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelperUtils.kt
new file mode 100644
index 000000000000..1f0d696eebd6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelperUtils.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 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.keyboard.shortcut.ui.composable
+
+import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass
+import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
+import androidx.compose.runtime.Composable
+import com.android.compose.windowsizeclass.LocalWindowSizeClass
+
+/**
+ * returns true if either size of the window is compact. This represents majority of phone windows
+ * portrait
+ */
+@Composable
+fun hasCompactWindowSize() =
+ LocalWindowSizeClass.current.widthSizeClass == WindowWidthSizeClass.Compact ||
+ LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Compact
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt
index 799999aff29b..b9a16c402e59 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/view/ShortcutHelperActivity.kt
@@ -18,31 +18,43 @@ package com.android.systemui.keyboard.shortcut.ui.view
import android.content.ActivityNotFoundException
import android.content.Intent
-import android.graphics.Insets
+import android.content.res.Configuration
import android.os.Bundle
import android.provider.Settings
-import android.view.View
-import android.view.WindowInsets
-import androidx.activity.BackEventCompat
import androidx.activity.ComponentActivity
-import androidx.activity.OnBackPressedCallback
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.ModalBottomSheet
+import androidx.compose.material3.Surface
+import androidx.compose.material3.rememberModalBottomSheetState
+import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
-import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.key.Key
+import androidx.compose.ui.input.key.key
+import androidx.compose.ui.input.key.onKeyEvent
+import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
-import androidx.core.view.updatePadding
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.android.compose.theme.PlatformTheme
import com.android.systemui.keyboard.shortcut.ui.composable.ShortcutHelper
+import com.android.systemui.keyboard.shortcut.ui.composable.hasCompactWindowSize
import com.android.systemui.keyboard.shortcut.ui.viewmodel.ShortcutHelperViewModel
import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
-import com.android.systemui.util.dpToPx
-import com.google.android.material.bottomsheet.BottomSheetBehavior
-import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
-import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
import javax.inject.Inject
import kotlinx.coroutines.launch
@@ -55,52 +67,58 @@ class ShortcutHelperActivity
constructor(private val userTracker: UserTracker, private val viewModel: ShortcutHelperViewModel) :
ComponentActivity() {
- private val bottomSheetContainer
- get() = requireViewById<View>(R.id.shortcut_helper_sheet_container)
-
- private val bottomSheet
- get() = requireViewById<View>(R.id.shortcut_helper_sheet)
-
- private val bottomSheetBehavior
- get() = BottomSheetBehavior.from(bottomSheet)
-
override fun onCreate(savedInstanceState: Bundle?) {
setupEdgeToEdge()
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_keyboard_shortcut_helper)
- setUpWidth()
- expandBottomSheet()
- setUpInsets()
- setUpPredictiveBack()
- setUpSheetDismissListener()
- setUpDismissOnTouchOutside()
- setUpComposeView()
+ setContent { Content() }
observeFinishRequired()
viewModel.onViewOpened()
}
- private fun setUpWidth() {
- // we override this because when maxWidth isn't specified, material imposes a max width
- // constraint on bottom sheets on larger screens which is smaller than our desired width.
- bottomSheetBehavior.maxWidth =
- resources.getDimension(R.dimen.shortcut_helper_width).dpToPx(resources).toInt()
+ @Composable
+ private fun Content() {
+ CompositionLocalProvider(LocalContext provides userTracker.userContext) {
+ PlatformTheme { BottomSheet { finish() } }
+ }
}
- private fun setUpComposeView() {
- requireViewById<ComposeView>(R.id.shortcut_helper_compose_container).apply {
- setContent {
- CompositionLocalProvider(LocalContext provides userTracker.userContext) {
- PlatformTheme {
- val shortcutsUiState by
- viewModel.shortcutsUiState.collectAsStateWithLifecycle()
- ShortcutHelper(
- shortcutsUiState = shortcutsUiState,
- onKeyboardSettingsClicked = ::onKeyboardSettingsClicked,
- onSearchQueryChanged = { viewModel.onSearchQueryChanged(it) },
- )
- }
- }
- }
+ @OptIn(ExperimentalMaterial3Api::class)
+ @Composable
+ private fun BottomSheet(onDismiss: () -> Unit) {
+ ModalBottomSheet(
+ onDismissRequest = { onDismiss() },
+ modifier =
+ Modifier.width(getWidth()).padding(top = getTopPadding()).onKeyEvent {
+ if (it.key == Key.Escape) {
+ onDismiss()
+ true
+ } else false
+ },
+ sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
+ dragHandle = { DragHandle() },
+ ) {
+ val shortcutsUiState by viewModel.shortcutsUiState.collectAsStateWithLifecycle()
+ ShortcutHelper(
+ shortcutsUiState = shortcutsUiState,
+ onKeyboardSettingsClicked = ::onKeyboardSettingsClicked,
+ onSearchQueryChanged = { viewModel.onSearchQueryChanged(it) },
+ )
+ }
+ }
+
+ @Composable
+ fun DragHandle() {
+ val dragHandleContentDescription =
+ stringResource(id = R.string.shortcut_helper_content_description_drag_handle)
+ Surface(
+ modifier =
+ Modifier.padding(top = 16.dp, bottom = 6.dp).semantics {
+ contentDescription = dragHandleContentDescription
+ },
+ color = MaterialTheme.colorScheme.outlineVariant,
+ shape = MaterialTheme.shapes.extraLarge,
+ ) {
+ Box(Modifier.size(width = 32.dp, height = 4.dp))
}
}
@@ -139,81 +157,27 @@ constructor(private val userTracker: UserTracker, private val viewModel: Shortcu
window.setDecorFitsSystemWindows(false)
}
- private fun setUpInsets() {
- bottomSheetContainer.setOnApplyWindowInsetsListener { _, insets ->
- val safeDrawingInsets = insets.safeDrawing
- // Make sure the bottom sheet is not covered by the status bar.
- bottomSheetBehavior.maxHeight =
- windowManager.maximumWindowMetrics.bounds.height() - safeDrawingInsets.top
- // Make sure the contents inside of the bottom sheet are not hidden by system bars, or
- // cutouts.
- bottomSheet.updatePadding(
- left = safeDrawingInsets.left,
- right = safeDrawingInsets.right,
- bottom = safeDrawingInsets.bottom,
- )
- // The bottom sheet has to be expanded only after setting up insets, otherwise there is
- // a bug and it will not use full height.
- expandBottomSheet()
-
- // Return CONSUMED if you don't want want the window insets to keep passing
- // down to descendant views.
- WindowInsets.CONSUMED
- }
- }
-
- private fun expandBottomSheet() {
- bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
- bottomSheetBehavior.skipCollapsed = true
+ @Composable
+ private fun getTopPadding(): Dp {
+ return if (hasCompactWindowSize()) DefaultTopPadding else LargeScreenTopPadding
}
- private fun setUpPredictiveBack() {
- val onBackPressedCallback =
- object : OnBackPressedCallback(/* enabled= */ true) {
- override fun handleOnBackStarted(backEvent: BackEventCompat) {
- bottomSheetBehavior.startBackProgress(backEvent)
- }
-
- override fun handleOnBackProgressed(backEvent: BackEventCompat) {
- bottomSheetBehavior.updateBackProgress(backEvent)
- }
-
- override fun handleOnBackPressed() {
- bottomSheetBehavior.handleBackInvoked()
- }
-
- override fun handleOnBackCancelled() {
- bottomSheetBehavior.cancelBackProgress()
- }
+ @Composable
+ private fun getWidth(): Dp {
+ return if (hasCompactWindowSize()) {
+ DefaultWidth
+ } else
+ when (LocalConfiguration.current.orientation) {
+ Configuration.ORIENTATION_LANDSCAPE -> LargeScreenWidthLandscape
+ else -> LargeScreenWidthPortrait
}
- onBackPressedDispatcher.addCallback(
- owner = this,
- onBackPressedCallback = onBackPressedCallback,
- )
}
- private fun setUpSheetDismissListener() {
- bottomSheetBehavior.addBottomSheetCallback(
- object : BottomSheetCallback() {
- override fun onStateChanged(bottomSheet: View, newState: Int) {
- if (newState == STATE_HIDDEN) {
- finish()
- }
- }
-
- override fun onSlide(bottomSheet: View, slideOffset: Float) {}
- }
- )
- }
-
- private fun setUpDismissOnTouchOutside() {
- bottomSheetContainer.setOnClickListener { finish() }
+ companion object {
+ private val DefaultTopPadding = 64.dp
+ private val LargeScreenTopPadding = 72.dp
+ private val DefaultWidth = 412.dp
+ private val LargeScreenWidthPortrait = 704.dp
+ private val LargeScreenWidthLandscape = 864.dp
}
}
-
-private val WindowInsets.safeDrawing
- get() =
- getInsets(WindowInsets.Type.systemBars())
- .union(getInsets(WindowInsets.Type.displayCutout()))
-
-private fun Insets.union(insets: Insets): Insets = Insets.max(this, insets)