1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.settingslib.spa.widget.dialog
18
19 import android.content.res.Configuration
20 import androidx.compose.foundation.layout.Column
21 import androidx.compose.foundation.layout.width
22 import androidx.compose.foundation.rememberScrollState
23 import androidx.compose.foundation.verticalScroll
24 import androidx.compose.material3.AlertDialog
25 import androidx.compose.material3.Text
26 import androidx.compose.material3.TextButton
27 import androidx.compose.runtime.Composable
28 import androidx.compose.runtime.getValue
29 import androidx.compose.runtime.mutableStateOf
30 import androidx.compose.runtime.remember
31 import androidx.compose.runtime.saveable.rememberSaveable
32 import androidx.compose.runtime.setValue
33 import androidx.compose.ui.Modifier
34 import androidx.compose.ui.platform.LocalConfiguration
35 import androidx.compose.ui.unit.Dp
36 import androidx.compose.ui.unit.dp
37 import androidx.compose.ui.window.DialogProperties
38
39 data class AlertDialogButton(
40 val text: String,
41 val enabled: Boolean = true,
<lambda>null42 val onClick: () -> Unit = {},
43 )
44
45 interface AlertDialogPresenter {
46 /** Opens the dialog. */
opennull47 fun open()
48
49 /** Closes the dialog. */
50 fun close()
51 }
52
53 @Composable
54 fun rememberAlertDialogPresenter(
55 confirmButton: AlertDialogButton? = null,
56 dismissButton: AlertDialogButton? = null,
57 title: String? = null,
58 text: @Composable (() -> Unit)? = null,
59 ): AlertDialogPresenter {
60 var openDialog by rememberSaveable { mutableStateOf(false) }
61 val alertDialogPresenter = remember {
62 object : AlertDialogPresenter {
63 override fun open() {
64 openDialog = true
65 }
66
67 override fun close() {
68 openDialog = false
69 }
70 }
71 }
72 if (openDialog) {
73 alertDialogPresenter.SettingsAlertDialog(confirmButton, dismissButton, title, text)
74 }
75 return alertDialogPresenter
76 }
77
78 @Composable
SettingsAlertDialognull79 private fun AlertDialogPresenter.SettingsAlertDialog(
80 confirmButton: AlertDialogButton?,
81 dismissButton: AlertDialogButton?,
82 title: String?,
83 text: @Composable (() -> Unit)?,
84 ) {
85 AlertDialog(
86 onDismissRequest = ::close,
87 modifier = Modifier.width(getDialogWidth()),
88 confirmButton = { confirmButton?.let { Button(it) } },
89 dismissButton = dismissButton?.let { { Button(it) } },
90 title = title?.let { { Text(it) } },
91 text = text?.let {
92 {
93 Column(Modifier.verticalScroll(rememberScrollState())) {
94 text()
95 }
96 }
97 },
98 properties = DialogProperties(usePlatformDefaultWidth = false),
99 )
100 }
101
102 @Composable
getDialogWidthnull103 fun getDialogWidth(): Dp {
104 val configuration = LocalConfiguration.current
105 return configuration.screenWidthDp.dp * when (configuration.orientation) {
106 Configuration.ORIENTATION_LANDSCAPE -> 0.65f
107 else -> 0.85f
108 }
109 }
110
111 @Composable
Buttonnull112 private fun AlertDialogPresenter.Button(button: AlertDialogButton) {
113 TextButton(
114 onClick = {
115 close()
116 button.onClick()
117 },
118 enabled = button.enabled,
119 ) {
120 Text(button.text)
121 }
122 }
123