1+ package eu.darken.butler.main.ui.onboarding.pages
2+
3+ import androidx.compose.animation.AnimatedVisibility
4+ import androidx.compose.animation.core.tween
5+ import androidx.compose.animation.fadeIn
6+ import androidx.compose.animation.slideInVertically
7+ import androidx.compose.foundation.layout.Arrangement
8+ import androidx.compose.foundation.layout.Column
9+ import androidx.compose.foundation.layout.Row
10+ import androidx.compose.foundation.layout.Spacer
11+ import androidx.compose.foundation.layout.fillMaxSize
12+ import androidx.compose.foundation.layout.fillMaxWidth
13+ import androidx.compose.foundation.layout.height
14+ import androidx.compose.foundation.layout.padding
15+ import androidx.compose.foundation.layout.size
16+ import androidx.compose.foundation.rememberScrollState
17+ import androidx.compose.foundation.verticalScroll
18+ import androidx.compose.material.icons.Icons
19+ import androidx.compose.material.icons.twotone.Devices
20+ import androidx.compose.material.icons.twotone.PhoneAndroid
21+ import androidx.compose.material.icons.twotone.ScreenRotation
22+ import androidx.compose.material.icons.twotone.TabletAndroid
23+ import androidx.compose.material3.Button
24+ import androidx.compose.material3.Card
25+ import androidx.compose.material3.CardDefaults
26+ import androidx.compose.material3.Icon
27+ import androidx.compose.material3.MaterialTheme
28+ import androidx.compose.material3.Text
29+ import androidx.compose.runtime.Composable
30+ import androidx.compose.runtime.LaunchedEffect
31+ import androidx.compose.runtime.getValue
32+ import androidx.compose.runtime.mutableStateOf
33+ import androidx.compose.runtime.remember
34+ import androidx.compose.runtime.setValue
35+ import androidx.compose.ui.Alignment
36+ import androidx.compose.ui.Modifier
37+ import androidx.compose.ui.graphics.vector.ImageVector
38+ import androidx.compose.ui.res.stringResource
39+ import androidx.compose.ui.text.font.FontWeight
40+ import androidx.compose.ui.text.style.TextAlign
41+ import androidx.compose.ui.unit.dp
42+ import eu.darken.butler.R
43+ import eu.darken.butler.common.compose.Preview2
44+ import eu.darken.butler.common.compose.PreviewWrapper
45+
46+ @Composable
47+ internal fun AdaptiveLayoutPage (
48+ onContinue : () -> Unit = {},
49+ ) {
50+ var isVisible by remember { mutableStateOf(false ) }
51+
52+ LaunchedEffect (Unit ) {
53+ isVisible = true
54+ }
55+
56+ Column (
57+ modifier = Modifier
58+ .fillMaxSize()
59+ .padding(32 .dp)
60+ ) {
61+ AnimatedVisibility (
62+ visible = isVisible,
63+ enter = fadeIn(
64+ animationSpec = tween(400 )
65+ ) + slideInVertically(
66+ initialOffsetY = { 30 },
67+ animationSpec = tween(400 )
68+ ),
69+ modifier = Modifier .weight(1f )
70+ ) {
71+ Column (
72+ modifier = Modifier
73+ .fillMaxWidth()
74+ .verticalScroll(rememberScrollState()),
75+ horizontalAlignment = Alignment .CenterHorizontally ,
76+ verticalArrangement = Arrangement .Center
77+ ) {
78+ Icon (
79+ imageVector = Icons .TwoTone .Devices ,
80+ contentDescription = null ,
81+ modifier = Modifier .size(72 .dp),
82+ tint = MaterialTheme .colorScheme.primary
83+ )
84+
85+ Spacer (modifier = Modifier .height(24 .dp))
86+
87+ Text (
88+ text = stringResource(R .string.onboarding_adaptive_title),
89+ style = MaterialTheme .typography.headlineMedium,
90+ fontWeight = FontWeight .Bold ,
91+ textAlign = TextAlign .Center ,
92+ color = MaterialTheme .colorScheme.onSurface,
93+ )
94+
95+ Spacer (modifier = Modifier .height(16 .dp))
96+
97+ Text (
98+ text = stringResource(R .string.onboarding_adaptive_message),
99+ style = MaterialTheme .typography.bodyLarge,
100+ textAlign = TextAlign .Center ,
101+ color = MaterialTheme .colorScheme.onSurface.copy(alpha = 0.8f ),
102+ )
103+
104+ Spacer (modifier = Modifier .height(32 .dp))
105+
106+ Column (
107+ modifier = Modifier .fillMaxWidth(),
108+ verticalArrangement = Arrangement .spacedBy(12 .dp)
109+ ) {
110+ AdaptiveFeatureCard (
111+ icon = Icons .TwoTone .PhoneAndroid ,
112+ title = stringResource(R .string.onboarding_adaptive_phone_title),
113+ description = stringResource(R .string.onboarding_adaptive_phone_description)
114+ )
115+
116+ AdaptiveFeatureCard (
117+ icon = Icons .TwoTone .ScreenRotation ,
118+ title = stringResource(R .string.onboarding_adaptive_landscape_title),
119+ description = stringResource(R .string.onboarding_adaptive_landscape_description)
120+ )
121+
122+ AdaptiveFeatureCard (
123+ icon = Icons .TwoTone .TabletAndroid ,
124+ title = stringResource(R .string.onboarding_adaptive_tablet_title),
125+ description = stringResource(R .string.onboarding_adaptive_tablet_description)
126+ )
127+ }
128+
129+ Spacer (modifier = Modifier .height(24 .dp))
130+ }
131+ }
132+
133+ AnimatedVisibility (
134+ visible = isVisible,
135+ enter = fadeIn(
136+ animationSpec = tween(
137+ durationMillis = 400 ,
138+ delayMillis = 200
139+ )
140+ )
141+ ) {
142+ Button (
143+ onClick = onContinue,
144+ modifier = Modifier .fillMaxWidth()
145+ ) {
146+ Text (text = stringResource(R .string.onboarding_adaptive_action))
147+ }
148+ }
149+ }
150+ }
151+
152+ @Composable
153+ private fun AdaptiveFeatureCard (
154+ icon : ImageVector ,
155+ title : String ,
156+ description : String ,
157+ modifier : Modifier = Modifier
158+ ) {
159+ Card (
160+ modifier = modifier.fillMaxWidth(),
161+ colors = CardDefaults .cardColors(
162+ containerColor = MaterialTheme .colorScheme.surfaceVariant
163+ )
164+ ) {
165+ Row (
166+ modifier = Modifier
167+ .padding(16 .dp)
168+ .fillMaxWidth(),
169+ verticalAlignment = Alignment .CenterVertically ,
170+ horizontalArrangement = Arrangement .Start
171+ ) {
172+ Icon (
173+ imageVector = icon,
174+ contentDescription = null ,
175+ modifier = Modifier .size(40 .dp),
176+ tint = MaterialTheme .colorScheme.primary
177+ )
178+
179+ Column (
180+ modifier = Modifier
181+ .weight(1f )
182+ .padding(start = 16 .dp)
183+ ) {
184+ Text (
185+ text = title,
186+ style = MaterialTheme .typography.titleSmall,
187+ fontWeight = FontWeight .Bold ,
188+ color = MaterialTheme .colorScheme.onSurface
189+ )
190+ Spacer (modifier = Modifier .height(4 .dp))
191+ Text (
192+ text = description,
193+ style = MaterialTheme .typography.bodySmall,
194+ color = MaterialTheme .colorScheme.onSurface.copy(alpha = 0.7f )
195+ )
196+ }
197+ }
198+ }
199+ }
200+
201+ @Preview2
202+ @Composable
203+ private fun AdaptiveLayoutPagePreview () {
204+ PreviewWrapper {
205+ AdaptiveLayoutPage ()
206+ }
207+ }
0 commit comments