Merge pull request #6795 from thundernest/add_onboarding_feature

Add onboarding feature
This commit is contained in:
Wolf-Martell Montwé 2023-04-03 16:44:32 +00:00 committed by GitHub
commit 1a302a2dd3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 551 additions and 53 deletions

View file

@ -10,7 +10,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import app.k9mail.core.ui.compose.common.DevicePreviews
import app.k9mail.core.ui.compose.designsystem.atom.Surface
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveContent
import app.k9mail.core.ui.compose.theme.K9Theme
import app.k9mail.core.ui.compose.theme.MainTheme
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
import app.k9mail.ui.catalog.items.buttonItems
import app.k9mail.ui.catalog.items.colorItems
import app.k9mail.ui.catalog.items.imageItems
@ -30,39 +33,57 @@ fun CatalogContent(
modifier: Modifier = Modifier,
) {
Surface {
LazyVerticalGrid(
columns = GridCells.Adaptive(300.dp),
contentPadding = contentPadding,
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
modifier = modifier.padding(MainTheme.spacings.double),
) {
themeHeaderItem(text = "Thunderbird Catalog")
themeSelectorItems(
catalogTheme = catalogTheme,
catalogThemeVariant = catalogThemeVariant,
onThemeChange = onThemeChange,
onThemeVariantChange = onThemeVariantChange,
)
ResponsiveContent {
LazyVerticalGrid(
columns = GridCells.Adaptive(300.dp),
contentPadding = contentPadding,
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
modifier = modifier.padding(MainTheme.spacings.double),
) {
themeHeaderItem(text = "Thunderbird Catalog")
themeSelectorItems(
catalogTheme = catalogTheme,
catalogThemeVariant = catalogThemeVariant,
onThemeChange = onThemeChange,
onThemeVariantChange = onThemeVariantChange,
)
typographyItems()
colorItems()
buttonItems()
selectionControlItems()
textFieldItems()
imageItems()
typographyItems()
colorItems()
buttonItems()
selectionControlItems()
textFieldItems()
imageItems()
}
}
}
}
@DevicePreviews
@Composable
internal fun CatalogContentPreview() {
CatalogContent(
catalogTheme = CatalogTheme.K9,
catalogThemeVariant = CatalogThemeVariant.LIGHT,
onThemeChange = {},
onThemeVariantChange = {},
contentPadding = PaddingValues(),
)
internal fun CatalogContentK9ThemePreview() {
K9Theme {
CatalogContent(
catalogTheme = CatalogTheme.K9,
catalogThemeVariant = CatalogThemeVariant.LIGHT,
onThemeChange = {},
onThemeVariantChange = {},
contentPadding = PaddingValues(),
)
}
}
@DevicePreviews
@Composable
internal fun CatalogContentThunderbirdThemePreview() {
ThunderbirdTheme {
CatalogContent(
catalogTheme = CatalogTheme.THUNDERBIRD,
catalogThemeVariant = CatalogThemeVariant.LIGHT,
onThemeChange = {},
onThemeVariantChange = {},
contentPadding = PaddingValues(),
)
}
}

View file

@ -578,6 +578,8 @@ style:
ignoreConstantDeclaration: true
ignoreCompanionObjectPropertyDeclaration: true
ignoreAnnotation: false
ignoreAnnotated:
- 'Preview'
ignoreNamedArgument: true
ignoreEnums: false
ignoreRanges: false

View file

@ -12,11 +12,11 @@ enum class WindowSizeClass {
;
companion object {
private const val COMPACT_MAX_WIDTH = 600
private const val COMPACT_MAX_HEIGHT = 480
const val COMPACT_MAX_WIDTH = 600
const val COMPACT_MAX_HEIGHT = 480
private const val MEDIUM_MAX_WIDTH = 840
private const val MEDIUM_MAX_HEIGHT = 900
const val MEDIUM_MAX_WIDTH = 840
const val MEDIUM_MAX_HEIGHT = 900
fun fromWidth(width: Int): WindowSizeClass {
return when {

View file

@ -5,6 +5,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import app.k9mail.core.ui.compose.theme.MainTheme
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
import androidx.compose.material.Surface as MaterialSurface
@ -13,11 +14,13 @@ import androidx.compose.material.Surface as MaterialSurface
fun Surface(
modifier: Modifier = Modifier,
color: Color = MainTheme.colors.surface,
elevation: Dp = MainTheme.elevations.default,
content: @Composable () -> Unit,
) {
MaterialSurface(
modifier = modifier,
content = content,
elevation = elevation,
color = color,
)
}

View file

@ -0,0 +1,86 @@
package app.k9mail.core.ui.compose.designsystem.template
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.dp
import app.k9mail.core.ui.compose.designsystem.atom.Surface
import app.k9mail.core.ui.compose.theme.K9Theme
/**
* The [LazyColumnWithFooter] composable creates a [LazyColumn] with a footer.
*
* @param modifier The modifier to be applied to the layout.
* @param verticalArrangement The vertical arrangement of the children.
* @param horizontalAlignment The horizontal alignment of the children.
* @param footer The footer to be displayed at the bottom of the [LazyColumn].
* @param content The content of the [LazyColumn].
*/
@Composable
fun LazyColumnWithFooter(
modifier: Modifier = Modifier,
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
footer: @Composable () -> Unit = {},
content: LazyListScope.() -> Unit,
) {
LazyColumn(
modifier = modifier,
verticalArrangement = verticalArrangementWithFooter(verticalArrangement),
horizontalAlignment = horizontalAlignment,
) {
content()
item { footer() }
}
}
@Composable
private fun verticalArrangementWithFooter(verticalArrangement: Arrangement.Vertical) = remember {
object : Arrangement.Vertical {
override fun Density.arrange(
totalSize: Int,
sizes: IntArray,
outPositions: IntArray,
) {
val innerSizes = sizes.dropLast(1).toIntArray()
val footerSize = sizes.last()
val innerTotalSize = totalSize - footerSize
with(verticalArrangement) {
arrange(
totalSize = innerTotalSize,
sizes = innerSizes,
outPositions = outPositions,
)
}
outPositions[outPositions.lastIndex] = totalSize - footerSize
}
}
}
@Composable
@Preview
internal fun LazyColumnWithFooterPreview() {
K9Theme {
Surface {
LazyColumnWithFooter(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(32.dp, Alignment.CenterVertically),
footer = { Text(text = "Footer") },
) {
items(10) {
Text(text = "Item $it")
}
}
}
}
}

View file

@ -0,0 +1,129 @@
package app.k9mail.core.ui.compose.designsystem.template
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import app.k9mail.core.ui.compose.common.DevicePreviews
import app.k9mail.core.ui.compose.common.window.WindowSizeClass
import app.k9mail.core.ui.compose.common.window.getWindowSizeInfo
import app.k9mail.core.ui.compose.designsystem.atom.Surface
import app.k9mail.core.ui.compose.theme.K9Theme
import app.k9mail.core.ui.compose.theme.MainTheme
/**
* The [ResponsiveContent] composable automatically adapts its child content to different screen sizes and resolutions,
* providing a responsive layout for a better user experience.
*
* It uses the [WindowSizeClass] (Compact, Medium, or Expanded) to make appropriate layout adjustments.
*
* @param modifier The modifier to be applied to the layout.
* @param content The content to be displayed.
*/
@Composable
fun ResponsiveContent(
modifier: Modifier = Modifier,
content: @Composable () -> Unit,
) {
val windowSizeClass = getWindowSizeInfo()
when (windowSizeClass.screenWidthSizeClass) {
WindowSizeClass.Compact -> CompactContent(modifier = modifier, content = content)
WindowSizeClass.Medium -> MediumContent(modifier = modifier, content = content)
WindowSizeClass.Expanded -> ExpandedContent(modifier = modifier, content = content)
}
}
@Composable
private fun CompactContent(
modifier: Modifier = Modifier,
content: @Composable () -> Unit,
) {
Box(
modifier = Modifier
.fillMaxSize()
.then(modifier),
) {
content()
}
}
@Composable
private fun MediumContent(
modifier: Modifier = Modifier,
content: @Composable () -> Unit,
) {
Box(
modifier = Modifier
.fillMaxSize()
.then(modifier),
contentAlignment = Alignment.TopCenter,
) {
Box(
modifier = Modifier.requiredWidth(WindowSizeClass.COMPACT_MAX_WIDTH.dp),
) {
content()
}
}
}
@Composable
private fun ExpandedContent(
modifier: Modifier = Modifier,
content: @Composable () -> Unit,
) {
when (getWindowSizeInfo().screenHeightSizeClass) {
WindowSizeClass.Compact -> MediumContent(modifier, content)
WindowSizeClass.Medium -> {
Box(
modifier = Modifier
.fillMaxSize()
.then(modifier),
contentAlignment = Alignment.TopCenter,
) {
Surface(
modifier = Modifier.requiredWidth(WindowSizeClass.MEDIUM_MAX_WIDTH.dp),
elevation = MainTheme.elevations.raised,
) {
content()
}
}
}
WindowSizeClass.Expanded -> {
Box(
modifier = Modifier
.fillMaxSize()
.then(modifier),
contentAlignment = Alignment.Center,
) {
Surface(
modifier = Modifier
.requiredWidth(WindowSizeClass.MEDIUM_MAX_WIDTH.dp)
.requiredHeight(WindowSizeClass.MEDIUM_MAX_HEIGHT.dp),
elevation = MainTheme.elevations.raised,
) {
content()
}
}
}
}
}
@Composable
@DevicePreviews
internal fun ResponsiveContentPreview() {
K9Theme {
Surface {
ResponsiveContent {
Surface(
color = MainTheme.colors.info,
modifier = Modifier.fillMaxSize(),
) {}
}
}
}
}

View file

@ -7,7 +7,9 @@ import androidx.compose.ui.unit.dp
@Immutable
data class Elevations(
val card: Dp = 0.dp,
val default: Dp = 0.dp,
val raised: Dp = 2.dp,
val card: Dp = 4.dp,
)
internal val LocalElevations = staticCompositionLocalOf { Elevations() }

View file

@ -2,6 +2,9 @@ package app.k9mail.core.ui.compose.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable
import app.k9mail.core.ui.compose.theme.color.MaterialColor
import app.k9mail.core.ui.compose.theme.color.darkColors
import app.k9mail.core.ui.compose.theme.color.lightColors
private val k9LightColorPalette = lightColors(
primary = MaterialColor.gray_800,
@ -12,7 +15,7 @@ private val k9LightColorPalette = lightColors(
private val k9DarkColorPalette = darkColors(
primary = MaterialColor.gray_100,
primaryVariant = MaterialColor.gray_50,
primaryVariant = MaterialColor.gray_400,
secondary = MaterialColor.pink_300,
secondaryVariant = MaterialColor.pink_500,
)
@ -22,7 +25,7 @@ fun K9Theme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit,
) {
val images = Images(logo = R.drawable.core_ui_theme_logo_orange)
val images = Images(logo = R.drawable.core_ui_theme_k9_logo)
MainTheme(
lightColorPalette = k9LightColorPalette,

View file

@ -7,6 +7,9 @@ import androidx.compose.material.Typography
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.ReadOnlyComposable
import app.k9mail.core.ui.compose.theme.color.Colors
import app.k9mail.core.ui.compose.theme.color.LocalColors
import app.k9mail.core.ui.compose.theme.color.toMaterialColors
@Composable
fun MainTheme(

View file

@ -2,21 +2,22 @@ package app.k9mail.core.ui.compose.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable
import app.k9mail.core.ui.compose.theme.color.MaterialColor
import app.k9mail.core.ui.compose.theme.color.darkColors
import app.k9mail.core.ui.compose.theme.color.lightColors
private val thunderbirdLightColorPalette = lightColors(
primary = MaterialColor.blue_600,
primaryVariant = MaterialColor.light_blue_500,
primary = MaterialColor.blue_800,
primaryVariant = MaterialColor.light_blue_700,
secondary = MaterialColor.pink_500,
secondaryVariant = MaterialColor.pink_300,
background = MaterialColor.gray_200,
)
private val thunderbirdDarkColorPalette = darkColors(
primary = MaterialColor.blue_100,
primaryVariant = MaterialColor.blue_50,
primary = MaterialColor.blue_200,
primaryVariant = MaterialColor.blue_400,
secondary = MaterialColor.pink_300,
secondaryVariant = MaterialColor.pink_500,
background = MaterialColor.gray_800,
)
@Composable
@ -24,7 +25,7 @@ fun ThunderbirdTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit,
) {
val images = Images(logo = R.drawable.core_ui_theme_logo_teal)
val images = Images(logo = R.drawable.core_ui_theme_thunderbird_logo)
MainTheme(
lightColorPalette = thunderbirdLightColorPalette,

View file

@ -1,4 +1,4 @@
package app.k9mail.core.ui.compose.theme
package app.k9mail.core.ui.compose.theme.color
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.staticCompositionLocalOf
@ -31,7 +31,7 @@ internal fun lightColors(
primaryVariant: Color = MaterialColor.deep_purple_900,
secondary: Color = MaterialColor.cyan_600,
secondaryVariant: Color = MaterialColor.cyan_800,
background: Color = MaterialColor.gray_200,
background: Color = Color.White,
surface: Color = Color.White,
success: Color = MaterialColor.green_600,
error: Color = MaterialColor.red_600,
@ -66,9 +66,9 @@ internal fun darkColors(
primary: Color = MaterialColor.deep_purple_200,
primaryVariant: Color = MaterialColor.deep_purple_50,
secondary: Color = MaterialColor.cyan_300,
secondaryVariant: Color = MaterialColor.cyan_100,
background: Color = MaterialColor.gray_800,
surface: Color = MaterialColor.gray_900,
secondaryVariant: Color = secondary,
background: Color = MaterialColor.gray_950,
surface: Color = MaterialColor.gray_950,
success: Color = MaterialColor.green_300,
error: Color = MaterialColor.red_300,
warning: Color = MaterialColor.orange_300,

View file

@ -1,6 +1,6 @@
@file:Suppress("unused")
package app.k9mail.core.ui.compose.theme
package app.k9mail.core.ui.compose.theme.color
import androidx.compose.ui.graphics.Color
@ -214,4 +214,5 @@ internal object MaterialColor {
val gray_700 = Color(color = 0xFF616161)
val gray_800 = Color(color = 0xFF424242)
val gray_900 = Color(color = 0xFF212121)
val gray_950 = Color(color = 0xFF121212)
}

View file

@ -64,7 +64,7 @@
android:pathData="M171.99,116V48C171.99,41.37 166.62,36 159.99,36L31.99,36C25.37,36 19.99,41.37 19.99,48V116C19.99,122.62 25.37,128 31.99,128L159.99,128C166.62,128 171.99,122.62 171.99,116Z"
android:strokeAlpha="0.2" />
<path
android:fillColor="#FFB74D"
android:fillColor="#FF2C55"
android:pathData="M172,116V48C172,41.37 166.63,36 160,36L32,36C25.37,36 20,41.37 20,48V116C20,122.63 25.37,128 32,128H160C166.63,128 172,122.63 172,116Z" />
<path
android:fillColor="#00000000"
@ -73,10 +73,10 @@
android:strokeColor="#FBE9E7"
android:strokeLineCap="round" />
<path
android:fillColor="#FFB74D"
android:fillColor="#FF2C55"
android:pathData="M32,36C25.35,36 20,41.35 20,48V49C20,42.35 25.35,37 32,37H160C166.65,37 172,42.35 172,49V48C172,41.35 166.65,36 160,36H32Z" />
<path
android:fillColor="#F57C00"
android:fillColor="#C2185B"
android:pathData="M20,115V116C20,122.65 25.35,128 32,128H160C166.65,128 172,122.65 172,116V115C172,121.65 166.65,127 160,127H32C25.35,127 20,121.65 20,115Z" />
<path
android:fillAlpha="0.2"

View file

@ -64,7 +64,7 @@
android:pathData="M171.99,116V48C171.99,41.37 166.62,36 159.99,36L31.99,36C25.37,36 19.99,41.37 19.99,48V116C19.99,122.62 25.37,128 31.99,128L159.99,128C166.62,128 171.99,122.62 171.99,116Z"
android:strokeAlpha="0.2" />
<path
android:fillColor="#4DB6AC"
android:fillColor="#1E88E5"
android:pathData="M172,116V48C172,41.37 166.63,36 160,36L32,36C25.37,36 20,41.37 20,48V116C20,122.63 25.37,128 32,128H160C166.63,128 172,122.63 172,116Z" />
<path
android:fillColor="#00000000"
@ -73,7 +73,7 @@
android:strokeColor="#FBE9E7"
android:strokeLineCap="round" />
<path
android:fillColor="#4DB6AC"
android:fillColor="#1E88E5"
android:pathData="M32,36C25.35,36 20,41.35 20,48V49C20,42.35 25.35,37 32,37H160C166.65,37 172,42.35 172,49V48C172,41.35 166.65,36 160,36H32Z" />
<path
android:fillColor="#00796B"

View file

@ -0,0 +1,12 @@
plugins {
id(ThunderbirdPlugins.Library.androidCompose)
}
android {
namespace = "net.thunderbird.feature.onboarding"
resourcePrefix = "onboarding_"
}
dependencies {
implementation(projects.core.ui.compose.designsystem)
}

View file

@ -0,0 +1,171 @@
package net.thunderbird.feature.onboarding
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import app.k9mail.core.ui.compose.common.DevicePreviews
import app.k9mail.core.ui.compose.designsystem.atom.Background
import app.k9mail.core.ui.compose.designsystem.atom.button.Button
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonText
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBody1
import app.k9mail.core.ui.compose.designsystem.atom.text.TextHeadline2
import app.k9mail.core.ui.compose.designsystem.template.LazyColumnWithFooter
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveContent
import app.k9mail.core.ui.compose.theme.K9Theme
import app.k9mail.core.ui.compose.theme.MainTheme
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
@Composable
internal fun OnboardingContent(
onStartClick: () -> Unit,
onImportClick: () -> Unit,
modifier: Modifier = Modifier,
) {
ResponsiveContent {
Background(
modifier = modifier,
) {
LazyColumnWithFooter(
modifier = Modifier
.fillMaxHeight()
.padding(MainTheme.spacings.double),
footer = {
WelcomeFooter(
modifier = Modifier
.fillMaxWidth()
.padding(top = MainTheme.spacings.triple),
onStartClick = onStartClick,
onImportClick = onImportClick,
)
},
verticalArrangement = Arrangement.spacedBy(MainTheme.sizes.large, Alignment.CenterVertically),
) {
item {
WelcomeLogo(
modifier = Modifier.fillMaxWidth(),
)
}
item {
WelcomeTitle(
modifier = Modifier.fillMaxWidth(),
)
}
item {
WelcomeMessage(
modifier = Modifier.fillMaxWidth(),
)
}
}
}
}
}
@Composable
private fun WelcomeLogo(
modifier: Modifier = Modifier,
) {
Column(
modifier = Modifier.then(modifier),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Box(
modifier = Modifier
.size(MainTheme.sizes.huge)
.clip(shape = RoundedCornerShape(percent = 50))
.background(color = MainTheme.colors.surface),
) {
Image(
painter = painterResource(id = MainTheme.images.logo),
contentDescription = null,
modifier = Modifier.size(MainTheme.sizes.huge),
)
}
}
}
@Composable
private fun WelcomeTitle(
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally,
) {
TextHeadline2(
text = stringResource(id = R.string.onboarding_welcome_title),
)
}
}
@Composable
private fun WelcomeMessage(
modifier: Modifier = Modifier,
) {
Column(
modifier = Modifier
.padding(start = MainTheme.spacings.quadruple, end = MainTheme.spacings.quadruple)
.then(modifier),
horizontalAlignment = Alignment.CenterHorizontally,
) {
TextBody1(
text = stringResource(id = R.string.onboarding_welcome_message),
)
}
}
@Composable
private fun WelcomeFooter(
onStartClick: () -> Unit,
onImportClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Button(
text = stringResource(id = R.string.onboarding_welcome_start_button),
onClick = onStartClick,
)
ButtonText(
text = stringResource(id = R.string.onboarding_welcome_import_button),
onClick = onImportClick,
)
}
}
@Composable
@DevicePreviews
internal fun OnboardingContentK9Preview() {
K9Theme {
OnboardingContent(
onStartClick = {},
onImportClick = {},
)
}
}
@Composable
@DevicePreviews
internal fun OnboardingContentThunderbirdPreview() {
ThunderbirdTheme {
OnboardingContent(
onStartClick = {},
onImportClick = {},
)
}
}

View file

@ -0,0 +1,24 @@
package net.thunderbird.feature.onboarding
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
@Composable
fun OnboardingScreen(
onStartClick: () -> Unit,
onImportClick: () -> Unit,
) {
OnboardingContent(
onStartClick = onStartClick,
onImportClick = onImportClick,
)
}
@Preview
@Composable
internal fun OnboardingScreenPreview() {
OnboardingScreen(
onStartClick = {},
onImportClick = {},
)
}

View file

@ -0,0 +1,27 @@
package net.thunderbird.feature.onboarding.navigation
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import net.thunderbird.feature.onboarding.OnboardingScreen
const val NAVIGATION_ROUTE_ONBOARDING = "onboarding"
fun NavController.navigateToOnboarding(
navOptions: NavOptions? = null,
) {
navigate(NAVIGATION_ROUTE_ONBOARDING, navOptions)
}
fun NavGraphBuilder.onboardingScreen(
onStartClick: () -> Unit,
onImportClick: () -> Unit,
) {
composable(route = NAVIGATION_ROUTE_ONBOARDING) {
OnboardingScreen(
onStartClick = onStartClick,
onImportClick = onImportClick,
)
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="onboarding_welcome_title">K-9 Mail</string>
<string name="onboarding_welcome_message">Welcome to K-9 Mail, the Android email client designed for enhanced security, easy customization, and seamless management of all your email accounts.</string>
<string name="onboarding_welcome_start_button">Start</string>
<string name="onboarding_welcome_import_button">Import settings</string>
</resources>

View file

@ -83,6 +83,7 @@ androidx-compose-activity = "androidx.activity:activity-compose:1.6.1"
androidx-compose-lifecycle-viewmodel = "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
androidx-compose-material = { module = "androidx.compose.material:material", version.ref = "androidxComposeMaterial" }
androidx-compose-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "androidxComposeMaterial" }
androidx-compose-navigation = { module = "androidx.navigation:navigation-compose", version.ref = "androidxNavigation" }
androidx-test-core = "androidx.test:core:1.5.0"
androidx-test-ext-junit-ktx = "androidx.test.ext:junit-ktx:1.1.5"
androidx-test-espresso-core = "androidx.test.espresso:espresso-core:3.5.1"
@ -154,6 +155,7 @@ shared-jvm-android-compose = [
"androidx-compose-foundation",
"androidx-compose-ui-tooling-preview",
"androidx-compose-lifecycle-viewmodel",
"androidx-compose-navigation",
]
shared-jvm-android-compose-debug = [
"androidx-compose-ui-tooling",

View file

@ -41,6 +41,10 @@ include(
":app:html-cleaner",
)
include(
":feature:onboarding",
)
include(
":core:common",
":core:testing",