Skip to content

Commit 31a71aa

Browse files
Added AweryID screen,
IntroDsl for easy intro screen creation, Fixed missing spacing at the bottom of LibraryTabbedScreen.kt
1 parent 33a4bfd commit 31a71aa

File tree

20 files changed

+1053
-476
lines changed

20 files changed

+1053
-476
lines changed

data/src/commonMain/kotlin/com/mrboomdev/awery/data/settings/AwerySettings.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ object AwerySettings {
2626
settings[EXTENSION_IS_ENABLED_PREFIX + id] = isEnabled
2727
}
2828

29+
val aweryServerInstance by setting("http://awery.mrboomdev.ru:80")
2930
val aweryServerToken by setting("")
3031
val darkTheme by setting(DarkTheme.AUTO)
3132
val primaryColor by setting(-1L)

ui/src/commonMain/kotlin/com/mrboomdev/awery/ui/App.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ import com.mrboomdev.awery.data.settings.collectAsState
4444
import com.mrboomdev.awery.extension.loaders.ExtensionInstaller
4545
import com.mrboomdev.awery.resources.*
4646
import com.mrboomdev.awery.ui.components.*
47-
import com.mrboomdev.awery.ui.screens.intro.IntroStep
47+
import com.mrboomdev.awery.ui.screens.intro.steps.IntroThemeStep
48+
import com.mrboomdev.awery.ui.screens.intro.steps.IntroUserStep
49+
import com.mrboomdev.awery.ui.screens.intro.steps.IntroWelcomeStep
4850
import com.mrboomdev.awery.ui.screens.settings.SettingsDefaults
4951
import com.mrboomdev.awery.ui.screens.settings.itemClickable
5052
import com.mrboomdev.awery.ui.screens.settings.pages.SettingsPages
@@ -189,9 +191,9 @@ fun App(onNavigate: (NavigationState) -> Unit = {}) {
189191

190192
RememberLaunchedEffect(Unit) {
191193
when {
192-
!AwerySettings.introDidWelcome.value -> Routes.Intro(IntroStep.Welcome, singleStep = false)
193-
!AwerySettings.introDidTheme.value -> Routes.Intro(IntroStep.Theme, singleStep = false)
194-
AwerySettings.username.value.isBlank() -> Routes.Intro(IntroStep.UserCreation, singleStep = false)
194+
!AwerySettings.introDidWelcome.value -> Routes.Intro(IntroWelcomeStep, singleStep = false)
195+
!AwerySettings.introDidTheme.value -> Routes.Intro(IntroThemeStep, singleStep = false)
196+
AwerySettings.username.value.isBlank() -> Routes.Intro(IntroUserStep, singleStep = false)
195197
else -> null
196198
}.also {
197199
if(it == null) {
@@ -478,7 +480,7 @@ private fun AweryDrawerContent(
478480
contentDescription = null,
479481
onClick = {
480482
navigation.push(Routes.Intro(
481-
step = IntroStep.UserCreation,
483+
step = IntroUserStep,
482484
singleStep = true
483485
))
484486

ui/src/commonMain/kotlin/com/mrboomdev/awery/ui/Routes.kt

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import com.mrboomdev.awery.data.settings.collectAsState
77
import com.mrboomdev.awery.extension.sdk.Preference
88
import com.mrboomdev.awery.extension.sdk.Video
99
import com.mrboomdev.awery.resources.*
10-
import com.mrboomdev.awery.ui.screens.auth.AuthScreen
1110
import com.mrboomdev.awery.ui.screens.browser.BrowserScreen
12-
import com.mrboomdev.awery.ui.screens.extension.*
11+
import com.mrboomdev.awery.ui.screens.extension.ExtensionFeedScreen
12+
import com.mrboomdev.awery.ui.screens.extension.ExtensionScreen
13+
import com.mrboomdev.awery.ui.screens.extension.ExtensionSearchScreen
1314
import com.mrboomdev.awery.ui.screens.home.HomeScreen
1415
import com.mrboomdev.awery.ui.screens.intro.IntroScreen
15-
import com.mrboomdev.awery.ui.screens.intro.IntroStep
16+
import com.mrboomdev.awery.ui.screens.intro.steps.IntroStep
17+
import com.mrboomdev.awery.ui.screens.intro.steps.IntroUserStep
1618
import com.mrboomdev.awery.ui.screens.library.LibraryColumnScreen
1719
import com.mrboomdev.awery.ui.screens.library.LibraryTabbedScreen
1820
import com.mrboomdev.awery.ui.screens.media.MediaScreen
@@ -157,14 +159,6 @@ sealed interface Routes {
157159
contentPadding: PaddingValues
158160
) = BrowserScreen(url)
159161
}
160-
161-
@Serializable
162-
data object Auth: Routes {
163-
@Composable
164-
override fun Content(
165-
contentPadding: PaddingValues
166-
) = AuthScreen(contentPadding = contentPadding)
167-
}
168162
}
169163

170164
enum class MainRoutes(
@@ -211,7 +205,7 @@ enum class MainRoutes(
211205
PROFILE(
212206
title = Res.string.account,
213207
icon = Res.drawable.ic_account_outlined,
214-
route = Routes.Intro(IntroStep.UserCreation, true),
208+
route = Routes.Intro(IntroUserStep, true),
215209
desktopOnly = true
216210
);
217211

ui/src/commonMain/kotlin/com/mrboomdev/awery/ui/screens/auth/AuthScreen.kt

Lines changed: 0 additions & 13 deletions
This file was deleted.

ui/src/commonMain/kotlin/com/mrboomdev/awery/ui/screens/auth/AuthViewModel.kt

Lines changed: 0 additions & 6 deletions
This file was deleted.

ui/src/commonMain/kotlin/com/mrboomdev/awery/ui/screens/home/HomeScreen.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ fun HomeScreen(
7373
fun Content() {
7474
LazyColumn(
7575
modifier = Modifier.fillMaxSize(),
76-
contentPadding = contentPadding
77-
.only(vertical = true)
78-
.add(bottom = 32.dp),
76+
contentPadding = contentPadding.only(vertical = true),
7977
state = lazyListState,
8078
userScrollEnabled = !showShimmer
8179
) {
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
package com.mrboomdev.awery.ui.screens.intro
2+
3+
import androidx.compose.foundation.Image
4+
import androidx.compose.foundation.layout.*
5+
import androidx.compose.foundation.rememberScrollState
6+
import androidx.compose.foundation.verticalScroll
7+
import androidx.compose.material3.*
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.runtime.remember
10+
import androidx.compose.ui.Alignment
11+
import androidx.compose.ui.Modifier
12+
import androidx.compose.ui.graphics.painter.Painter
13+
import androidx.compose.ui.graphics.vector.VectorPainter
14+
import androidx.compose.ui.text.font.FontWeight
15+
import androidx.compose.ui.unit.Dp
16+
import androidx.compose.ui.unit.dp
17+
import com.mrboomdev.awery.ui.utils.*
18+
19+
@DslMarker
20+
private annotation class IntroDslMarker
21+
22+
@IntroDslMarker
23+
interface IntroDsl {
24+
var iconSize: Dp
25+
var icon: @Composable () -> Painter?
26+
var title: @Composable () -> String?
27+
var description: @Composable () -> String?
28+
29+
var primaryContent: (@Composable ColumnScope.(PaddingValues) -> Unit)?
30+
var primaryContentAlignment: Alignment.Horizontal
31+
32+
var secondaryContent: (@Composable ColumnScope.(PaddingValues) -> Unit)?
33+
var secondaryContentAlignment: Alignment.Horizontal
34+
35+
fun addAction(content: IntroActionDsl.() -> Unit)
36+
var actionsAlignment: Alignment.Horizontal
37+
var actionScale: Float
38+
}
39+
40+
fun IntroDsl.setAlignment(alignment: Alignment.Horizontal) {
41+
primaryContentAlignment = alignment
42+
secondaryContentAlignment = alignment
43+
actionsAlignment = alignment
44+
}
45+
46+
@IntroDslMarker
47+
interface IntroActionDsl {
48+
var text: String
49+
var enabled: Boolean
50+
var onClick: () -> Unit
51+
}
52+
53+
@Composable
54+
fun IntroDslWrapper(
55+
contentPadding: PaddingValues = PaddingValues.Zero,
56+
content: IntroDsl.() -> Unit
57+
) {
58+
val windowSize = currentWindowSize()
59+
60+
val contentImpl = remember(content) {
61+
object : IntroDsl {
62+
val actions = mutableListOf<IntroActionDsl>()
63+
override var actionScale = 1f
64+
override var iconSize = IntroDefaults.iconSize
65+
override var icon: @Composable () -> Painter? = { null }
66+
override var title: @Composable () -> String? = { null }
67+
override var description: @Composable () -> String? = { null }
68+
override var primaryContent: @Composable (ColumnScope.(PaddingValues) -> Unit)? = null
69+
override var primaryContentAlignment = Alignment.Start
70+
override var secondaryContent: @Composable (ColumnScope.(PaddingValues) -> Unit)? = null
71+
override var secondaryContentAlignment = Alignment.Start
72+
override var actionsAlignment = Alignment.Start
73+
74+
override fun addAction(content: IntroActionDsl.() -> Unit) {
75+
actions += object : IntroActionDsl {
76+
override lateinit var text: String
77+
override var enabled = true
78+
override lateinit var onClick: () -> Unit
79+
}.apply(content)
80+
}
81+
}.apply(content)
82+
}
83+
84+
val icon: (@Composable () -> Unit)? = contentImpl.icon()?.let { icon ->
85+
when(icon) {
86+
is VectorPainter -> {{
87+
Icon(
88+
modifier = Modifier.size(contentImpl.iconSize),
89+
tint = MaterialTheme.colorScheme.primary,
90+
painter = icon,
91+
contentDescription = null
92+
)
93+
}}
94+
95+
else -> {{
96+
Image(
97+
modifier = Modifier.size(contentImpl.iconSize),
98+
painter = icon,
99+
contentDescription = null
100+
)
101+
}}
102+
}
103+
}
104+
105+
if(windowSize.width >= WindowSizeType.Large) {
106+
Row(
107+
modifier = Modifier.fillMaxSize(),
108+
horizontalArrangement = Arrangement.spacedBy(64.dp)
109+
) {
110+
Column(
111+
modifier = Modifier
112+
.fillMaxHeight()
113+
.weight(1f)
114+
.verticalScroll(rememberScrollState())
115+
.padding(contentPadding.only(top = true, horizontal = true))
116+
.padding(start = niceSideInset()),
117+
verticalArrangement = Arrangement.spacedBy(8.dp),
118+
horizontalAlignment = contentImpl.primaryContentAlignment
119+
) {
120+
icon?.invoke()
121+
122+
contentImpl.title()?.also { title ->
123+
Text(
124+
modifier = Modifier.padding(top = 8.dp),
125+
style = MaterialTheme.typography.headlineLarge,
126+
color = MaterialTheme.colorScheme.onBackground,
127+
fontWeight = FontWeight.Normal,
128+
textAlign = contentImpl.primaryContentAlignment.toTextAlign(),
129+
text = title
130+
)
131+
}
132+
133+
contentImpl.description()?.also { description ->
134+
Text(
135+
textAlign = contentImpl.primaryContentAlignment.toTextAlign(),
136+
text = description
137+
)
138+
}
139+
}
140+
141+
Box(
142+
modifier = Modifier
143+
.fillMaxHeight()
144+
.weight(1f)
145+
) {
146+
Column(
147+
modifier = Modifier
148+
.fillMaxSize()
149+
.verticalScroll(rememberScrollState()),
150+
horizontalAlignment = contentImpl.secondaryContentAlignment
151+
) {
152+
contentImpl.secondaryContent?.invoke(this, contentPadding.only(
153+
top = true, end = true
154+
).add(bottom = 64.dp, end = niceSideInset()))
155+
}
156+
157+
Row(
158+
modifier = Modifier
159+
.fillMaxWidth()
160+
.padding(contentPadding.only(bottom = true, end = true))
161+
.padding(end = niceSideInset())
162+
.align(Alignment.BottomCenter),
163+
horizontalArrangement = Arrangement.spacedBy(IntroDefaults.spaceBetweenActions, contentImpl.actionsAlignment)
164+
) {
165+
contentImpl.actions.forEach { action ->
166+
Button(
167+
enabled = action.enabled,
168+
onClick = action.onClick
169+
) {
170+
Text(action.text)
171+
}
172+
}
173+
}
174+
}
175+
}
176+
} else {
177+
Column(Modifier.fillMaxSize()) {
178+
Column(
179+
modifier = Modifier
180+
.fillMaxWidth()
181+
.weight(1f)
182+
.verticalScroll(rememberScrollState())
183+
.padding(contentPadding.only(top = true, start = true, end = true)),
184+
verticalArrangement = Arrangement.spacedBy(8.dp),
185+
horizontalAlignment = contentImpl.primaryContentAlignment
186+
) {
187+
if(icon != null && contentImpl.primaryContentAlignment == Alignment.CenterHorizontally) {
188+
Spacer(Modifier.height(16.dp))
189+
}
190+
191+
icon?.invoke()
192+
193+
contentImpl.title()?.also { title ->
194+
Text(
195+
modifier = Modifier.padding(top = 8.dp),
196+
style = MaterialTheme.typography.headlineLarge,
197+
color = MaterialTheme.colorScheme.onBackground,
198+
fontWeight = FontWeight.Normal,
199+
textAlign = contentImpl.primaryContentAlignment.toTextAlign(),
200+
text = title
201+
)
202+
}
203+
204+
contentImpl.description()?.also { description ->
205+
Text(
206+
textAlign = contentImpl.primaryContentAlignment.toTextAlign(),
207+
text = description
208+
)
209+
}
210+
211+
Column(
212+
modifier = Modifier
213+
.fillMaxWidth()
214+
.weight(1f),
215+
horizontalAlignment = contentImpl.secondaryContentAlignment
216+
) {
217+
contentImpl.secondaryContent?.invoke(this, contentPadding.only(
218+
/*horizontal = true*/
219+
).add(vertical = 16.dp))
220+
}
221+
}
222+
223+
Row(
224+
modifier = Modifier
225+
.fillMaxWidth()
226+
.padding(contentPadding.only(horizontal = true, bottom = true)),
227+
horizontalArrangement = Arrangement.spacedBy(IntroDefaults.spaceBetweenActions, contentImpl.actionsAlignment)
228+
) {
229+
contentImpl.actions.forEach { action ->
230+
Button(
231+
enabled = action.enabled,
232+
onClick = action.onClick,
233+
234+
contentPadding = ButtonDefaults.ContentPadding *
235+
(contentImpl.actionScale.takeUnless { it == 1f }?.times(1.25f) ?: 1f)
236+
) {
237+
Text(
238+
fontSize = LocalTextStyle.current.fontSize * contentImpl.actionScale,
239+
text = action.text
240+
)
241+
}
242+
}
243+
}
244+
245+
if(contentImpl.actionScale > 1f) {
246+
Spacer(Modifier.height((contentImpl.actionScale * 10f).dp))
247+
}
248+
}
249+
}
250+
}

0 commit comments

Comments
 (0)