16
16
17
17
package com.google.android.horologist.datalayer.phone.ui.prompt.installapp
18
18
19
+ import android.content.res.Configuration
20
+ import androidx.compose.foundation.layout.Arrangement
19
21
import androidx.compose.foundation.layout.Box
20
22
import androidx.compose.foundation.layout.Column
23
+ import androidx.compose.foundation.layout.Row
24
+ import androidx.compose.foundation.layout.Spacer
21
25
import androidx.compose.foundation.layout.fillMaxWidth
22
- import androidx.compose.foundation.layout.heightIn
26
+ import androidx.compose.foundation.layout.height
23
27
import androidx.compose.foundation.layout.padding
28
+ import androidx.compose.foundation.rememberScrollState
29
+ import androidx.compose.foundation.verticalScroll
24
30
import androidx.compose.material.icons.Icons
25
31
import androidx.compose.material.icons.filled.Email
26
32
import androidx.compose.material3.Button
27
33
import androidx.compose.material3.ExperimentalMaterial3Api
28
34
import androidx.compose.material3.Icon
29
35
import androidx.compose.material3.MaterialTheme
30
36
import androidx.compose.material3.ModalBottomSheet
31
- import androidx.compose.material3.OutlinedButton
32
37
import androidx.compose.material3.SheetState
33
38
import androidx.compose.material3.Text
39
+ import androidx.compose.material3.TextButton
34
40
import androidx.compose.material3.rememberModalBottomSheetState
35
41
import androidx.compose.runtime.Composable
36
42
import androidx.compose.ui.Alignment
37
43
import androidx.compose.ui.Modifier
44
+ import androidx.compose.ui.platform.LocalConfiguration
38
45
import androidx.compose.ui.res.stringResource
39
46
import androidx.compose.ui.text.style.TextAlign
40
47
import androidx.compose.ui.tooling.preview.Preview
41
48
import androidx.compose.ui.unit.dp
42
49
import com.google.android.horologist.datalayer.phone.ui.R
43
50
51
+ // Constants from the redlines.
52
+ private val PADDING_GREEN = 12 .dp
53
+ private val PADDING_PINK = 16 .dp
54
+ private val PADDING_PURPLE = 24 .dp
55
+ private val PADDING_BLUE = 32 .dp
56
+
44
57
@OptIn(ExperimentalMaterial3Api ::class )
45
58
@Composable
46
59
public fun InstallAppBottomSheet (
47
- message : String ,
48
- appName : String ,
49
- watchName : String ,
50
- icon : @Composable (() -> Unit )? ,
60
+ image : @Composable (() -> Unit )? ,
61
+ topMessage : String ,
62
+ bottomMessage : String ,
51
63
onDismissRequest : () -> Unit ,
52
64
onConfirmation : () -> Unit ,
65
+ modifier : Modifier = Modifier ,
53
66
sheetState : SheetState = rememberModalBottomSheetState(),
54
67
) {
55
68
ModalBottomSheet (
56
69
onDismissRequest = onDismissRequest,
70
+ modifier = modifier,
57
71
sheetState = sheetState,
72
+ dragHandle = null ,
58
73
) {
59
- InstallAppBottomSheetContent (
60
- message = message,
61
- appName = appName,
62
- watchName = watchName,
63
- icon = icon,
64
- onDismissRequest = onDismissRequest,
65
- onConfirmation = onConfirmation,
66
- )
74
+ val configuration = LocalConfiguration .current
75
+ when (configuration.orientation) {
76
+ Configuration .ORIENTATION_PORTRAIT -> {
77
+ InstallAppBottomSheetPortraitContent (
78
+ image = image,
79
+ topMessage = topMessage,
80
+ bottomMessage = bottomMessage,
81
+ onDismissRequest = onDismissRequest,
82
+ onConfirmation = onConfirmation,
83
+ )
84
+ }
85
+
86
+ else -> {
87
+ InstallAppBottomSheetLandscapeContent (
88
+ image = image,
89
+ topMessage = topMessage,
90
+ bottomMessage = bottomMessage,
91
+ onDismissRequest = onDismissRequest,
92
+ onConfirmation = onConfirmation,
93
+ )
94
+ }
95
+ }
67
96
}
68
97
}
69
98
70
99
@Composable
71
- internal fun InstallAppBottomSheetContent (
72
- message : String ,
73
- appName : String ,
74
- watchName : String ,
75
- icon : @Composable (() -> Unit )? ,
100
+ internal fun InstallAppBottomSheetPortraitContent (
101
+ image : @Composable (() -> Unit )? ,
102
+ topMessage : String ,
103
+ bottomMessage : String ,
76
104
onDismissRequest : () -> Unit ,
77
105
onConfirmation : () -> Unit ,
106
+ modifier : Modifier = Modifier ,
78
107
) {
79
- Column (modifier = Modifier .padding(horizontal = 20 .dp)) {
80
- icon?.let {
108
+ Column (
109
+ modifier = modifier
110
+ .padding(PADDING_PINK )
111
+ .fillMaxWidth()
112
+ .verticalScroll(rememberScrollState()),
113
+ ) {
114
+ image?.let {
81
115
Box (
82
116
modifier = Modifier
83
- .heightIn(min = 0 .dp, max = 180 .dp)
84
- .padding(vertical = 20 .dp)
117
+ .padding(top = PADDING_PURPLE )
85
118
.align(Alignment .CenterHorizontally ),
86
119
) {
87
- icon ()
120
+ image ()
88
121
}
89
122
}
90
123
91
- Text (
92
- text = message,
93
- modifier = Modifier
94
- .fillMaxWidth()
95
- .padding(bottom = 10 .dp),
96
- textAlign = TextAlign .Center ,
97
- style = MaterialTheme .typography.titleMedium,
98
- )
99
-
100
- Text (
101
- text = stringResource(
102
- id = R .string.horologist_install_app_prompt_title,
103
- appName,
104
- watchName,
105
- ),
106
- modifier = Modifier .fillMaxWidth(),
107
- textAlign = TextAlign .Center ,
108
- )
109
-
110
- Box (
124
+ if (topMessage.isNotBlank()) {
125
+ Text (
126
+ text = topMessage,
127
+ modifier = Modifier
128
+ .padding(top = PADDING_PURPLE )
129
+ .fillMaxWidth(),
130
+ color = MaterialTheme .colorScheme.onSurface,
131
+ textAlign = TextAlign .Center ,
132
+ maxLines = 3 ,
133
+ style = MaterialTheme .typography.titleLarge,
134
+ )
135
+ }
136
+
137
+ if (bottomMessage.isNotBlank()) {
138
+ Text (
139
+ text = bottomMessage,
140
+ modifier = Modifier
141
+ .padding(top = PADDING_PINK )
142
+ .fillMaxWidth(),
143
+ color = MaterialTheme .colorScheme.onSurfaceVariant,
144
+ textAlign = TextAlign .Center ,
145
+ maxLines = 3 ,
146
+ style = MaterialTheme .typography.bodyLarge,
147
+ )
148
+ }
149
+
150
+ Spacer (modifier = Modifier .height(PADDING_PURPLE ))
151
+
152
+ Row (
111
153
modifier = Modifier
112
- .padding(top = 20 .dp, bottom = 20 .dp )
154
+ .padding(horizontal = PADDING_PINK )
113
155
.fillMaxWidth(),
156
+ horizontalArrangement = Arrangement .End ,
114
157
) {
115
- OutlinedButton (
158
+ TextButton (
116
159
onClick = onDismissRequest,
117
160
modifier = Modifier
118
- .padding(start = 8 .dp)
119
- .align(Alignment .CenterStart ),
161
+ .padding(end = PADDING_GREEN ),
120
162
) {
121
163
Text (stringResource(id = R .string.horologist_install_app_prompt_cancel_btn_label))
122
164
}
123
165
124
166
Button (
125
167
onClick = onConfirmation,
168
+ ) {
169
+ Text (stringResource(id = R .string.horologist_install_app_prompt_ok_btn_label))
170
+ }
171
+ }
172
+ }
173
+ }
174
+
175
+ @Composable
176
+ internal fun InstallAppBottomSheetLandscapeContent (
177
+ image : @Composable (() -> Unit )? ,
178
+ topMessage : String ,
179
+ bottomMessage : String ,
180
+ onDismissRequest : () -> Unit ,
181
+ onConfirmation : () -> Unit ,
182
+ modifier : Modifier = Modifier ,
183
+ ) {
184
+ Column (
185
+ modifier = modifier
186
+ .padding(horizontal = PADDING_PURPLE )
187
+ .padding(top = PADDING_BLUE )
188
+ .verticalScroll(rememberScrollState()),
189
+ ) {
190
+ Row {
191
+ image?.let {
192
+ Box (modifier = Modifier .padding(end = PADDING_PURPLE )) {
193
+ image()
194
+ }
195
+ }
196
+
197
+ Column {
198
+ if (topMessage.isNotBlank()) {
199
+ Text (
200
+ text = topMessage,
201
+ modifier = Modifier
202
+ .fillMaxWidth(),
203
+ color = MaterialTheme .colorScheme.onSurface,
204
+ textAlign = TextAlign .Start ,
205
+ maxLines = 3 ,
206
+ style = MaterialTheme .typography.titleLarge,
207
+ )
208
+ }
209
+
210
+ if (bottomMessage.isNotBlank()) {
211
+ Text (
212
+ text = bottomMessage,
213
+ modifier = Modifier
214
+ .padding(top = PADDING_PINK )
215
+ .fillMaxWidth(),
216
+ color = MaterialTheme .colorScheme.onSurfaceVariant,
217
+ textAlign = TextAlign .Start ,
218
+ maxLines = 3 ,
219
+ style = MaterialTheme .typography.bodyLarge,
220
+ )
221
+ }
222
+ }
223
+ }
224
+
225
+ Row (
226
+ modifier = Modifier
227
+ .padding(top = PADDING_BLUE , bottom = PADDING_PINK )
228
+ .fillMaxWidth(),
229
+ horizontalArrangement = Arrangement .End ,
230
+ ) {
231
+ TextButton (
232
+ onClick = onDismissRequest,
126
233
modifier = Modifier
127
- .padding(end = 8 .dp)
128
- .align(Alignment .CenterEnd ),
234
+ .padding(end = PADDING_GREEN ),
235
+ ) {
236
+ Text (stringResource(id = R .string.horologist_install_app_prompt_cancel_btn_label))
237
+ }
238
+
239
+ Button (
240
+ onClick = onConfirmation,
129
241
) {
130
242
Text (stringResource(id = R .string.horologist_install_app_prompt_ok_btn_label))
131
243
}
@@ -136,11 +248,10 @@ internal fun InstallAppBottomSheetContent(
136
248
@Preview(showBackground = true )
137
249
@Composable
138
250
private fun InstallAppBottomSheetContentPreview () {
139
- InstallAppBottomSheetContent (
140
- message = " Stay productive and manage emails right from your wrist." ,
141
- appName = " Gmail" ,
142
- watchName = " Pixel Watch" ,
143
- icon = { Icon (Icons .Default .Email , contentDescription = null ) },
251
+ InstallAppBottomSheetPortraitContent (
252
+ image = { Icon (Icons .Default .Email , contentDescription = null ) },
253
+ topMessage = " Stay productive and manage emails right from your wrist." ,
254
+ bottomMessage = " Add the Gmail app to your Wear OS watch for easy access wherever you are." ,
144
255
onDismissRequest = { },
145
256
onConfirmation = { },
146
257
)
@@ -149,11 +260,10 @@ private fun InstallAppBottomSheetContentPreview() {
149
260
@Preview(showBackground = true )
150
261
@Composable
151
262
private fun InstallAppBottomSheetContentPreviewNoIcon () {
152
- InstallAppBottomSheetContent (
153
- message = " Stay productive and manage emails right from your wrist." ,
154
- appName = " Gmail" ,
155
- watchName = " Pixel Watch" ,
156
- icon = null ,
263
+ InstallAppBottomSheetPortraitContent (
264
+ image = null ,
265
+ topMessage = " Stay productive and manage emails right from your wrist." ,
266
+ bottomMessage = " Add the Gmail app to your Wear OS watch for easy access wherever you are." ,
157
267
onDismissRequest = { },
158
268
onConfirmation = { },
159
269
)
0 commit comments