diff options
author | 2024-11-08 15:47:08 +0000 | |
---|---|---|
committer | 2024-11-08 15:47:08 +0000 | |
commit | 74f7be2e81f4f3c09a30b134b4033829dbc6f0fc (patch) | |
tree | d2f867a7ff2b20ce73775d12f0b9ea43a60e72d3 | |
parent | 5468d804eb6ecdfc6f0fc0b4cf0b9278ccb60e52 (diff) | |
parent | 69a9c56e44cdace902a974e68a916b76372db320 (diff) |
Merge "Supporting Material 3 UI in Role Request Screen" into main
5 files changed, 150 insertions, 35 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButton.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButton.kt index 4ed9e92b9..e0adf1265 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButton.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButton.kt @@ -20,10 +20,13 @@ import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.Hyphens import androidx.wear.compose.material3.Button import androidx.wear.compose.material3.ButtonColors import androidx.wear.compose.material3.ButtonDefaults import androidx.wear.compose.material3.LocalTextConfiguration +import androidx.wear.compose.material3.LocalTextStyle import androidx.wear.compose.material3.Text import com.android.permissioncontroller.permission.ui.wear.elements.Chip import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion @@ -94,6 +97,8 @@ private fun WearPermissionButtonInternal( text = label, modifier = Modifier.fillMaxWidth(), maxLines = labelMaxLines ?: LocalTextConfiguration.current.maxLines, + style = + LocalTextStyle.current.copy(fontWeight = FontWeight.W600, hyphens = Hyphens.Auto), ) } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButtonStyle.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButtonStyle.kt index 5a91ae46c..504c69bb0 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButtonStyle.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButtonStyle.kt @@ -21,6 +21,7 @@ import androidx.wear.compose.material.ChipColors import androidx.wear.compose.material.ChipDefaults import androidx.wear.compose.material3.ButtonColors import androidx.wear.compose.material3.ButtonDefaults +import com.android.permissioncontroller.permission.ui.wear.elements.chipDefaultColors import com.android.permissioncontroller.permission.ui.wear.elements.chipDisabledColors import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle.DisabledLike import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle.Primary @@ -41,7 +42,7 @@ enum class WearPermissionButtonStyle { @Composable internal fun WearPermissionButtonStyle.material2ChipColors(): ChipColors { return when (this) { - Primary -> ChipDefaults.primaryChipColors() + Primary -> chipDefaultColors() Secondary -> ChipDefaults.secondaryChipColors() Transparent -> ChipDefaults.childChipColors() DisabledLike -> chipDisabledColors() diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListFooter.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListFooter.kt new file mode 100644 index 000000000..807c93370 --- /dev/null +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListFooter.kt @@ -0,0 +1,67 @@ +/* + * 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.permissioncontroller.permission.ui.wear.elements.material3 + +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.requiredHeightIn +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.wear.compose.material3.Button +import androidx.wear.compose.material3.ButtonDefaults +import androidx.wear.compose.material3.Text +import com.android.permissioncontroller.permission.ui.wear.elements.ListFooter +import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion + +@Composable +fun WearPermissionListFooter( + materialUIVersion: WearPermissionMaterialUIVersion, + label: String, + iconBuilder: WearPermissionIconBuilder? = null, + onClick: (() -> Unit) = {}, +) { + if (materialUIVersion == WearPermissionMaterialUIVersion.MATERIAL2_5) { + ListFooter( + description = label, + iconRes = iconBuilder?.let { it.iconResource as Int }, + onClick = onClick, + ) + } else { + WearPermissionListFooterInternal(label, iconBuilder, onClick) + } +} + +@Composable +private fun WearPermissionListFooterInternal( + label: String, + iconBuilder: WearPermissionIconBuilder?, + onClick: () -> Unit, +) { + val footerTextComposable: (@Composable RowScope.() -> Unit) = { + Text(modifier = Modifier.fillMaxWidth(), text = label, maxLines = Int.MAX_VALUE) + } + Button( + icon = { iconBuilder?.build() }, + label = {}, + secondaryLabel = footerTextComposable, + enabled = true, + onClick = onClick, + modifier = Modifier.requiredHeightIn(min = 1.dp).fillMaxWidth(), + colors = ButtonDefaults.childButtonColors(), + ) +} diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearPermissionTheme.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearPermissionTheme.kt index cfaaa0df9..adf179be6 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearPermissionTheme.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearPermissionTheme.kt @@ -35,15 +35,16 @@ import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion.MATERIAL2_5 import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion.MATERIAL3 +/** This enum is used to specify the material version used for a specific screen */ enum class WearPermissionMaterialUIVersion { MATERIAL2_5, MATERIAL3, } /** - * Supports both Material 3 and Material 2 theme. default version for permission theme will be - * LEGACY until we migrate enough screens to 3. LEGACY version will use material 3 overlay resources - * by default. + * Supports both Material 3 and Material 2_5 theme. default version for permission theme will be 2_5 + * until we migrate enough screens to 3. 2_5 version will use material 3 overlay resources if we + * enable material3 for even one screen (Permission screens will be migrated in phases). */ @Composable fun WearPermissionTheme( @@ -53,7 +54,9 @@ fun WearPermissionTheme( if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) { WearPermissionLegacyTheme(content) } else { + // Whether we are ready to use material3 for any screen. val useBridgedTheme = Flags.wearComposeMaterial3() + // Material3 UI controls are still being used in the screen that the theme is applied if (version == MATERIAL3) { val material3Theme = WearOverlayableMaterial3Theme(LocalContext.current) Material3Theme( @@ -62,7 +65,12 @@ fun WearPermissionTheme( shapes = material3Theme.shapes, content = content, ) - } else if (version == MATERIAL2_5 && useBridgedTheme) { + } + // Material2_5 UI controls are still being used in the screen that the theme is applied, + // But some in-app screens(like permission grant screen) are migrated to material3. + // To avoid having two set of overlay resources, we will use material3 overlay resources to + // support material2_5 UI controls as well. + else if (version == MATERIAL2_5 && useBridgedTheme) { val material3Theme = WearOverlayableMaterial3Theme(LocalContext.current) val bridgedLegacyTheme = WearMaterialBridgedLegacyTheme.createFrom(material3Theme) MaterialTheme( @@ -71,7 +79,9 @@ fun WearPermissionTheme( shapes = bridgedLegacyTheme.shapes, content = content, ) - } else { + } + // We are not ready for material3 yet in any screens. + else { WearPermissionLegacyTheme(content) } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt index 13a9cb6d6..ee8fe2545 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt @@ -30,22 +30,26 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.wear.compose.material.ChipDefaults -import androidx.wear.compose.material.MaterialTheme +import com.android.permission.flags.Flags import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.ui.wear.elements.Chip -import com.android.permissioncontroller.permission.ui.wear.elements.ListFooter import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChip import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChipToggleControl -import com.android.permissioncontroller.permission.ui.wear.elements.toggleChipBackgroundColors +import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton +import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle +import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder +import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionListFooter +import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControl +import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlStyle +import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion.MATERIAL2_5 +import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion.MATERIAL3 import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData @Composable fun WearRequestRoleScreen( helper: WearRequestRoleHelper, onSetAsDefault: (Boolean, String?) -> Unit, - onCanceled: () -> Unit + onCanceled: () -> Unit, ) { val roleLiveData = helper.viewModel.roleLiveData.observeAsState(emptyList()) val manageRoleHolderState = @@ -75,7 +79,15 @@ fun WearRequestRoleScreen( } } + val useMaterial3Controls = Flags.wearComposeMaterial3() + val materialUIVersion = + if (useMaterial3Controls) { + MATERIAL3 + } else { + MATERIAL2_5 + } WearRequestRoleContent( + materialUIVersion, isLoading, helper, roleLiveData.value, @@ -85,7 +97,7 @@ fun WearRequestRoleScreen( onCheckedChanged, onDontAskAgainCheckedChanged, onSetAsDefault, - onCanceled + onCanceled, ) if (isLoading && roleLiveData.value.isNotEmpty()) { @@ -95,6 +107,7 @@ fun WearRequestRoleScreen( @Composable internal fun WearRequestRoleContent( + materialUIVersion: WearPermissionMaterialUIVersion, isLoading: Boolean, helper: WearRequestRoleHelper, qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>, @@ -104,56 +117,74 @@ internal fun WearRequestRoleContent( onCheckedChanged: (Boolean, String?, Boolean) -> Unit, onDontAskAgainCheckedChanged: (Boolean) -> Unit, onSetAsDefault: (Boolean, String?) -> Unit, - onCanceled: () -> Unit + onCanceled: () -> Unit, ) { ScrollableScreen( + materialUIVersion = materialUIVersion, image = helper.getIcon(), title = helper.getTitle(), showTimeText = false, - isLoading = isLoading + isLoading = isLoading, ) { - helper.getNonePreference(qualifyingApplications, selectedPackageName)?.let { + helper.getNonePreference(qualifyingApplications, selectedPackageName)?.let { pref -> item { - ToggleChip( - label = it.label, - icon = it.icon, - enabled = enabled && it.enabled, - checked = it.checked, + WearPermissionToggleControl( + materialUIVersion = materialUIVersion, + label = pref.label, + iconBuilder = pref.icon?.let { WearPermissionIconBuilder.builder(it) }, + enabled = enabled && pref.enabled, + checked = pref.checked, onCheckedChanged = { checked -> - run { onCheckedChanged(checked, it.packageName, it.isHolder) } + onCheckedChanged(checked, pref.packageName, pref.isHolder) }, toggleControl = ToggleChipToggleControl.Radio, - labelMaxLine = Integer.MAX_VALUE + labelMaxLines = Integer.MAX_VALUE, ) } - it.subTitle?.let { subTitle -> item { ListFooter(description = subTitle) } } + pref.subTitle?.let { subTitle -> + item { + WearPermissionListFooter( + materialUIVersion = materialUIVersion, + label = subTitle, + ) + } + } } for (pref in helper.getPreferences(qualifyingApplications, selectedPackageName)) { item { - ToggleChip( + WearPermissionToggleControl( + materialUIVersion = materialUIVersion, label = pref.label, - icon = pref.icon, + iconBuilder = pref.icon?.let { WearPermissionIconBuilder.builder(it) }, enabled = enabled && pref.enabled, checked = pref.checked, onCheckedChanged = { checked -> - run { onCheckedChanged(checked, pref.packageName, pref.isHolder) } + onCheckedChanged(checked, pref.packageName, pref.isHolder) }, toggleControl = ToggleChipToggleControl.Radio, ) } - pref.subTitle?.let { subTitle -> item { ListFooter(description = subTitle) } } + pref.subTitle?.let { subTitle -> + item { + WearPermissionListFooter( + materialUIVersion = materialUIVersion, + label = subTitle, + ) + } + } } if (helper.showDontAskButton()) { item { - ToggleChip( + WearPermissionToggleControl( + materialUIVersion = materialUIVersion, checked = dontAskAgain, enabled = enabled, onCheckedChanged = { checked -> run { onDontAskAgainCheckedChanged(checked) } }, label = stringResource(R.string.request_role_dont_ask_again), toggleControl = ToggleChipToggleControl.Checkbox, - colors = toggleChipBackgroundColors(), + style = WearPermissionToggleControlStyle.Transparent, modifier = Modifier.testTag("com.android.permissioncontroller:id/dont_ask_again"), ) @@ -163,17 +194,18 @@ internal fun WearRequestRoleContent( item { Spacer(modifier = Modifier.height(14.dp)) } item { - Chip( + WearPermissionButton( + materialUIVersion = materialUIVersion, label = stringResource(R.string.request_role_set_as_default), - textColor = MaterialTheme.colors.background, - colors = ChipDefaults.primaryChipColors(), + style = WearPermissionButtonStyle.Primary, enabled = helper.shouldSetAsDefaultEnabled(enabled), onClick = { onSetAsDefault(dontAskAgain, selectedPackageName) }, modifier = Modifier.testTag("android:id/button1"), ) } item { - Chip( + WearPermissionButton( + materialUIVersion = materialUIVersion, label = stringResource(R.string.cancel), enabled = enabled, onClick = { onCanceled() }, |