Move the Compose Gallery to our vendor repository (2/2)

Bug: 247473910
Test: Builds
Change-Id: I665f351cda86dc6588946b8449fbb1c13fcba503
This commit is contained in:
Jordan Demeulenaere
2022-09-20 15:46:30 +02:00
parent 13590497c4
commit 0d5de04586
44 changed files with 0 additions and 2052 deletions

View File

@@ -1,86 +0,0 @@
// 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",
":SystemUI-tests-utils",
],
resource_dirs: [
"res",
],
static_libs: [
"SystemUI-core",
"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",
// TODO(b/240431193): Remove the dependencies and depend on
// SystemUI-test-utils directly.
"androidx.test.runner",
"mockito-target-extended-minus-junit4",
"testables",
"truth-prebuilt",
"androidx.test.uiautomator",
"kotlinx_coroutines_test",
],
libs: [
"android.test.mock",
],
kotlincflags: ["-Xjvm-default=all"],
}
android_app {
name: "SystemUIComposeGallery",
defaults: ["platform_app_defaults"],
manifest: "app/AndroidManifest.xml",
static_libs: [
"SystemUIComposeGalleryLib",
],
platform_apis: true,
system_ext_specific: true,
certificate: "platform",
privileged: true,
optimize: {
proguard_flags_files: ["proguard-rules.pro"],
},
dxflags: ["--multi-dex"],
}

View File

@@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.android.systemui.compose.gallery">
<!-- To emulate a display size and density. -->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application
android:name="android.app.Application"
android:appComponentFactory="androidx.core.app.AppComponentFactory"
tools:replace="android:name,android:appComponentFactory">
<!-- Disable providers from SystemUI -->
<provider android:name="com.android.systemui.keyguard.KeyguardSliceProvider"
android:authorities="com.android.systemui.test.keyguard.disabled"
android:enabled="false"
tools:replace="android:authorities"
tools:node="remove" />
<provider android:name="com.google.android.systemui.keyguard.KeyguardSliceProviderGoogle"
android:authorities="com.android.systemui.test.keyguard.disabled"
android:enabled="false"
tools:replace="android:authorities"
tools:node="remove" />
<provider android:name="com.android.keyguard.clock.ClockOptionsProvider"
android:authorities="com.android.systemui.test.keyguard.clock.disabled"
android:enabled="false"
tools:replace="android:authorities"
tools:node="remove" />
<provider android:name="com.android.systemui.people.PeopleProvider"
android:authorities="com.android.systemui.test.people.disabled"
android:enabled="false"
tools:replace="android:authorities"
tools:node="remove" />
<provider android:name="androidx.core.content.FileProvider"
android:authorities="com.android.systemui.test.fileprovider.disabled"
android:enabled="false"
tools:replace="android:authorities"
tools:node="remove"/>
</application>
</manifest>

View File

@@ -1,15 +0,0 @@
{
"presubmit": [
{
"name": "SystemUIComposeGalleryTests",
"options": [
{
"exclude-annotation": "org.junit.Ignore"
},
{
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
]
}

View File

@@ -1,39 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.android.systemui.compose.gallery.app">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.SystemUI.Gallery"
tools:replace="android:icon,android:theme,android:label">
<activity
android:name="com.android.systemui.compose.gallery.GalleryActivity"
android:exported="true"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,21 +0,0 @@
# 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

View File

@@ -1,30 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

View File

@@ -1,170 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<resources>
<color name="ic_launcher_background">#FFFFFF</color>
</resources>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<resources>
<!-- Application name [CHAR LIMIT=NONE] -->
<string name="app_name">SystemUI Gallery</string>
</resources>

View File

@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.SystemUI.Gallery">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:statusBarColor" tools:targetApi="l">
@android:color/transparent
</item>
<item name="android:navigationBarColor" tools:targetApi="l">
@android:color/transparent
</item>
<item name="android:windowLightStatusBar">true</item>
</style>
</resources>

View File

@@ -1,77 +0,0 @@
/*
* 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.
*
*/
@file:OptIn(ExperimentalMaterial3Api::class)
package com.android.systemui.compose.gallery
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.android.systemui.compose.SysUiButton
import com.android.systemui.compose.SysUiOutlinedButton
import com.android.systemui.compose.SysUiTextButton
@Composable
fun ButtonsScreen(
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier,
) {
SysUiButton(
onClick = {},
) {
Text("SysUiButton")
}
SysUiButton(
onClick = {},
enabled = false,
) {
Text("SysUiButton - disabled")
}
SysUiOutlinedButton(
onClick = {},
) {
Text("SysUiOutlinedButton")
}
SysUiOutlinedButton(
onClick = {},
enabled = false,
) {
Text("SysUiOutlinedButton - disabled")
}
SysUiTextButton(
onClick = {},
) {
Text("SysUiTextButton")
}
SysUiTextButton(
onClick = {},
enabled = false,
) {
Text("SysUiTextButton - disabled")
}
}
}

View File

@@ -1,139 +0,0 @@
/*
* 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.fillMaxWidth
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
import com.android.systemui.compose.theme.LocalAndroidColorScheme
/** The screen that shows all the Material 3 colors. */
@Composable
fun MaterialColorsScreen() {
val colors = MaterialTheme.colorScheme
ColorsScreen(
listOf(
"primary" to colors.primary,
"onPrimary" to colors.onPrimary,
"primaryContainer" to colors.primaryContainer,
"onPrimaryContainer" to colors.onPrimaryContainer,
"inversePrimary" to colors.inversePrimary,
"secondary" to colors.secondary,
"onSecondary" to colors.onSecondary,
"secondaryContainer" to colors.secondaryContainer,
"onSecondaryContainer" to colors.onSecondaryContainer,
"tertiary" to colors.tertiary,
"onTertiary" to colors.onTertiary,
"tertiaryContainer" to colors.tertiaryContainer,
"onTertiaryContainer" to colors.onTertiaryContainer,
"background" to colors.background,
"onBackground" to colors.onBackground,
"surface" to colors.surface,
"onSurface" to colors.onSurface,
"surfaceVariant" to colors.surfaceVariant,
"onSurfaceVariant" to colors.onSurfaceVariant,
"inverseSurface" to colors.inverseSurface,
"inverseOnSurface" to colors.inverseOnSurface,
"error" to colors.error,
"onError" to colors.onError,
"errorContainer" to colors.errorContainer,
"onErrorContainer" to colors.onErrorContainer,
"outline" to colors.outline,
)
)
}
/** The screen that shows all the Android colors. */
@Composable
fun AndroidColorsScreen() {
val colors = LocalAndroidColorScheme.current
ColorsScreen(
listOf(
"colorPrimary" to colors.colorPrimary,
"colorPrimaryDark" to colors.colorPrimaryDark,
"colorAccent" to colors.colorAccent,
"colorAccentPrimary" to colors.colorAccentPrimary,
"colorAccentSecondary" to colors.colorAccentSecondary,
"colorAccentTertiary" to colors.colorAccentTertiary,
"colorAccentPrimaryVariant" to colors.colorAccentPrimaryVariant,
"colorAccentSecondaryVariant" to colors.colorAccentSecondaryVariant,
"colorAccentTertiaryVariant" to colors.colorAccentTertiaryVariant,
"colorSurface" to colors.colorSurface,
"colorSurfaceHighlight" to colors.colorSurfaceHighlight,
"colorSurfaceVariant" to colors.colorSurfaceVariant,
"colorSurfaceHeader" to colors.colorSurfaceHeader,
"colorError" to colors.colorError,
"colorBackground" to colors.colorBackground,
"colorBackgroundFloating" to colors.colorBackgroundFloating,
"panelColorBackground" to colors.panelColorBackground,
"textColorPrimary" to colors.textColorPrimary,
"textColorSecondary" to colors.textColorSecondary,
"textColorTertiary" to colors.textColorTertiary,
"textColorPrimaryInverse" to colors.textColorPrimaryInverse,
"textColorSecondaryInverse" to colors.textColorSecondaryInverse,
"textColorTertiaryInverse" to colors.textColorTertiaryInverse,
"textColorOnAccent" to colors.textColorOnAccent,
"colorForeground" to colors.colorForeground,
"colorForegroundInverse" to colors.colorForegroundInverse,
)
)
}
@Composable
private fun ColorsScreen(
colors: List<Pair<String, Color>>,
) {
LazyColumn(
Modifier.fillMaxWidth(),
) {
colors.forEach { (name, color) -> item { ColorTile(color, name) } }
}
}
@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)
}
}

View File

@@ -1,210 +0,0 @@
package com.android.systemui.compose.gallery
import android.graphics.Point
import android.os.UserHandle
import android.view.Display
import android.view.WindowManagerGlobal
import androidx.compose.foundation.layout.RowScope
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.DarkMode
import androidx.compose.material.icons.filled.FormatSize
import androidx.compose.material.icons.filled.FormatTextdirectionLToR
import androidx.compose.material.icons.filled.FormatTextdirectionRToL
import androidx.compose.material.icons.filled.InvertColors
import androidx.compose.material.icons.filled.LightMode
import androidx.compose.material.icons.filled.Smartphone
import androidx.compose.material.icons.filled.Tablet
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import kotlin.math.max
import kotlin.math.min
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(
theme: Theme,
fontScale: FontScale,
layoutDirection: LayoutDirection,
onChangeTheme: () -> Unit,
onChangeLayoutDirection: () -> Unit,
onChangeFontScale: () -> Unit,
modifier: Modifier = Modifier,
) {
// The display we are emulating, if any.
var emulatedDisplayName by rememberSaveable { mutableStateOf<String?>(null) }
val emulatedDisplay =
emulatedDisplayName?.let { name -> EmulatedDisplays.firstOrNull { it.name == name } }
LaunchedEffect(emulatedDisplay) {
val wm = WindowManagerGlobal.getWindowManagerService()
val defaultDisplayId = Display.DEFAULT_DISPLAY
if (emulatedDisplay == null) {
wm.clearForcedDisplayDensityForUser(defaultDisplayId, UserHandle.myUserId())
wm.clearForcedDisplaySize(defaultDisplayId)
} else {
val density = emulatedDisplay.densityDpi
// Emulate the display and make sure that we use the maximum available space possible.
val initialSize = Point()
wm.getInitialDisplaySize(defaultDisplayId, initialSize)
val width = emulatedDisplay.width
val height = emulatedDisplay.height
val minOfSize = min(width, height)
val maxOfSize = max(width, height)
if (initialSize.x < initialSize.y) {
wm.setForcedDisplaySize(defaultDisplayId, minOfSize, maxOfSize)
} else {
wm.setForcedDisplaySize(defaultDisplayId, maxOfSize, minOfSize)
}
wm.setForcedDisplayDensityForUser(defaultDisplayId, density, UserHandle.myUserId())
}
}
// TODO(b/231131244): Fork FlowRow from Accompanist and use that instead to make sure that users
// don't miss any available configuration.
LazyRow(modifier) {
// Dark/light theme.
item {
TextButton(onChangeTheme) {
val text: String
val icon: ImageVector
when (theme) {
Theme.System -> {
icon = Icons.Default.InvertColors
text = "System"
}
Theme.Dark -> {
icon = Icons.Default.DarkMode
text = "Dark"
}
Theme.Light -> {
icon = Icons.Default.LightMode
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")
}
}
}
}
// Display emulation.
EmulatedDisplays.forEach { display ->
item {
DisplayButton(
display,
emulatedDisplay == display,
{ emulatedDisplayName = it?.name },
)
}
}
}
}
@Composable
private fun DisplayButton(
display: EmulatedDisplay,
selected: Boolean,
onChangeEmulatedDisplay: (EmulatedDisplay?) -> Unit,
) {
val onClick = {
if (selected) {
onChangeEmulatedDisplay(null)
} else {
onChangeEmulatedDisplay(display)
}
}
val content: @Composable RowScope.() -> Unit = {
Icon(display.icon, null)
Spacer(Modifier.width(8.dp))
Text(display.name)
}
if (selected) {
Button(onClick, contentPadding = ButtonDefaults.TextButtonContentPadding, content = content)
} else {
TextButton(onClick, content = content)
}
}
/** The displays that can be emulated from this Gallery app. */
private val EmulatedDisplays =
listOf(
EmulatedDisplay(
"Phone",
Icons.Default.Smartphone,
width = 1440,
height = 3120,
densityDpi = 560,
),
EmulatedDisplay(
"Tablet",
Icons.Default.Tablet,
width = 2560,
height = 1600,
densityDpi = 320,
),
)
private data class EmulatedDisplay(
val name: String,
val icon: ImageVector,
val width: Int,
val height: Int,
val densityDpi: Int,
)

View File

@@ -1,28 +0,0 @@
/*
* 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 androidx.compose.ui.Modifier
import com.android.systemui.ExampleFeature
/** The screen that shows ExampleFeature. */
@Composable
fun ExampleFeatureScreen(modifier: Modifier = Modifier) {
Column(modifier) { ExampleFeature("This is an example feature!") }
}

View File

@@ -1,80 +0,0 @@
/*
* 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.app.UiModeManager
import android.content.Context
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Color
import androidx.core.view.WindowCompat
import com.android.systemui.compose.rememberSystemUiController
class GalleryActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
val uiModeManager = getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
setContent {
var theme by rememberSaveable { mutableStateOf(Theme.System) }
val onChangeTheme = {
// Change to the next theme for a toggle behavior.
theme =
when (theme) {
Theme.System -> Theme.Dark
Theme.Dark -> Theme.Light
Theme.Light -> Theme.System
}
}
val isSystemInDarkTheme = isSystemInDarkTheme()
val isDark = theme == Theme.Dark || (theme == Theme.System && isSystemInDarkTheme)
val useDarkIcons = !isDark
val systemUiController = rememberSystemUiController()
SideEffect {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
darkIcons = useDarkIcons,
)
uiModeManager.setApplicationNightMode(
when (theme) {
Theme.System -> UiModeManager.MODE_NIGHT_AUTO
Theme.Dark -> UiModeManager.MODE_NIGHT_YES
Theme.Light -> UiModeManager.MODE_NIGHT_NO
}
)
}
GalleryApp(theme, onChangeTheme)
}
}
}
enum class Theme {
System,
Dark,
Light,
}

View File

@@ -1,202 +0,0 @@
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.saveable.rememberSaveable
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.rememberNavController
import com.android.systemui.compose.theme.SystemUITheme
/** The gallery app screens. */
object GalleryAppScreens {
private val Typography = ChildScreen("typography") { TypographyScreen() }
private val MaterialColors = ChildScreen("material_colors") { MaterialColorsScreen() }
private val AndroidColors = ChildScreen("android_colors") { AndroidColorsScreen() }
private val Buttons = ChildScreen("buttons") { ButtonsScreen() }
private val ExampleFeature = ChildScreen("example_feature") { ExampleFeatureScreen() }
private val PeopleEmpty =
ChildScreen("people_empty") { navController ->
EmptyPeopleScreen(onResult = { navController.popBackStack() })
}
private val PeopleFew =
ChildScreen("people_few") { navController ->
FewPeopleScreen(onResult = { navController.popBackStack() })
}
private val PeopleFull =
ChildScreen("people_full") { navController ->
FullPeopleScreen(onResult = { navController.popBackStack() })
}
private val People =
ParentScreen(
"people",
mapOf(
"Empty" to PeopleEmpty,
"Few" to PeopleFew,
"Full" to PeopleFull,
)
)
private val UserSwitcherSingleUser =
ChildScreen("user_switcher_single") { navController ->
UserSwitcherScreen(
userCount = 1,
onFinished = navController::popBackStack,
)
}
private val UserSwitcherThreeUsers =
ChildScreen("user_switcher_three") { navController ->
UserSwitcherScreen(
userCount = 3,
onFinished = navController::popBackStack,
)
}
private val UserSwitcherFourUsers =
ChildScreen("user_switcher_four") { navController ->
UserSwitcherScreen(
userCount = 4,
onFinished = navController::popBackStack,
)
}
private val UserSwitcherFiveUsers =
ChildScreen("user_switcher_five") { navController ->
UserSwitcherScreen(
userCount = 5,
onFinished = navController::popBackStack,
)
}
private val UserSwitcherSixUsers =
ChildScreen("user_switcher_six") { navController ->
UserSwitcherScreen(
userCount = 6,
onFinished = navController::popBackStack,
)
}
private val UserSwitcher =
ParentScreen(
"user_switcher",
mapOf(
"Single" to UserSwitcherSingleUser,
"Three" to UserSwitcherThreeUsers,
"Four" to UserSwitcherFourUsers,
"Five" to UserSwitcherFiveUsers,
"Six" to UserSwitcherSixUsers,
)
)
val Home =
ParentScreen(
"home",
mapOf(
"Typography" to Typography,
"Material colors" to MaterialColors,
"Android colors" to AndroidColors,
"Example feature" to ExampleFeature,
"Buttons" to Buttons,
"People" to People,
"User Switcher" to UserSwitcher,
)
)
}
/** The main content of the app, that shows [GalleryAppScreens.Home] by default. */
@Composable
private fun MainContent(onControlToggleRequested: () -> Unit) {
Box(Modifier.fillMaxSize()) {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = GalleryAppScreens.Home.identifier,
) {
screen(GalleryAppScreens.Home, navController, onControlToggleRequested)
}
}
}
/**
* 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(
theme: Theme,
onChangeTheme: () -> Unit,
) {
val systemFontScale = LocalDensity.current.fontScale
var fontScale: FontScale by rememberSaveable {
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 rememberSaveable { mutableStateOf(systemLayoutDirection) }
val onChangeLayoutDirection = {
layoutDirection =
when (layoutDirection) {
LayoutDirection.Ltr -> LayoutDirection.Rtl
LayoutDirection.Rtl -> LayoutDirection.Ltr
}
}
CompositionLocalProvider(
LocalDensity provides density,
LocalLayoutDirection provides layoutDirection,
) {
SystemUITheme {
Surface(
Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background,
) {
Column(Modifier.fillMaxSize().systemBarsPadding()) {
var showControls by rememberSaveable { mutableStateOf(true) }
if (showControls) {
ConfigurationControls(
theme,
fontScale,
layoutDirection,
onChangeTheme,
onChangeLayoutDirection,
onChangeFontScale,
Modifier.padding(horizontal = 16.dp),
)
Spacer(Modifier.height(4.dp))
}
MainContent(onControlToggleRequested = { showControls = !showControls })
}
}
}
}
}

View File

@@ -1,46 +0,0 @@
/*
* 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.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import com.android.systemui.people.emptyPeopleSpaceViewModel
import com.android.systemui.people.fewPeopleSpaceViewModel
import com.android.systemui.people.fullPeopleSpaceViewModel
import com.android.systemui.people.ui.compose.PeopleScreen
import com.android.systemui.people.ui.viewmodel.PeopleViewModel
@Composable
fun EmptyPeopleScreen(onResult: (PeopleViewModel.Result) -> Unit) {
val context = LocalContext.current.applicationContext
val viewModel = emptyPeopleSpaceViewModel(context)
PeopleScreen(viewModel, onResult)
}
@Composable
fun FewPeopleScreen(onResult: (PeopleViewModel.Result) -> Unit) {
val context = LocalContext.current.applicationContext
val viewModel = fewPeopleSpaceViewModel(context)
PeopleScreen(viewModel, onResult)
}
@Composable
fun FullPeopleScreen(onResult: (PeopleViewModel.Result) -> Unit) {
val context = LocalContext.current.applicationContext
val viewModel = fullPeopleSpaceViewModel(context)
PeopleScreen(viewModel, onResult)
}

View File

@@ -1,126 +0,0 @@
/*
* 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
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation
/**
* A screen in an app. It is either an [ParentScreen] which lists its child screens to navigate to
* them or a [ChildScreen] which shows some content.
*/
sealed class Screen(val identifier: String)
class ParentScreen(
identifier: String,
val children: Map<String, Screen>,
) : Screen(identifier)
class ChildScreen(
identifier: String,
val content: @Composable (NavController) -> Unit,
) : Screen(identifier)
/** Create the navigation graph for [screen]. */
fun NavGraphBuilder.screen(
screen: Screen,
navController: NavController,
onControlToggleRequested: () -> Unit,
) {
when (screen) {
is ChildScreen -> composable(screen.identifier) { screen.content(navController) }
is ParentScreen -> {
val menuRoute = "${screen.identifier}_menu"
navigation(startDestination = menuRoute, route = screen.identifier) {
// The menu to navigate to one of the children screens.
composable(menuRoute) {
ScreenMenu(screen, navController, onControlToggleRequested)
}
// The content of the child screens.
screen.children.forEach { (_, child) ->
screen(
child,
navController,
onControlToggleRequested,
)
}
}
}
}
}
@Composable
private fun ScreenMenu(
screen: ParentScreen,
navController: NavController,
onControlToggleRequested: () -> Unit,
) {
LazyColumn(
Modifier.padding(horizontal = 16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
item {
Surface(
Modifier.fillMaxWidth(),
color = MaterialTheme.colorScheme.tertiaryContainer,
shape = CircleShape,
) {
Column(
Modifier.clickable(onClick = onControlToggleRequested).padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text("Toggle controls")
}
}
}
screen.children.forEach { (name, child) ->
item {
Surface(
Modifier.fillMaxWidth(),
color = MaterialTheme.colorScheme.secondaryContainer,
shape = CircleShape,
) {
Column(
Modifier.clickable { navController.navigate(child.identifier) }
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(name)
}
}
}
}
}
}

View File

@@ -1,67 +0,0 @@
/*
* 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,
)
}

View File

@@ -1,35 +0,0 @@
/*
* 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.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import com.android.systemui.user.Fakes.fakeUserSwitcherViewModel
import com.android.systemui.user.ui.compose.UserSwitcherScreen
@Composable
fun UserSwitcherScreen(
userCount: Int,
onFinished: () -> Unit,
) {
val context = LocalContext.current.applicationContext
UserSwitcherScreen(
viewModel = fakeUserSwitcherViewModel(context, userCount = userCount),
onFinished = onFinished,
)
}

View File

@@ -1,156 +0,0 @@
/*
* 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.people
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.Icon
import androidx.core.graphics.drawable.toIcon
import com.android.systemui.R
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.people.data.model.PeopleTileModel
import com.android.systemui.people.ui.viewmodel.PeopleViewModel
import com.android.systemui.people.widget.PeopleTileKey
/** A [PeopleViewModel] that does not have any conversations. */
fun emptyPeopleSpaceViewModel(@Application context: Context): PeopleViewModel {
return fakePeopleSpaceViewModel(context, emptyList(), emptyList())
}
/** A [PeopleViewModel] that has a few conversations. */
fun fewPeopleSpaceViewModel(@Application context: Context): PeopleViewModel {
return fakePeopleSpaceViewModel(
context,
priorityTiles =
listOf(
fakeTile(context, id = "0", Color.RED, "Priority"),
fakeTile(context, id = "1", Color.BLUE, "Priority NewStory", hasNewStory = true),
),
recentTiles =
listOf(
fakeTile(context, id = "2", Color.GREEN, "Recent Important", isImportant = true),
fakeTile(context, id = "3", Color.CYAN, "Recent DndBlocking", isDndBlocking = true),
),
)
}
/** A [PeopleViewModel] that has a lot of conversations. */
fun fullPeopleSpaceViewModel(@Application context: Context): PeopleViewModel {
return fakePeopleSpaceViewModel(
context,
priorityTiles =
listOf(
fakeTile(context, id = "0", Color.RED, "Priority"),
fakeTile(context, id = "1", Color.BLUE, "Priority NewStory", hasNewStory = true),
fakeTile(context, id = "2", Color.GREEN, "Priority Important", isImportant = true),
fakeTile(
context,
id = "3",
Color.CYAN,
"Priority DndBlocking",
isDndBlocking = true,
),
fakeTile(
context,
id = "4",
Color.MAGENTA,
"Priority NewStory Important",
hasNewStory = true,
isImportant = true,
),
),
recentTiles =
listOf(
fakeTile(
context,
id = "5",
Color.RED,
"Recent NewStory DndBlocking",
hasNewStory = true,
isDndBlocking = true,
),
fakeTile(
context,
id = "6",
Color.BLUE,
"Recent Important DndBlocking",
isImportant = true,
isDndBlocking = true,
),
fakeTile(
context,
id = "7",
Color.GREEN,
"Recent NewStory Important DndBlocking",
hasNewStory = true,
isImportant = true,
isDndBlocking = true,
),
fakeTile(context, id = "8", Color.CYAN, "Recent"),
fakeTile(context, id = "9", Color.MAGENTA, "Recent"),
),
)
}
private fun fakePeopleSpaceViewModel(
@Application context: Context,
priorityTiles: List<PeopleTileModel>,
recentTiles: List<PeopleTileModel>,
): PeopleViewModel {
return PeopleViewModel(
context,
FakePeopleTileRepository(priorityTiles, recentTiles),
FakePeopleWidgetRepository(),
)
}
private fun fakeTile(
@Application context: Context,
id: String,
iconColor: Int,
username: String,
hasNewStory: Boolean = false,
isImportant: Boolean = false,
isDndBlocking: Boolean = false
): PeopleTileModel {
return PeopleTileModel(
PeopleTileKey(id, /* userId= */ 0, /* packageName */ ""),
username,
fakeUserIcon(context, iconColor),
hasNewStory,
isImportant,
isDndBlocking,
)
}
private fun fakeUserIcon(@Application context: Context, color: Int): Icon {
val size = context.resources.getDimensionPixelSize(R.dimen.avatar_size_for_medium)
val bitmap =
Bitmap.createBitmap(
size,
size,
Bitmap.Config.ARGB_8888,
)
val canvas = Canvas(bitmap)
val paint = Paint().apply { this.color = color }
val radius = size / 2f
canvas.drawCircle(/* cx= */ radius, /* cy= */ radius, /* radius= */ radius, paint)
return bitmap.toIcon()
}

View File

@@ -1,164 +0,0 @@
/*
* 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.qs.footer
import android.content.Context
import android.os.UserHandle
import android.view.View
import com.android.internal.util.UserIcons
import com.android.systemui.R
import com.android.systemui.animation.Expandable
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.globalactions.GlobalActionsDialogLite
import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.util.mockito.mock
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
/** A list of fake [FooterActionsViewModel] to be used in screenshot tests and the gallery. */
fun fakeFooterActionsViewModels(
@Application context: Context,
): List<FooterActionsViewModel> {
return listOf(
fakeFooterActionsViewModel(context),
fakeFooterActionsViewModel(context, showPowerButton = false, isGuestUser = true),
fakeFooterActionsViewModel(context, showUserSwitcher = false),
fakeFooterActionsViewModel(context, showUserSwitcher = false, foregroundServices = 4),
fakeFooterActionsViewModel(
context,
foregroundServices = 4,
hasNewForegroundServices = true,
userId = 1,
),
fakeFooterActionsViewModel(
context,
securityText = "Security",
foregroundServices = 4,
showUserSwitcher = false,
),
fakeFooterActionsViewModel(
context,
securityText = "Security (not clickable)",
securityClickable = false,
foregroundServices = 4,
hasNewForegroundServices = true,
userId = 2,
),
)
}
private fun fakeFooterActionsViewModel(
@Application context: Context,
securityText: String? = null,
securityClickable: Boolean = true,
foregroundServices: Int = 0,
hasNewForegroundServices: Boolean = false,
showUserSwitcher: Boolean = true,
showPowerButton: Boolean = true,
userId: Int = UserHandle.USER_OWNER,
isGuestUser: Boolean = false,
): FooterActionsViewModel {
val interactor =
FakeFooterActionsInteractor(
securityButtonConfig =
flowOf(
securityText?.let { text ->
SecurityButtonConfig(
icon =
Icon.Resource(
R.drawable.ic_info_outline,
contentDescription = null,
),
text = text,
isClickable = securityClickable,
)
}
),
foregroundServicesCount = flowOf(foregroundServices),
hasNewForegroundServices = flowOf(hasNewForegroundServices),
userSwitcherStatus =
flowOf(
if (showUserSwitcher) {
UserSwitcherStatusModel.Enabled(
currentUserName = "foo",
currentUserImage =
UserIcons.getDefaultUserIcon(
context.resources,
userId,
/* light= */ false,
),
isGuestUser = isGuestUser,
)
} else {
UserSwitcherStatusModel.Disabled
}
),
deviceMonitoringDialogRequests = flowOf(),
)
return FooterActionsViewModel(
context,
interactor,
FalsingManagerFake(),
globalActionsDialogLite = mock(),
showPowerButton = showPowerButton,
)
}
private class FakeFooterActionsInteractor(
override val securityButtonConfig: Flow<SecurityButtonConfig?> = flowOf(null),
override val foregroundServicesCount: Flow<Int> = flowOf(0),
override val hasNewForegroundServices: Flow<Boolean> = flowOf(false),
override val userSwitcherStatus: Flow<UserSwitcherStatusModel> =
flowOf(UserSwitcherStatusModel.Disabled),
override val deviceMonitoringDialogRequests: Flow<Unit> = flowOf(),
private val onShowDeviceMonitoringDialogFromView: (View) -> Unit = {},
private val onShowDeviceMonitoringDialog: (Context) -> Unit = {},
private val onShowForegroundServicesDialog: (View) -> Unit = {},
private val onShowPowerMenuDialog: (GlobalActionsDialogLite, View) -> Unit = { _, _ -> },
private val onShowSettings: (Expandable) -> Unit = {},
private val onShowUserSwitcher: (View) -> Unit = {},
) : FooterActionsInteractor {
override fun showDeviceMonitoringDialog(view: View) {
onShowDeviceMonitoringDialogFromView(view)
}
override fun showDeviceMonitoringDialog(quickSettingsContext: Context) {
onShowDeviceMonitoringDialog(quickSettingsContext)
}
override fun showForegroundServicesDialog(view: View) {
onShowForegroundServicesDialog(view)
}
override fun showPowerMenuDialog(globalActionsDialogLite: GlobalActionsDialogLite, view: View) {
onShowPowerMenuDialog(globalActionsDialogLite, view)
}
override fun showSettings(expandable: Expandable) {
onShowSettings(expandable)
}
override fun showUserSwitcher(view: View) {
onShowUserSwitcher(view)
}
}

View File

@@ -1,116 +0,0 @@
/*
* 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.user
import android.content.Context
import androidx.appcompat.content.res.AppCompatResources
import com.android.systemui.common.shared.model.Text
import com.android.systemui.compose.gallery.R
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.power.data.repository.FakePowerRepository
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.user.domain.interactor.UserInteractor
import com.android.systemui.user.shared.model.UserActionModel
import com.android.systemui.user.shared.model.UserModel
import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel
import com.android.systemui.util.mockito.mock
object Fakes {
private val USER_TINT_COLORS =
arrayOf(
0x000000,
0x0000ff,
0x00ff00,
0x00ffff,
0xff0000,
0xff00ff,
0xffff00,
0xffffff,
)
fun fakeUserSwitcherViewModel(
context: Context,
userCount: Int,
): UserSwitcherViewModel {
return UserSwitcherViewModel.Factory(
userInteractor =
UserInteractor(
repository =
FakeUserRepository().apply {
setUsers(
(0 until userCount).map { index ->
UserModel(
id = index,
name =
Text.Loaded(
when (index % 6) {
0 -> "Ross Geller"
1 -> "Phoebe Buffay"
2 -> "Monica Geller"
3 -> "Rachel Greene"
4 -> "Chandler Bing"
else -> "Joey Tribbiani"
}
),
image =
checkNotNull(
AppCompatResources.getDrawable(
context,
when (index % 6) {
0 -> R.drawable.kitten1
1 -> R.drawable.kitten2
2 -> R.drawable.kitten3
3 -> R.drawable.kitten4
4 -> R.drawable.kitten5
else -> R.drawable.kitten6
},
)
),
isSelected = index == 0,
isSelectable = true,
)
}
)
setActions(
UserActionModel.values().mapNotNull {
if (it == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) {
null
} else {
it
}
}
)
},
controller = mock(),
activityStarter = mock(),
keyguardInteractor =
KeyguardInteractor(
repository =
FakeKeyguardRepository().apply { setKeyguardShowing(false) },
),
),
powerInteractor =
PowerInteractor(
repository = FakePowerRepository(),
)
)
.create(UserSwitcherViewModel::class.java)
}
}

View File

@@ -1,47 +0,0 @@
// 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"],
}

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.systemui.compose.gallery.tests" >
<application>
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.systemui.compose.gallery.tests"
android:label="Tests for SystemUIComposeGallery"/>
</manifest>

View File

@@ -1,36 +0,0 @@
/*
* 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() } }
}
}