Skip to content

Commit

Permalink
Merge pull request thunderbird#8352 from cketti/onboarding_migration
Browse files Browse the repository at this point in the history
Update `TbOnboardingMigrationScreen`
  • Loading branch information
cketti authored Oct 18, 2024
2 parents 6b30503 + 6f7759a commit f33f713
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ import androidx.compose.material3.Card as Material3Card
@Composable
fun CardFilled(
modifier: Modifier = Modifier,
onClick: () -> Unit = {},
content: @Composable ColumnScope.() -> Unit,
) {
Material3Card(
onClick = onClick,
modifier = modifier,
content = content,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.style.LineHeightStyle
import androidx.compose.ui.text.style.TextAlign
import app.k9mail.core.ui.compose.theme2.MainTheme
import androidx.compose.material3.Text as Material3Text
Expand Down Expand Up @@ -39,3 +40,20 @@ fun TextBodyMedium(
style = MainTheme.typography.bodyMedium,
)
}

@Composable
fun TextBodyMedium(
text: String,
lineHeightStyle: LineHeightStyle,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
textAlign: TextAlign? = null,
) {
Material3Text(
text = text,
modifier = modifier,
color = color,
textAlign = textAlign,
style = MainTheme.typography.bodyMedium.copy(lineHeightStyle = lineHeightStyle),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@ fun OnboardingNavHost(

composable(route = NESTED_NAVIGATION_ROUTE_MIGRATION) {
onboardingMigrationManager.OnboardingMigrationScreen(
onQrCodeScanClick = { navController.navigateToSettingsImportQrCode() },
onAddAccountClick = { navController.navigateToAccountSetup() },
onQrCodeScan = { navController.navigateToSettingsImportQrCode() },
onAddAccount = { navController.navigateToAccountSetup() },
onImport = { navController.navigateToSettingsImport() },
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ interface OnboardingMigrationManager {

@Composable
fun OnboardingMigrationScreen(
onQrCodeScanClick: () -> Unit,
onAddAccountClick: () -> Unit,
onQrCodeScan: () -> Unit,
onAddAccount: () -> Unit,
onImport: () -> Unit,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ class NoOpOnboardingMigrationManager : OnboardingMigrationManager {

@Composable
override fun OnboardingMigrationScreen(
onQrCodeScanClick: () -> Unit,
onAddAccountClick: () -> Unit,
onQrCodeScan: () -> Unit,
onAddAccount: () -> Unit,
onImport: () -> Unit,
) = Unit
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ internal fun TbOnboardingMigrationScreenPreview() {
ThunderbirdTheme2 {
Surface {
TbOnboardingMigrationScreen(
onQrCodeScanClick = {},
onAddAccountClick = {},
onQrCodeScan = {},
onAddAccount = {},
onImport = {},
brandNameProvider = object : BrandNameProvider {
override val brandName: String = "Thunderbird"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ class TbOnboardingMigrationManager : OnboardingMigrationManager {

@Composable
override fun OnboardingMigrationScreen(
onQrCodeScanClick: () -> Unit,
onAddAccountClick: () -> Unit,
onQrCodeScan: () -> Unit,
onAddAccount: () -> Unit,
onImport: () -> Unit,
) {
TbOnboardingMigrationScreen(
onQrCodeScanClick,
onAddAccountClick,
onQrCodeScan,
onAddAccount,
onImport,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package app.k9mail.feature.onboarding.migration.thunderbird

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
Expand All @@ -14,20 +15,25 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.LineHeightStyle
import app.k9mail.core.common.provider.BrandNameProvider
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonFilled
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonOutlined
import app.k9mail.core.ui.compose.designsystem.atom.card.CardFilled
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleMedium
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
import app.k9mail.core.ui.compose.theme2.MainTheme
import app.k9mail.feature.account.common.ui.AppTitleTopHeader
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import org.koin.compose.koinInject

@Composable
internal fun TbOnboardingMigrationScreen(
onQrCodeScanClick: () -> Unit,
onAddAccountClick: () -> Unit,
onQrCodeScan: () -> Unit,
onAddAccount: () -> Unit,
onImport: () -> Unit,
modifier: Modifier = Modifier,
brandNameProvider: BrandNameProvider = koinInject(),
) {
Expand All @@ -47,41 +53,73 @@ internal fun TbOnboardingMigrationScreen(
title = brandNameProvider.brandName,
)

Spacer(modifier = Modifier.height(MainTheme.spacings.double))
Spacer(
modifier = Modifier
.height(MainTheme.spacings.double)
.weight(1f),
)

TextCard(title = stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_title)) {
TextBodyMedium(
text = stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_description),
modifier = Modifier
.padding(bottom = MainTheme.spacings.double),
)
AlreadyUsingThunderbirdCard(onQrCodeScan)

ButtonFilled(
text = stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_button_text),
onClick = onQrCodeScanClick,
modifier = Modifier
.testTag("QrCodeImportButton")
.align(Alignment.CenterHorizontally),
Spacer(modifier = Modifier.height(MainTheme.spacings.triple))

TextGroup(title = stringResource(R.string.onboarding_migration_thunderbird_new_account_title)) {
ButtonOutlined(
text = stringResource(R.string.onboarding_migration_thunderbird_new_account_button_text),
onClick = onAddAccount,
modifier = Modifier.testTag("AddAccountButton"),
)
}

Spacer(modifier = Modifier.height(MainTheme.spacings.double))

TextCard(title = stringResource(R.string.onboarding_migration_thunderbird_new_account_title)) {
ButtonFilled(
text = stringResource(R.string.onboarding_migration_thunderbird_new_account_button_text),
onClick = onAddAccountClick,
modifier = Modifier
.testTag("AddAccountButton")
.align(Alignment.CenterHorizontally),
TextGroup(title = stringResource(R.string.onboarding_migration_thunderbird_import_title)) {
ButtonOutlined(
text = stringResource(R.string.onboarding_migration_thunderbird_import_button_text),
onClick = onImport,
modifier = Modifier.testTag("ImportButton"),
)
}

Spacer(modifier = Modifier.height(MainTheme.spacings.double))
Spacer(
modifier = Modifier
.height(MainTheme.spacings.double)
.weight(1f),
)
}
}
}

@Composable
private fun AlreadyUsingThunderbirdCard(onQrCodeScan: () -> Unit) {
TextCard(title = stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_title)) {
TextBodyMedium(
text = stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_text),
modifier = Modifier
.padding(bottom = MainTheme.spacings.double),
)

TextBodyMediumFullLineHeight(
text = stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_instructions_intro),
)

BulletList(
items = persistentListOf(
stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1),
stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2),
),
modifier = Modifier
.padding(bottom = MainTheme.spacings.double),
)

ButtonFilled(
text = stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_button_text),
onClick = onQrCodeScan,
modifier = Modifier
.testTag("QrCodeImportButton")
.align(Alignment.CenterHorizontally),
)
}
}

@Composable
private fun TextCard(
title: String,
Expand All @@ -108,3 +146,53 @@ private fun TextCard(
}
}
}

@Composable
private fun TextGroup(
title: String,
content: @Composable ColumnScope.() -> Unit,
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.padding(MainTheme.spacings.double),
) {
TextTitleMedium(
text = title,
color = MainTheme.colors.primary,
modifier = Modifier
.padding(bottom = MainTheme.spacings.default),
)

content()
}
}

@Composable
private fun BulletList(
items: ImmutableList<String>,
modifier: Modifier = Modifier,
) {
Column(modifier = modifier) {
for (item in items) {
Row {
TextBodyMediumFullLineHeight(text = " \u2022 ")
TextBodyMediumFullLineHeight(text = item)
}
}
}
}

@Composable
private fun TextBodyMediumFullLineHeight(text: String) {
// Disable line height trimming so that the space between TextBodyMediumFullLineHeight instances following each
// other is the same as the space between lines of text inside a single TextBodyMedium.
TextBodyMedium(
text = text,
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Proportional,
trim = LineHeightStyle.Trim.None,
),
)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Already using Thunderbird on desktop?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_description">You can easily import your account settings.\n\nIn your Thunderbird desktop client, go to the top menu bar, click on ‘Settings’, and select ‘Export for Mobile’.\n\nA new tab with QR codes will appear. Use your Android device to scan the codes.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Easily import your account settings by scanning a QR code.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">In Thunderbird desktop, go to:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">‘Settings’ in the Spaces Toolbar (bottom left)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2">Select ‘Export to Mobile’ and follow the instructions</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Import settings</string>
<string name="onboarding_migration_thunderbird_new_account_title">New to Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Add an email account now</string>
<string name="onboarding_migration_thunderbird_import_title">Moving from another app or device?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Import your account settings now</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import org.junit.Test

class TbOnboardingMigrationScreenKtTest : ComposeTest() {
@Test
fun `pressing QrCodeImportButton should call onQrCodeScanClick`() = runComposeTest {
fun `pressing QrCodeImportButton should call onQrCodeScan`() = runComposeTest {
var qrCodeScanClickCounter = 0
var addAccountClickCounter = 0
setContentWithTheme {
TbOnboardingMigrationScreen(
onQrCodeScanClick = { qrCodeScanClickCounter++ },
onAddAccountClick = { addAccountClickCounter++ },
onQrCodeScan = { qrCodeScanClickCounter++ },
onAddAccount = { error("Should not be called") },
onImport = { error("Should not be called") },
brandNameProvider = FakeBrandNameProvider,
)
}
Expand All @@ -28,17 +28,16 @@ class TbOnboardingMigrationScreenKtTest : ComposeTest() {
.performClick()

assertThat(qrCodeScanClickCounter).isEqualTo(1)
assertThat(addAccountClickCounter).isEqualTo(0)
}

@Test
fun `pressing AddAccountButton button should call onAddAccountClick`() = runComposeTest {
var qrCodeScanClickCounter = 0
fun `pressing AddAccountButton button should call onAddAccount`() = runComposeTest {
var addAccountClickCounter = 0
setContentWithTheme {
TbOnboardingMigrationScreen(
onQrCodeScanClick = { qrCodeScanClickCounter++ },
onAddAccountClick = { addAccountClickCounter++ },
onQrCodeScan = { error("Should not be called") },
onAddAccount = { addAccountClickCounter++ },
onImport = { error("Should not be called") },
brandNameProvider = FakeBrandNameProvider,
)
}
Expand All @@ -48,7 +47,25 @@ class TbOnboardingMigrationScreenKtTest : ComposeTest() {
.performClick()

assertThat(addAccountClickCounter).isEqualTo(1)
assertThat(qrCodeScanClickCounter).isEqualTo(0)
}

@Test
fun `pressing ImportButton button should call onImport`() = runComposeTest {
var importClickCounter = 0
setContentWithTheme {
TbOnboardingMigrationScreen(
onQrCodeScan = { error("Should not be called") },
onAddAccount = { error("Should not be called") },
onImport = { importClickCounter++ },
brandNameProvider = FakeBrandNameProvider,
)
}

composeTestRule.onNodeWithTag("ImportButton")
.performScrollTo()
.performClick()

assertThat(importClickCounter).isEqualTo(1)
}
}

Expand Down

0 comments on commit f33f713

Please sign in to comment.