summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt2
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlterDialogPage.kt62
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt2
-rw-r--r--packages/SettingsLib/Spa/spa/build.gradle7
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt118
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MoreOptions.kt5
-rw-r--r--packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialogTest.kt125
7 files changed, 316 insertions, 5 deletions
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
index 941e7705441b..6d20c917e214 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
@@ -23,6 +23,7 @@ import com.android.settingslib.spa.framework.common.SettingsPageProviderReposito
import com.android.settingslib.spa.framework.common.SpaEnvironment
import com.android.settingslib.spa.framework.common.createSettingsPage
import com.android.settingslib.spa.gallery.button.ActionButtonPageProvider
+import com.android.settingslib.spa.gallery.dialog.AlterDialogPageProvider
import com.android.settingslib.spa.gallery.home.HomePageProvider
import com.android.settingslib.spa.gallery.page.ArgumentPageProvider
import com.android.settingslib.spa.gallery.page.ChartPageProvider
@@ -72,6 +73,7 @@ class GallerySpaEnvironment(context: Context) : SpaEnvironment(context) {
ActionButtonPageProvider,
ProgressBarPageProvider,
ChartPageProvider,
+ AlterDialogPageProvider,
),
rootPages = listOf(
HomePageProvider.createSettingsPage(),
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlterDialogPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlterDialogPage.kt
new file mode 100644
index 000000000000..a57df0f46f6a
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/dialog/AlterDialogPage.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.settingslib.spa.gallery.dialog
+
+import android.os.Bundle
+import androidx.compose.material3.Text
+import com.android.settingslib.spa.framework.common.SettingsEntry
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.widget.dialog.AlertDialogButton
+import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+
+private const val TITLE = "AlterDialogPage"
+
+object AlterDialogPageProvider : SettingsPageProvider {
+ override val name = "AlterDialogPage"
+ private val owner = createSettingsPage()
+
+ override fun buildEntry(arguments: Bundle?): List<SettingsEntry> = listOf(
+ SettingsEntryBuilder.create("AlterDialog", owner).setUiLayoutFn {
+ val alertDialogPresenter = rememberAlertDialogPresenter(
+ confirmButton = AlertDialogButton("Ok"),
+ dismissButton = AlertDialogButton("Cancel"),
+ title = "Title",
+ text = { Text("Text") },
+ )
+ Preference(object : PreferenceModel {
+ override val title = "Show AlterDialog"
+ override val onClick = alertDialogPresenter::open
+ })
+ }.build(),
+ )
+
+ fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner)
+ .setIsAllowSearch(true)
+ .setUiLayoutFn {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+
+ override fun getTitle(arguments: Bundle?) = TITLE
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
index 83c72c75e9f3..6d53dae5ae41 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
@@ -27,6 +27,7 @@ import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.gallery.R
import com.android.settingslib.spa.gallery.SettingsPageProviderEnum
import com.android.settingslib.spa.gallery.button.ActionButtonPageProvider
+import com.android.settingslib.spa.gallery.dialog.AlterDialogPageProvider
import com.android.settingslib.spa.gallery.page.ArgumentPageModel
import com.android.settingslib.spa.gallery.page.ArgumentPageProvider
import com.android.settingslib.spa.gallery.page.ChartPageProvider
@@ -58,6 +59,7 @@ object HomePageProvider : SettingsPageProvider {
ActionButtonPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
ProgressBarPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
ChartPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+ AlterDialogPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
)
}
diff --git a/packages/SettingsLib/Spa/spa/build.gradle b/packages/SettingsLib/Spa/spa/build.gradle
index 854359641bc0..b1d8d0dadfbd 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle
+++ b/packages/SettingsLib/Spa/spa/build.gradle
@@ -55,6 +55,8 @@ android {
}
dependencies {
+ String jetpack_lifecycle_version = "2.6.0-alpha03"
+
api "androidx.appcompat:appcompat:1.7.0-alpha01"
api "androidx.slice:slice-builders:1.1.0-alpha02"
api "androidx.slice:slice-core:1.1.0-alpha02"
@@ -63,8 +65,9 @@ dependencies {
api "androidx.compose.material:material-icons-extended:$jetpack_compose_version"
api "androidx.compose.runtime:runtime-livedata:$jetpack_compose_version"
api "androidx.compose.ui:ui-tooling-preview:$jetpack_compose_version"
- api "androidx.lifecycle:lifecycle-livedata-ktx:2.6.0-alpha03"
- api "androidx.navigation:navigation-compose:2.6.0-alpha03"
+ api "androidx.lifecycle:lifecycle-livedata-ktx:$jetpack_lifecycle_version"
+ api "androidx.lifecycle:lifecycle-runtime-compose:$jetpack_lifecycle_version"
+ api "androidx.navigation:navigation-compose:2.6.0-alpha04"
api "com.github.PhilJay:MPAndroidChart:v3.1.0-alpha"
api "com.google.android.material:material:1.7.0-alpha03"
debugApi "androidx.compose.ui:ui-tooling:$jetpack_compose_version"
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt
new file mode 100644
index 000000000000..d6f5328068ad
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialog.kt
@@ -0,0 +1,118 @@
+/*
+ * 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.settingslib.spa.widget.dialog
+
+import android.content.res.Configuration
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.DialogProperties
+
+data class AlertDialogButton(
+ val text: String,
+ val onClick: () -> Unit = {},
+)
+
+interface AlertDialogPresenter {
+ /** Opens the dialog. */
+ fun open()
+
+ /** Closes the dialog. */
+ fun close()
+}
+
+@Composable
+fun rememberAlertDialogPresenter(
+ confirmButton: AlertDialogButton? = null,
+ dismissButton: AlertDialogButton? = null,
+ title: String? = null,
+ text: @Composable (() -> Unit)? = null,
+): AlertDialogPresenter {
+ var openDialog by rememberSaveable { mutableStateOf(false) }
+ val alertDialogPresenter = remember {
+ object : AlertDialogPresenter {
+ override fun open() {
+ openDialog = true
+ }
+
+ override fun close() {
+ openDialog = false
+ }
+ }
+ }
+ if (openDialog) {
+ alertDialogPresenter.SettingsAlertDialog(confirmButton, dismissButton, title, text)
+ }
+ return alertDialogPresenter
+}
+
+@OptIn(ExperimentalComposeUiApi::class)
+@Composable
+private fun AlertDialogPresenter.SettingsAlertDialog(
+ confirmButton: AlertDialogButton?,
+ dismissButton: AlertDialogButton?,
+ title: String?,
+ text: @Composable (() -> Unit)?,
+) {
+ val configuration = LocalConfiguration.current
+ AlertDialog(
+ onDismissRequest = ::close,
+ modifier = when (configuration.orientation) {
+ Configuration.ORIENTATION_LANDSCAPE -> {
+ Modifier.width(configuration.screenWidthDp.dp * 0.6f)
+ }
+ else -> Modifier
+ },
+ confirmButton = { confirmButton?.let { Button(it) } },
+ dismissButton = dismissButton?.let { { Button(it) } },
+ title = title?.let { { Text(it) } },
+ text = text?.let {
+ {
+ Column(Modifier.verticalScroll(rememberScrollState())) {
+ text()
+ }
+ }
+ },
+ properties = DialogProperties(usePlatformDefaultWidth = false),
+ )
+}
+
+@Composable
+private fun AlertDialogPresenter.Button(button: AlertDialogButton) {
+ TextButton(
+ onClick = {
+ close()
+ button.onClick()
+ },
+ ) {
+ Text(button.text)
+ }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MoreOptions.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MoreOptions.kt
index 5e201dfccbd5..84fea158175f 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MoreOptions.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/MoreOptions.kt
@@ -17,7 +17,6 @@
package com.android.settingslib.spa.widget.scaffold
import androidx.appcompat.R
-import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material3.DropdownMenu
@@ -36,7 +35,7 @@ import androidx.compose.ui.res.stringResource
/**
* Scope for the children of [MoreOptionsAction].
*/
-interface MoreOptionsScope : ColumnScope {
+interface MoreOptionsScope {
fun dismiss()
@Composable
@@ -61,7 +60,7 @@ fun MoreOptionsAction(
val onDismiss = { expanded = false }
DropdownMenu(expanded = expanded, onDismissRequest = onDismiss) {
val moreOptionsScope = remember(this) {
- object : MoreOptionsScope, ColumnScope by this {
+ object : MoreOptionsScope {
override fun dismiss() {
onDismiss()
}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialogTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialogTest.kt
new file mode 100644
index 000000000000..9468f95a094e
--- /dev/null
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/dialog/SettingsAlertDialogTest.kt
@@ -0,0 +1,125 @@
+/*
+ * 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.settingslib.spa.widget.dialog
+
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.performClick
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.testutils.onDialogText
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SettingsAlertDialogTest {
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ @Test
+ fun title_whenDialogNotOpen_notDisplayed() {
+ composeTestRule.setContent {
+ rememberAlertDialogPresenter(title = TITLE)
+ }
+
+ composeTestRule.onDialogText(TITLE).assertDoesNotExist()
+ }
+
+ @Test
+ fun title_displayed() {
+ setAndOpenDialog {
+ rememberAlertDialogPresenter(title = TITLE)
+ }
+
+ composeTestRule.onDialogText(TITLE).assertIsDisplayed()
+ }
+
+ @Test
+ fun text_displayed() {
+ setAndOpenDialog {
+ rememberAlertDialogPresenter(text = { Text(TEXT) })
+ }
+
+ composeTestRule.onDialogText(TEXT).assertIsDisplayed()
+ }
+
+ @Test
+ fun confirmButton_displayed() {
+ setAndOpenDialog {
+ rememberAlertDialogPresenter(confirmButton = AlertDialogButton(CONFIRM_TEXT))
+ }
+
+ composeTestRule.onDialogText(CONFIRM_TEXT).assertIsDisplayed()
+ }
+
+ @Test
+ fun confirmButton_clickable() {
+ var confirmButtonClicked = false
+ setAndOpenDialog {
+ rememberAlertDialogPresenter(confirmButton = AlertDialogButton(CONFIRM_TEXT) {
+ confirmButtonClicked = true
+ })
+ }
+
+ composeTestRule.onDialogText(CONFIRM_TEXT).performClick()
+
+ assertThat(confirmButtonClicked).isTrue()
+ }
+
+ @Test
+ fun dismissButton_displayed() {
+ setAndOpenDialog {
+ rememberAlertDialogPresenter(dismissButton = AlertDialogButton(DISMISS_TEXT))
+ }
+
+ composeTestRule.onDialogText(DISMISS_TEXT).assertIsDisplayed()
+ }
+
+ @Test
+ fun dismissButton_clickable() {
+ var dismissButtonClicked = false
+ setAndOpenDialog {
+ rememberAlertDialogPresenter(dismissButton = AlertDialogButton(DISMISS_TEXT) {
+ dismissButtonClicked = true
+ })
+ }
+
+ composeTestRule.onDialogText(DISMISS_TEXT).performClick()
+
+ assertThat(dismissButtonClicked).isTrue()
+ }
+
+ private fun setAndOpenDialog(dialog: @Composable () -> AlertDialogPresenter) {
+ composeTestRule.setContent {
+ val dialogPresenter = dialog()
+ LaunchedEffect(Unit) {
+ dialogPresenter.open()
+ }
+ }
+ }
+
+ private companion object {
+ const val CONFIRM_TEXT = "Confirm"
+ const val DISMISS_TEXT = "Dismiss"
+ const val TITLE = "Title"
+ const val TEXT = "Text"
+ }
+}