diff --git a/packages/SystemUI/compose/core/TEST_MAPPING b/packages/SystemUI/compose/core/TEST_MAPPING index 6b7f69e981456..dc243d2fd8f58 100644 --- a/packages/SystemUI/compose/core/TEST_MAPPING +++ b/packages/SystemUI/compose/core/TEST_MAPPING @@ -21,6 +21,17 @@ "exclude-annotation": "androidx.test.filters.FlakyTest" } ] + }, + { + "name": "SystemUIComposeGalleryTests", + "options": [ + { + "exclude-annotation": "org.junit.Ignore" + }, + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + } + ] } ] } \ No newline at end of file diff --git a/packages/SystemUI/compose/features/TEST_MAPPING b/packages/SystemUI/compose/features/TEST_MAPPING index 55d8e2f737534..7430acb2e900c 100644 --- a/packages/SystemUI/compose/features/TEST_MAPPING +++ b/packages/SystemUI/compose/features/TEST_MAPPING @@ -10,6 +10,17 @@ "exclude-annotation": "androidx.test.filters.FlakyTest" } ] + }, + { + "name": "SystemUIComposeGalleryTests", + "options": [ + { + "exclude-annotation": "org.junit.Ignore" + }, + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + } + ] } ] } \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/Android.bp b/packages/SystemUI/compose/gallery/Android.bp new file mode 100644 index 0000000000000..030ad854992ad --- /dev/null +++ b/packages/SystemUI/compose/gallery/Android.bp @@ -0,0 +1,70 @@ +// Copyright (C) 2022 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"], +} + +android_library { + name: "SystemUIComposeGalleryLib", + manifest: "AndroidManifest.xml", + + srcs: [ + "src/**/*.kt", + ], + + resource_dirs: [ + "res", + ], + + static_libs: [ + "SystemUIComposeCore", + "SystemUIComposeFeatures", + + "androidx.compose.runtime_runtime", + "androidx.compose.material3_material3", + "androidx.compose.material_material-icons-extended", + "androidx.activity_activity-compose", + "androidx.navigation_navigation-compose", + + "androidx.appcompat_appcompat", + ], + + kotlincflags: ["-Xjvm-default=all"], +} + +android_app { + name: "SystemUIComposeGallery", + defaults: ["platform_app_defaults"], + + static_libs: [ + "SystemUIComposeGalleryLib", + ], + + platform_apis: true, + system_ext_specific: true, + certificate: "platform", + privileged: true, + + optimize: { + proguard_flags_files: ["proguard-rules.pro"], + }, + + dxflags: ["--multi-dex"], +} diff --git a/packages/SystemUI/compose/gallery/AndroidManifest.xml b/packages/SystemUI/compose/gallery/AndroidManifest.xml new file mode 100644 index 0000000000000..81132632079af --- /dev/null +++ b/packages/SystemUI/compose/gallery/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/packages/SystemUI/compose/gallery/TEST_MAPPING b/packages/SystemUI/compose/gallery/TEST_MAPPING new file mode 100644 index 0000000000000..c7f8a92164188 --- /dev/null +++ b/packages/SystemUI/compose/gallery/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "SystemUIComposeGalleryTests", + "options": [ + { + "exclude-annotation": "org.junit.Ignore" + }, + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/proguard-rules.pro b/packages/SystemUI/compose/gallery/proguard-rules.pro new file mode 100644 index 0000000000000..481bb43481410 --- /dev/null +++ b/packages/SystemUI/compose/gallery/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/res/drawable-v24/ic_launcher_foreground.xml b/packages/SystemUI/compose/gallery/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000000000..966abaff20743 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/res/drawable/ic_launcher_background.xml b/packages/SystemUI/compose/gallery/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000000..61bb79edb7090 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/compose/gallery/res/mipmap-anydpi-v26/ic_launcher.xml b/packages/SystemUI/compose/gallery/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000000..03eed2533da28 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/res/mipmap-anydpi-v26/ic_launcher_round.xml b/packages/SystemUI/compose/gallery/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000000..03eed2533da28 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/res/mipmap-hdpi/ic_launcher.webp b/packages/SystemUI/compose/gallery/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000000000..c209e78ecd372 Binary files /dev/null and b/packages/SystemUI/compose/gallery/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/packages/SystemUI/compose/gallery/res/mipmap-hdpi/ic_launcher_round.webp b/packages/SystemUI/compose/gallery/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000..b2dfe3d1ba5cf Binary files /dev/null and b/packages/SystemUI/compose/gallery/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/packages/SystemUI/compose/gallery/res/mipmap-mdpi/ic_launcher.webp b/packages/SystemUI/compose/gallery/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000000000..4f0f1d64e58ba Binary files /dev/null and b/packages/SystemUI/compose/gallery/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/packages/SystemUI/compose/gallery/res/mipmap-mdpi/ic_launcher_round.webp b/packages/SystemUI/compose/gallery/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000..62b611da08167 Binary files /dev/null and b/packages/SystemUI/compose/gallery/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/packages/SystemUI/compose/gallery/res/mipmap-xhdpi/ic_launcher.webp b/packages/SystemUI/compose/gallery/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000000000..948a3070fe34c Binary files /dev/null and b/packages/SystemUI/compose/gallery/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/packages/SystemUI/compose/gallery/res/mipmap-xhdpi/ic_launcher_round.webp b/packages/SystemUI/compose/gallery/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000..1b9a6956b3acd Binary files /dev/null and b/packages/SystemUI/compose/gallery/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/packages/SystemUI/compose/gallery/res/mipmap-xxhdpi/ic_launcher.webp b/packages/SystemUI/compose/gallery/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000..28d4b77f9f036 Binary files /dev/null and b/packages/SystemUI/compose/gallery/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/packages/SystemUI/compose/gallery/res/mipmap-xxhdpi/ic_launcher_round.webp b/packages/SystemUI/compose/gallery/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000..9287f5083623b Binary files /dev/null and b/packages/SystemUI/compose/gallery/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/packages/SystemUI/compose/gallery/res/mipmap-xxxhdpi/ic_launcher.webp b/packages/SystemUI/compose/gallery/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000..aa7d6427e6fa1 Binary files /dev/null and b/packages/SystemUI/compose/gallery/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/packages/SystemUI/compose/gallery/res/mipmap-xxxhdpi/ic_launcher_round.webp b/packages/SystemUI/compose/gallery/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000..9126ae37cbc35 Binary files /dev/null and b/packages/SystemUI/compose/gallery/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/packages/SystemUI/compose/gallery/res/values-night/themes.xml b/packages/SystemUI/compose/gallery/res/values-night/themes.xml new file mode 100644 index 0000000000000..58d20b88c13b1 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/values-night/themes.xml @@ -0,0 +1,26 @@ + + + + + \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/res/values/colors.xml b/packages/SystemUI/compose/gallery/res/values/colors.xml new file mode 100644 index 0000000000000..a2fcbffc26c07 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/values/colors.xml @@ -0,0 +1,19 @@ + + + + #FFFFFF + \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/res/values/strings.xml b/packages/SystemUI/compose/gallery/res/values/strings.xml new file mode 100644 index 0000000000000..86bdb05688371 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/values/strings.xml @@ -0,0 +1,20 @@ + + + + + SystemUI Gallery + \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/res/values/themes.xml b/packages/SystemUI/compose/gallery/res/values/themes.xml new file mode 100644 index 0000000000000..6e5e99832f094 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/values/themes.xml @@ -0,0 +1,27 @@ + + + + + \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ColorsScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ColorsScreen.kt new file mode 100644 index 0000000000000..ac9fdbf2eee9a --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ColorsScreen.kt @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2022 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.compose.gallery + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp + +/** The screen that shows all the Material 3 colors. */ +@Composable +fun ColorsScreen() { + val colors = MaterialTheme.colorScheme + LazyColumn { + item { ColorTile(colors.primary, "primary") } + item { ColorTile(colors.onPrimary, "onPrimary") } + item { ColorTile(colors.primaryContainer, "primaryContainer") } + item { ColorTile(colors.onPrimaryContainer, "onPrimaryContainer") } + item { ColorTile(colors.inversePrimary, "inversePrimary") } + item { ColorTile(colors.secondary, "secondary") } + item { ColorTile(colors.onSecondary, "onSecondary") } + item { ColorTile(colors.secondaryContainer, "secondaryContainer") } + item { ColorTile(colors.onSecondaryContainer, "onSecondaryContainer") } + item { ColorTile(colors.tertiary, "tertiary") } + item { ColorTile(colors.onTertiary, "onTertiary") } + item { ColorTile(colors.tertiaryContainer, "tertiaryContainer") } + item { ColorTile(colors.onTertiaryContainer, "onTertiaryContainer") } + item { ColorTile(colors.background, "background") } + item { ColorTile(colors.onBackground, "onBackground") } + item { ColorTile(colors.surface, "surface") } + item { ColorTile(colors.onSurface, "onSurface") } + item { ColorTile(colors.surfaceVariant, "surfaceVariant") } + item { ColorTile(colors.onSurfaceVariant, "onSurfaceVariant") } + item { ColorTile(colors.inverseSurface, "inverseSurface") } + item { ColorTile(colors.inverseOnSurface, "inverseOnSurface") } + item { ColorTile(colors.error, "error") } + item { ColorTile(colors.onError, "onError") } + item { ColorTile(colors.errorContainer, "errorContainer") } + item { ColorTile(colors.onErrorContainer, "onErrorContainer") } + item { ColorTile(colors.outline, "outline") } + } +} + +@Composable +private fun ColorTile( + color: Color, + name: String, +) { + Row( + Modifier.padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + val shape = RoundedCornerShape(16.dp) + Spacer( + Modifier + .border(1.dp, MaterialTheme.colorScheme.onBackground, shape) + .background(color, shape) + .size(64.dp) + ) + Spacer(Modifier.width(16.dp)) + Text(name) + } +} \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ConfigurationControls.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ConfigurationControls.kt new file mode 100644 index 0000000000000..e8e6080b9fa18 --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ConfigurationControls.kt @@ -0,0 +1,86 @@ +package com.android.systemui.compose.gallery + +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.BrightnessHigh +import androidx.compose.material.icons.filled.BrightnessLow +import androidx.compose.material.icons.filled.FormatSize +import androidx.compose.material.icons.filled.FormatTextdirectionLToR +import androidx.compose.material.icons.filled.FormatTextdirectionRToL +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp + +enum class FontScale(val scale: Float) { + Small(0.85f), + Normal(1f), + Big(1.15f), + Bigger(1.30f), +} + +/** A configuration panel that allows to toggle the theme, font scale and layout direction. */ +@Composable +fun ConfigurationControls( + isDarkTheme: Boolean, + fontScale: FontScale, + layoutDirection: LayoutDirection, + onChangeTheme: () -> Unit, + onChangeLayoutDirection: () -> Unit, + onChangeFontScale: () -> Unit, +) { + LazyRow { + // Dark/light theme. + item { + TextButton(onChangeTheme) { + val text: String + val icon: ImageVector + if (isDarkTheme) { + icon = Icons.Default.BrightnessHigh + text = "Dark" + } else { + icon = Icons.Default.BrightnessLow + text = "Light" + } + + Icon(icon, null) + Spacer(Modifier.width(8.dp)) + Text(text) + } + } + + // Font scale. + item { + TextButton(onChangeFontScale) { + Icon(Icons.Default.FormatSize, null) + Spacer(Modifier.width(8.dp)) + + Text(fontScale.name) + } + } + + // Layout direction. + item { + TextButton(onChangeLayoutDirection) { + when (layoutDirection) { + LayoutDirection.Ltr -> { + Icon(Icons.Default.FormatTextdirectionLToR, null) + Spacer(Modifier.width(8.dp)) + Text("LTR") + } + LayoutDirection.Rtl -> { + Icon(Icons.Default.FormatTextdirectionRToL, null) + Spacer(Modifier.width(8.dp)) + Text("RTL") + } + } + } + } + } +} \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ExampleFeatureScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ExampleFeatureScreen.kt new file mode 100644 index 0000000000000..1c6b9b09ff3ac --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ExampleFeatureScreen.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022 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.compose.gallery + +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import com.android.systemui.ExampleFeature + +/** The screen that shows ExampleFeature. */ +@Composable +fun ExampleFeatureScreen() { + Column { + ExampleFeature("This is an example feature!") + } +} \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryActivity.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryActivity.kt new file mode 100644 index 0000000000000..fce632d1b90aa --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryActivity.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022 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.compose.gallery + +import android.os.Bundle +import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.isSystemInDarkTheme +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.core.view.WindowCompat + +class GalleryActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + WindowCompat.setDecorFitsSystemWindows(window, false) + + setContent { + val isSystemInDarkTheme = isSystemInDarkTheme() + var isDarkTheme by remember { mutableStateOf(isSystemInDarkTheme) } + val onChangeTheme = { isDarkTheme = !isDarkTheme } + + LaunchedEffect(isDarkTheme) { + // Update the status bar color when the theme changes. + val insetsController = window.decorView.windowInsetsController + if (isDarkTheme) { + insetsController.setSystemBarsAppearance(0, APPEARANCE_LIGHT_STATUS_BARS) + } else { + insetsController.setSystemBarsAppearance( + APPEARANCE_LIGHT_STATUS_BARS, APPEARANCE_LIGHT_STATUS_BARS) + } + } + + GalleryApp(isDarkTheme, onChangeTheme) + } + } +} diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt new file mode 100644 index 0000000000000..f7d311b288bee --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt @@ -0,0 +1,127 @@ +package com.android.systemui.compose.gallery + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import com.android.systemui.compose.theme.SystemUITheme + +enum class Screen { + Home, + Typography, + Colors, + ExampleFeature, +} + +/** The main content of the app, that shows the [HomeScreen] by default. */ +@Composable +private fun MainContent() { + Box(Modifier.fillMaxSize()) { + val navController = rememberNavController() + NavHost( + navController = navController, + startDestination = Screen.Home.name, + ) { + composable(Screen.Home.name) { + HomeScreen( + onScreenSelected = { navController.navigate(it.name) }, + ) + } + composable(Screen.Typography.name) { TypographyScreen() } + composable(Screen.Colors.name) { ColorsScreen() } + composable(Screen.ExampleFeature.name) { ExampleFeatureScreen() } + } + } +} + +/** + * The top-level composable shown when starting the app. This composable always shows a + * [ConfigurationControls] at the top of the screen, above the [MainContent]. + */ +@Composable +fun GalleryApp( + isDarkTheme: Boolean, + onChangeTheme: () -> Unit, +) { + val systemFontScale = LocalDensity.current.fontScale + var fontScale: FontScale by remember { + mutableStateOf( + FontScale + .values() + .firstOrNull { it.scale == systemFontScale } + ?: FontScale.Normal + ) + } + val context = LocalContext.current + val density = Density(context.resources.displayMetrics.density, fontScale.scale) + val onChangeFontScale = { + fontScale = when (fontScale) { + FontScale.Small -> FontScale.Normal + FontScale.Normal -> FontScale.Big + FontScale.Big -> FontScale.Bigger + FontScale.Bigger -> FontScale.Small + } + } + + val systemLayoutDirection = LocalLayoutDirection.current + var layoutDirection by remember { mutableStateOf(systemLayoutDirection) } + val onChangeLayoutDirection = { + layoutDirection = when (layoutDirection) { + LayoutDirection.Ltr -> LayoutDirection.Rtl + LayoutDirection.Rtl -> LayoutDirection.Ltr + } + } + + CompositionLocalProvider( + LocalDensity provides density, + LocalLayoutDirection provides layoutDirection, + ) { + SystemUITheme(isDarkTheme) { + Surface( + Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background, + ) { + Column( + Modifier + .fillMaxSize() + .systemBarsPadding() + .padding(16.dp) + ) { + ConfigurationControls( + isDarkTheme, + fontScale, + layoutDirection, + onChangeTheme, + onChangeLayoutDirection, + onChangeFontScale, + ) + + Spacer(Modifier.height(4.dp)) + + MainContent() + } + } + } + } +} diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt new file mode 100644 index 0000000000000..d0f265c071777 --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/HomeScreen.kt @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2022 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.compose.gallery + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +/** The home screen shown when starting the app. */ +@Composable +fun HomeScreen(onScreenSelected: (Screen) -> Unit) { + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + Screen.values() + .filter { it != Screen.Home } + .forEach { screen -> + item { + Surface( + Modifier.fillMaxWidth(), + color = MaterialTheme.colorScheme.secondaryContainer, + shape = CircleShape, + ) { + Column( + Modifier + .clickable { onScreenSelected(screen) } + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text(screen.name) + } + } + } + } + } +} \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/TypographyScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/TypographyScreen.kt new file mode 100644 index 0000000000000..32191916547d9 --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/TypographyScreen.kt @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2022 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.compose.gallery + +import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextOverflow + +/** The screen that shows the Material text styles. */ +@Composable +fun TypographyScreen() { + val typography = MaterialTheme.typography + + Column( + Modifier + .fillMaxSize() + .horizontalScroll(rememberScrollState()) + .verticalScroll(rememberScrollState()), + ) { + FontLine("displayLarge", typography.displayLarge) + FontLine("displayMedium", typography.displayMedium) + FontLine("displaySmall", typography.displaySmall) + FontLine("headlineLarge", typography.headlineLarge) + FontLine("headlineMedium", typography.headlineMedium) + FontLine("headlineSmall", typography.headlineSmall) + FontLine("titleLarge", typography.titleLarge) + FontLine("titleMedium", typography.titleMedium) + FontLine("titleSmall", typography.titleSmall) + FontLine("bodyLarge", typography.bodyLarge) + FontLine("bodyMedium", typography.bodyMedium) + FontLine("bodySmall", typography.bodySmall) + FontLine("labelLarge", typography.labelLarge) + FontLine("labelMedium", typography.labelMedium) + FontLine("labelSmall", typography.labelSmall) + } +} + +@Composable +private fun FontLine(name: String, style: TextStyle) { + Text( + "$name (${style.fontSize}/${style.lineHeight}, W${style.fontWeight?.weight})", + style = style, + maxLines = 1, + overflow = TextOverflow.Visible, + ) +} diff --git a/packages/SystemUI/compose/gallery/tests/Android.bp b/packages/SystemUI/compose/gallery/tests/Android.bp new file mode 100644 index 0000000000000..3e01f7d2c431f --- /dev/null +++ b/packages/SystemUI/compose/gallery/tests/Android.bp @@ -0,0 +1,47 @@ +// Copyright (C) 2022 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"], +} + +android_test { + name: "SystemUIComposeGalleryTests", + manifest: "AndroidManifest.xml", + test_suites: ["device-tests"], + sdk_version: "current", + certificate: "platform", + + srcs: [ + "src/**/*.kt", + ], + + static_libs: [ + "SystemUIComposeGalleryLib", + + "androidx.test.runner", + "androidx.test.ext.junit", + + "androidx.compose.runtime_runtime", + "androidx.compose.ui_ui-test-junit4", + "androidx.compose.ui_ui-test-manifest", + ], + + kotlincflags: ["-Xjvm-default=enable"], +} diff --git a/packages/SystemUI/compose/gallery/tests/AndroidManifest.xml b/packages/SystemUI/compose/gallery/tests/AndroidManifest.xml new file mode 100644 index 0000000000000..5eeb3ad24e5aa --- /dev/null +++ b/packages/SystemUI/compose/gallery/tests/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/compose/gallery/tests/src/com/android/systemui/compose/gallery/ScreenshotsTests.kt b/packages/SystemUI/compose/gallery/tests/src/com/android/systemui/compose/gallery/ScreenshotsTests.kt new file mode 100644 index 0000000000000..6fb1674d3f166 --- /dev/null +++ b/packages/SystemUI/compose/gallery/tests/src/com/android/systemui/compose/gallery/ScreenshotsTests.kt @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 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.compose.gallery + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.systemui.compose.theme.SystemUITheme +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ScreenshotsTests { + @get:Rule + val composeRule = createComposeRule() + + @Test + fun exampleFeatureScreenshotTest() { + // TODO(b/230832101): Wire this with the screenshot diff testing infra. We should reuse the + // configuration of the features in the gallery app to populate the UIs. + composeRule.setContent { + SystemUITheme { + ExampleFeatureScreen() + } + } + } +}