Move the Compose Gallery to our vendor repository (2/2)
Bug: 247473910 Test: Builds Change-Id: I665f351cda86dc6588946b8449fbb1c13fcba503
@@ -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"],
|
||||
}
|
||||
@@ -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>
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"presubmit": [
|
||||
{
|
||||
"name": "SystemUIComposeGalleryTests",
|
||||
"options": [
|
||||
{
|
||||
"exclude-annotation": "org.junit.Ignore"
|
||||
},
|
||||
{
|
||||
"exclude-annotation": "androidx.test.filters.FlakyTest"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 982 B |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
@@ -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!") }
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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"],
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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() } }
|
||||
}
|
||||
}
|
||||