Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 13:56:56 +01:00
parent 75dc487a7a
commit 39c29d175b
6317 changed files with 388324 additions and 2 deletions

View file

@ -0,0 +1,19 @@
plugins {
id(ThunderbirdPlugins.Library.androidCompose)
}
android {
namespace = "app.k9mail.feature.onboarding.main"
resourcePrefix = "onboarding_main_"
}
dependencies {
implementation(projects.core.common)
implementation(projects.core.ui.compose.designsystem)
implementation(projects.core.ui.compose.navigation)
implementation(projects.feature.onboarding.welcome)
implementation(projects.feature.account.setup)
implementation(projects.feature.settings.import)
implementation(projects.feature.onboarding.permissions)
implementation(projects.feature.onboarding.migration.api)
}

View file

@ -0,0 +1,15 @@
package app.k9mail.feature.onboarding.main
import app.k9mail.feature.onboarding.main.navigation.DefaultOnboardingNavigation
import app.k9mail.feature.onboarding.main.navigation.OnboardingNavigation
import app.k9mail.feature.onboarding.permissions.featureOnboardingPermissionsModule
import org.koin.core.module.Module
import org.koin.dsl.module
val featureOnboardingModule: Module = module {
single<OnboardingNavigation> { DefaultOnboardingNavigation() }
includes(
featureOnboardingPermissionsModule,
)
}

View file

@ -0,0 +1,21 @@
package app.k9mail.feature.onboarding.main.navigation
import androidx.navigation.NavGraphBuilder
import app.k9mail.core.ui.compose.navigation.deepLinkComposable
import app.k9mail.feature.onboarding.main.navigation.OnboardingRoute.Onboarding
class DefaultOnboardingNavigation : OnboardingNavigation {
override fun registerRoutes(
navGraphBuilder: NavGraphBuilder,
onBack: () -> Unit,
onFinish: (OnboardingRoute) -> Unit,
) {
with(navGraphBuilder) {
deepLinkComposable<Onboarding>(Onboarding.BASE_PATH) {
OnboardingNavHost(
onFinish = onFinish,
)
}
}
}
}

View file

@ -0,0 +1,139 @@
package app.k9mail.feature.onboarding.main.navigation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.navigation.NavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import app.k9mail.feature.account.setup.navigation.AccountSetupNavHost
import app.k9mail.feature.account.setup.navigation.AccountSetupRoute
import app.k9mail.feature.onboarding.migration.api.OnboardingMigrationManager
import app.k9mail.feature.onboarding.permissions.domain.PermissionsDomainContract.UseCase.HasRuntimePermissions
import app.k9mail.feature.onboarding.permissions.ui.PermissionsScreen
import app.k9mail.feature.onboarding.welcome.ui.WelcomeScreen
import app.k9mail.feature.settings.import.ui.SettingsImportAction
import app.k9mail.feature.settings.import.ui.SettingsImportScreen
import org.koin.compose.koinInject
private const val NESTED_NAVIGATION_ROUTE_WELCOME = "welcome"
private const val NESTED_NAVIGATION_ROUTE_MIGRATION = "migration"
private const val NESTED_NAVIGATION_ROUTE_ACCOUNT_SETUP = "account_setup"
private const val NESTED_NAVIGATION_ROUTE_SETTINGS_IMPORT = "settings_import"
private const val NESTED_NAVIGATION_ROUTE_SETTINGS_IMPORT_QR_CODE = "settings_import_qr_code"
private const val NESTED_NAVIGATION_ROUTE_PERMISSIONS = "permissions"
private fun NavController.navigateToMigration() {
navigate(NESTED_NAVIGATION_ROUTE_MIGRATION)
}
private fun NavController.navigateToAccountSetup() {
navigate(NESTED_NAVIGATION_ROUTE_ACCOUNT_SETUP)
}
private fun NavController.navigateToSettingsImport() {
navigate(NESTED_NAVIGATION_ROUTE_SETTINGS_IMPORT)
}
private fun NavController.navigateToSettingsImportQrCode() {
navigate(NESTED_NAVIGATION_ROUTE_SETTINGS_IMPORT_QR_CODE)
}
private fun NavController.navigateToPermissions() {
navigate(NESTED_NAVIGATION_ROUTE_PERMISSIONS) {
popUpTo(NESTED_NAVIGATION_ROUTE_WELCOME) {
inclusive = true
}
}
}
@Suppress("LongMethod")
@Composable
fun OnboardingNavHost(
onFinish: (OnboardingRoute) -> Unit,
hasRuntimePermissions: HasRuntimePermissions = koinInject(),
onboardingMigrationManager: OnboardingMigrationManager = koinInject(),
) {
val navController = rememberNavController()
var accountUuid by rememberSaveable { mutableStateOf<String?>(null) }
fun onImportSuccess() {
if (hasRuntimePermissions()) {
navController.navigateToPermissions()
} else {
onFinish(OnboardingRoute.Onboarding(null))
}
}
NavHost(
navController = navController,
startDestination = NESTED_NAVIGATION_ROUTE_WELCOME,
) {
composable(route = NESTED_NAVIGATION_ROUTE_WELCOME) {
WelcomeScreen(
onStartClick = {
if (onboardingMigrationManager.isFeatureIncluded()) {
navController.navigateToMigration()
} else {
navController.navigateToAccountSetup()
}
},
onImportClick = { navController.navigateToSettingsImport() },
appNameProvider = koinInject(),
onboardingMigrationManager = koinInject(),
)
}
composable(route = NESTED_NAVIGATION_ROUTE_MIGRATION) {
onboardingMigrationManager.OnboardingMigrationScreen(
onQrCodeScan = { navController.navigateToSettingsImportQrCode() },
onAddAccount = { navController.navigateToAccountSetup() },
onImport = { navController.navigateToSettingsImport() },
)
}
composable(route = NESTED_NAVIGATION_ROUTE_ACCOUNT_SETUP) {
AccountSetupNavHost(
onBack = { navController.popBackStack() },
onFinish = { route: AccountSetupRoute ->
when (route) {
is AccountSetupRoute.AccountSetup -> {
val createdAccountUuid = route.accountId
accountUuid = createdAccountUuid
if (hasRuntimePermissions()) {
navController.navigateToPermissions()
} else {
onFinish(OnboardingRoute.Onboarding(createdAccountUuid))
}
}
}
},
)
}
composable(route = NESTED_NAVIGATION_ROUTE_SETTINGS_IMPORT) {
SettingsImportScreen(
action = SettingsImportAction.Overview,
onImportSuccess = ::onImportSuccess,
onBack = { navController.popBackStack() },
)
}
composable(route = NESTED_NAVIGATION_ROUTE_SETTINGS_IMPORT_QR_CODE) {
SettingsImportScreen(
action = SettingsImportAction.ScanQrCode,
onImportSuccess = ::onImportSuccess,
onBack = { navController.popBackStack() },
)
}
composable(route = NESTED_NAVIGATION_ROUTE_PERMISSIONS) {
PermissionsScreen(
onNext = { onFinish(OnboardingRoute.Onboarding(accountUuid)) },
)
}
}
}

View file

@ -0,0 +1,5 @@
package app.k9mail.feature.onboarding.main.navigation
import app.k9mail.core.ui.compose.navigation.Navigation
interface OnboardingNavigation : Navigation<OnboardingRoute>

View file

@ -0,0 +1,24 @@
package app.k9mail.feature.onboarding.main.navigation
import app.k9mail.core.ui.compose.navigation.Route
import kotlinx.serialization.Serializable
interface OnboardingRoute : Route {
@Serializable
data class Onboarding(
val accountId: String? = null,
) : OnboardingRoute {
override val basePath: String = BASE_PATH
override fun route(): String = basePath
companion object {
const val BASE_PATH = ONBOARDING_BASE_PATH
}
}
companion object {
const val ONBOARDING_BASE_PATH = "app://onboarding"
}
}

View file

@ -0,0 +1,13 @@
plugins {
id(ThunderbirdPlugins.Library.androidCompose)
alias(libs.plugins.kotlin.serialization)
}
android {
namespace = "app.k9mail.feature.onboarding.migration.api"
resourcePrefix = "onboarding_migration_api_"
}
dependencies {
api(projects.core.ui.compose.navigation)
}

View file

@ -0,0 +1,14 @@
package app.k9mail.feature.onboarding.migration.api
import androidx.compose.runtime.Composable
interface OnboardingMigrationManager {
fun isFeatureIncluded(): Boolean
@Composable
fun OnboardingMigrationScreen(
onQrCodeScan: () -> Unit,
onAddAccount: () -> Unit,
onImport: () -> Unit,
)
}

View file

@ -0,0 +1,12 @@
plugins {
id(ThunderbirdPlugins.Library.androidCompose)
}
android {
namespace = "app.k9mail.feature.onboarding.migration.noop"
resourcePrefix = "onboarding_migration_noop_"
}
dependencies {
api(projects.feature.onboarding.migration.api)
}

View file

@ -0,0 +1,10 @@
package app.k9mail.feature.onboarding.migration
import app.k9mail.feature.onboarding.migration.api.OnboardingMigrationManager
import app.k9mail.feature.onboarding.migration.noop.NoOpOnboardingMigrationManager
import org.koin.core.module.Module
import org.koin.dsl.module
val onboardingMigrationModule: Module = module {
single<OnboardingMigrationManager> { NoOpOnboardingMigrationManager() }
}

View file

@ -0,0 +1,15 @@
package app.k9mail.feature.onboarding.migration.noop
import androidx.compose.runtime.Composable
import app.k9mail.feature.onboarding.migration.api.OnboardingMigrationManager
class NoOpOnboardingMigrationManager : OnboardingMigrationManager {
override fun isFeatureIncluded(): Boolean = false
@Composable
override fun OnboardingMigrationScreen(
onQrCodeScan: () -> Unit,
onAddAccount: () -> Unit,
onImport: () -> Unit,
) = Unit
}

View file

@ -0,0 +1,18 @@
plugins {
id(ThunderbirdPlugins.Library.androidCompose)
}
android {
namespace = "app.k9mail.feature.onboarding.migration.thunderbird"
resourcePrefix = "onboarding_migration_thunderbird_"
}
dependencies {
api(projects.feature.onboarding.migration.api)
implementation(projects.core.common)
implementation(projects.core.logging.implLegacy)
implementation(projects.core.ui.compose.designsystem)
implementation(projects.feature.account.common)
testImplementation(projects.core.ui.compose.testing)
}

View file

@ -0,0 +1,24 @@
package app.k9mail.feature.onboarding.migration.thunderbird
import androidx.compose.runtime.Composable
import app.k9mail.core.ui.compose.common.annotation.PreviewDevices
import app.k9mail.core.ui.compose.designsystem.atom.Surface
import app.k9mail.core.ui.compose.theme2.thunderbird.ThunderbirdTheme2
import net.thunderbird.core.common.provider.BrandNameProvider
@Composable
@PreviewDevices
internal fun TbOnboardingMigrationScreenPreview() {
ThunderbirdTheme2 {
Surface {
TbOnboardingMigrationScreen(
onQrCodeScan = {},
onAddAccount = {},
onImport = {},
brandNameProvider = object : BrandNameProvider {
override val brandName: String = "Thunderbird"
},
)
}
}
}

View file

@ -0,0 +1,10 @@
package app.k9mail.feature.onboarding.migration
import app.k9mail.feature.onboarding.migration.api.OnboardingMigrationManager
import app.k9mail.feature.onboarding.migration.thunderbird.TbOnboardingMigrationManager
import org.koin.core.module.Module
import org.koin.dsl.module
val onboardingMigrationModule: Module = module {
single<OnboardingMigrationManager> { TbOnboardingMigrationManager() }
}

View file

@ -0,0 +1,21 @@
package app.k9mail.feature.onboarding.migration.thunderbird
import androidx.compose.runtime.Composable
import app.k9mail.feature.onboarding.migration.api.OnboardingMigrationManager
class TbOnboardingMigrationManager : OnboardingMigrationManager {
override fun isFeatureIncluded(): Boolean = true
@Composable
override fun OnboardingMigrationScreen(
onQrCodeScan: () -> Unit,
onAddAccount: () -> Unit,
onImport: () -> Unit,
) {
TbOnboardingMigrationScreen(
onQrCodeScan,
onAddAccount,
onImport,
)
}
}

View file

@ -0,0 +1,280 @@
package app.k9mail.feature.onboarding.migration.thunderbird
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
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
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
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.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextDecoration
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.TextBodySmall
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 net.thunderbird.core.common.provider.BrandNameProvider
import net.thunderbird.core.logging.legacy.Log
import net.thunderbird.core.ui.compose.common.modifier.testTagAsResourceId
import org.koin.compose.koinInject
@Composable
internal fun TbOnboardingMigrationScreen(
onQrCodeScan: () -> Unit,
onAddAccount: () -> Unit,
onImport: () -> Unit,
modifier: Modifier = Modifier,
brandNameProvider: BrandNameProvider = koinInject(),
) {
val scrollState = rememberScrollState()
ResponsiveWidthContainer(
modifier = Modifier
.fillMaxSize()
.then(modifier),
) { contentPadding ->
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(scrollState)
.padding(contentPadding),
) {
AppTitleTopHeader(
title = brandNameProvider.brandName,
)
Spacer(
modifier = Modifier
.height(MainTheme.spacings.double)
.weight(1f),
)
AlreadyUsingThunderbirdCard(onQrCodeScan)
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.testTagAsResourceId("onboarding_migration_new_account_button"),
)
}
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.testTagAsResourceId("ImportButton"),
)
}
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),
)
TextBodyMedium(
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_v2),
),
modifier = Modifier
.padding(
top = MainTheme.spacings.half,
bottom = MainTheme.spacings.double,
),
)
ButtonFilled(
text = stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_button_text),
onClick = onQrCodeScan,
modifier = Modifier
.testTagAsResourceId("QrCodeImportButton")
.align(Alignment.CenterHorizontally),
)
ThunderbirdVersionNote(
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(top = MainTheme.spacings.half),
)
}
}
@Composable
private fun ThunderbirdVersionNote(
modifier: Modifier = Modifier,
) {
val formatString = if (LocalInspectionMode.current) {
// When called from Android Studio previews, stringResource() replaces format string placeholders. We work
// around that by using a static string.
"Import requires the latest version of Thunderbird Desktop 128. %s"
} else {
stringResource(R.string.onboarding_migration_thunderbird_qr_code_import_instructions_require_latest)
}
val context = LocalContext.current
Box(
modifier = modifier
.clip(MainTheme.shapes.small)
.clickable { context.launchLearnHowToUpdateThunderbird() }
.semantics { role = Role.Button }
.padding(MainTheme.spacings.double),
) {
check("%s" in formatString) { "Placeholder needs to be exactly %s" }
val prefix = formatString.substringBefore("%s")
val suffix = formatString.substringAfter("%s")
val text = buildAnnotatedString {
val linkText = AnnotatedString(
text = stringResource(
R.string.onboarding_migration_thunderbird_qr_code_import_instructions_learn_update,
),
spanStyle = SpanStyle(
color = MainTheme.colors.primary,
textDecoration = TextDecoration.Underline,
),
)
append(prefix)
append(linkText)
append(suffix)
}
TextBodySmall(text)
}
}
@Composable
private fun TextCard(
title: String,
content: @Composable ColumnScope.() -> Unit,
) {
CardFilled(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = MainTheme.spacings.quadruple),
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(MainTheme.spacings.double),
) {
TextTitleMedium(
text = title,
color = MainTheme.colors.primary,
modifier = Modifier
.padding(bottom = MainTheme.spacings.double),
)
content()
}
}
}
@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,
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.half),
) {
for (item in items) {
Row {
TextBodyMedium(text = " \u2022 ")
TextBodyMedium(text = item)
}
}
}
}
private fun Context.launchLearnHowToUpdateThunderbird() {
try {
val url = getString(R.string.onboarding_migration_thunderbird_update_thunderbird_url)
val viewIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(viewIntent)
} catch (e: ActivityNotFoundException) {
Log.d(e, "Failed to open URL")
Toast.makeText(
this,
getString(R.string.onboarding_migration_thunderbird_link_open_error),
Toast.LENGTH_SHORT,
).show()
}
}

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">هل تستخدمُ ثَندَربِرْد على الحاسوب؟</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">استورد إعدادات حسابك بسهولة عن طريق مسح رمز الاستجابة السريعة ضوئياً.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">في ثندربرد للحاسوب، انتقل إلى:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">’الإعدادات‘ في شريط المساحات (أسفل اليسار)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">حدد\'تصدير إلى الهاتف\'</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">يتطلب الاستيراد أحدث إصدار من سطح المكتب 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">تعرّف على كيفية تحديث ثندربرد.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">استيراد الإعدادات</string>
<string name="onboarding_migration_thunderbird_new_account_title">جديد على ثندربرد؟</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">إضافة حساب بريدي الآن</string>
<string name="onboarding_migration_thunderbird_import_title">الانتقال من تطبيق أو جهاز آخر؟</string>
<string name="onboarding_migration_thunderbird_import_button_text">استيراد إعدادات حسابك الآن</string>
<string name="onboarding_migration_thunderbird_link_open_error">لم يتم العثور على تطبيق لفتح الرابط.</string>
</resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Ужо карыстаецеся Thunderbird на камп\'ютэры?</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Вече използвате Thunderbird на компютър?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Лесно вмъкване на настройките на профила си, чрез сканиране на QR код.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">В настолната версия на Thuderbird, отидете до:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Изберете \"Изнасяне към мобилното приложение\"</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Научете как да осъвременявате Thunderbird.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Процеса по внасяне изисква послено издание на Thunderbird 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Внасяне на настройките</string>
<string name="onboarding_migration_thunderbird_new_account_title">Нов потребител на Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Добавяне на имейл профил</string>
<string name="onboarding_migration_thunderbird_import_title">Преминавате ли от друго устройство?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Внасяне на настройките на профила</string>
<string name="onboarding_migration_thunderbird_link_open_error">Не е намерено приложение за отваряне на връзката.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">„Настройки“ в лентата с инструменти на Spaces (в долния ляв ъгъл)</string>
</resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Ja feu servir el Thunderbird a l\'escriptori?</string>
<string name="onboarding_migration_thunderbird_new_account_title">És el primer cop que useu el Thunderbird?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importa la configuració</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">A la versió d\'escriptori del Thunderbird, aneu a:</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Afegeix un compte de correu electrònic ara</string>
<string name="onboarding_migration_thunderbird_import_title">Veniu d\'una altra aplicació o dispositiu?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importeu fàcilment la configuració del vostre compte escanejant un codi QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">«Configuració» a la barra d\'eines (a baix a l\'esquerra)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Selecciona «Exporta al mòbil»</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">La importació requereix la darrera versió del Thunderbird 128 per a l\'escriptori. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Apreneu a actualitzar el Thunderbird.</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importeu la vostra configuració del compte</string>
<string name="onboarding_migration_thunderbird_link_open_error">No s\'ha trobat cap aplicació per obrir l\'enllaç.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Impiegate dighjà Thunderbird nantà lurdinatore ?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Impurtà i parametri</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Impurtate in quattru è trè sette i vostri parametri di conti analizendu un codice QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">« Parametri » in a barra dattrezzi di i spazii (in bassu è à manca)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">In Thunderbird nantà lurdinatore, andà à :</string>
<string name="onboarding_migration_thunderbird_new_account_title">Principiante nantà Thunderbird ?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Aghjunghje subitu un contu di messaghjeria</string>
<string name="onboarding_migration_thunderbird_import_title">Venite da unaltra appiecazione o da un altru apparechju ?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Impurtà subitu i vostri parametri di conti</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Selezziunate « Espurtà versu u mobile »</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Limpurtazione richiede lultima versione 128 di Thunderbird per lurdinatore. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Scuprite cumu mette Thunderbird à livellu.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Nisuna appiecazione hè stata trova per apre u liame.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_new_account_title">Používáte Thunderbird poprvé?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Přidat e-mailový účet</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Používáte Thunderbird na počítači?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importovat nastavení</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">V Thunderbirdu na počítači přejděte do:</string>
<string name="onboarding_migration_thunderbird_import_title">Přecházíte z jiné aplikace nebo zařízení?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">„Nastavení“ v navigační liště (vlevo dole)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Jednoduše importujte nastavení svého účtu naskenováním QR kódu.</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importujte nastavení svého účtu</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Zvolte „Export pro mobilní zařízení“</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Importování vyžaduje nejnovější verzi Thunderbirdu 128 pro počítač. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Zjistěte, jak aktualizovat Thunderbird.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Nenalezena aplikace k otevření odkazu.</string>
</resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Nutzt du bereits Thunderbird auf dem Desktop?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Einstellungen importieren</string>
<string name="onboarding_migration_thunderbird_new_account_title">Neu bei Thunderbird?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importiere deine Kontoeinstellungen ganz einfach durch Scannen eines QR-Codes.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Gehe im Thunderbird Desktop zu:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\'Einstellungen\' in der Spaces-Symbolleiste (unten links)</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Jetzt ein E-Mail-Konto hinzufügen</string>
<string name="onboarding_migration_thunderbird_import_title">Von einer anderen App oder einem anderen Gerät übertragen?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Kontoeinstellungen jetzt importieren</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Wähle \'Auf Mobilgerät exportieren\'</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Der Import erfordert die neueste Version von Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Erfahre, wie du Thunderbird aktualisieren kannst.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Keine App zum Öffnen des Links gefunden.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_new_account_title">Νέος χρήστης του Thunderbird;</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Προσθήκη λογαριασμού email</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Εισαγάγετε εύκολα τις ρυθμίσεις του λογαριασμού σας σαρώνοντας έναν κωδικό QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Στο Thunderbird για υπολογιστές, μεταβείτε στις:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">«Ρυθμίσεις» από τη γραμμή χώρων (κάτω αριστερά)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Επιλέξτε «Εξαγωγή σε κινητή συσκευή»</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Η εισαγωγή απαιτεί την πιο πρόσφατη έκδοση του Thunderbird 128 για υπολογιστές. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Μάθετε πώς να ενημερώσετε το Thunderbird.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Eισαγωγή ρυθμίσεων</string>
<string name="onboarding_migration_thunderbird_import_title">Έρχεστε από άλλη εφαρμογή ή συσκευή;</string>
<string name="onboarding_migration_thunderbird_import_button_text">Εισάγετε τις ρυθμίσεις του λογαριασμού σας τώρα</string>
<string name="onboarding_migration_thunderbird_link_open_error">Δεν βρέθηκε εφαρμογή για το άνοιγμα του συνδέσμου.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Χρησιμοποιείτε ήδη το Thunderbird για υπολογιστές;</string>
</resources>

View file

@ -0,0 +1,5 @@
<?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_text">Easily import your account settings by scanning a QR code.</string>
</resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">¿Ya utilizas Thunderbird para equipos de escritorio?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importar ajustes</string>
<string name="onboarding_migration_thunderbird_new_account_title">¿Es la primera vez que usas Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Añade una cuenta de correo</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Puedes importar fácilmente tus cuentas de correo escaneando un código QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">En la versión de escritorio de Thunderbird ve a:</string>
<string name="onboarding_migration_thunderbird_import_title">¿Vienes de otra aplicación o dispositivo?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Puedes traer tus cuentas de correo de otros sitios</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">«Ajustes» en la barra de herramientas abajo a la izquierda</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Elige «Exportar a móvil»</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">La importación requiere la última versión de Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Aprende a actualizar Thunderbird.</string>
<string name="onboarding_migration_thunderbird_link_open_error">No se ha encontrado ninguna aplicación para abrir el enlace.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Kas sa juba kasutad Thunderbirdi oma arvutis?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Impordi seadistused</string>
<string name="onboarding_migration_thunderbird_new_account_title">Thunderbird on sinu jaoks uus rakendus?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Lisa e-posti konto nüüd</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Impordi mugavalt oma kontoseadistused QR-koodi skaneerimise abil.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Ava Thunderbird oma laua- või sülearvutis ning ava:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">tööriistaribalt „Seadistused“ (all vasakul)</string>
<string name="onboarding_migration_thunderbird_import_title">Oled hoopis kolimas muust rakendusest või seadmest?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Impordi oma kontoseadistused nüüd</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Vali „Ekspordi nutiseadmesse“</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Importimine eeldab viimase Thunderbirdi arvutiversiooni (128) kasutamist. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Lisateave Thunderbirdi uuendamise kohta.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Lingi avamiseks ei leidu rakendusi.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Mahaigainekoan Thunderbird erabiltzen duzu dagoeneko?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Inportatu ezarpenak</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Gehitu email kontua orain</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Mahaigaineko Tunderbirden, zoaz hona:</string>
<string name="onboarding_migration_thunderbird_import_button_text">Inportatu zure kontuaren ezarpenak orain</string>
<string name="onboarding_migration_thunderbird_new_account_title">Berria Thunderbird-en?</string>
<string name="onboarding_migration_thunderbird_import_title">Beste aplikazio edo gailu batetik mugitzen ari zara?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Erraz inportatu zure kontuaren ezarpenak QR kode bat eskaneatuz.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\"Ezarpenak\" tresna-barran (behean ezkerrean)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Ikasi nola eguneratu Thunderbird.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Ez da aurkitu aplikaziorik lotura irekitzeko.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Hautatu \"Mugikorrera esportatu\"</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Inportatzeko mahaigaineko Thunderbird 128ko azken bertsioa behar da <xliff:g id="link_text">%s</xliff:g></string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">درون‌ریزی تنظیمات</string>
<string name="onboarding_migration_thunderbird_new_account_title">کاربر جدید تاندربرد؟</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">افزودن حساب رایانامه</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">استفادهٔ پیشین از تاندربر روی میزکار؟</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">در تاندربرد میزکار، رفتن به:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">«تنظیمات» در نوار ابزار فضاها (پایین سمت راست)</string>
<string name="onboarding_migration_thunderbird_import_title">جابه‌جایی از برنامه یا دستگاهی دیگر؟</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">درون‌ریزی آسان تنظیمات حسابتان با پویش رمزینه.</string>
<string name="onboarding_migration_thunderbird_import_button_text">درون‌ریزی تنظیمات حسابتان</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">چگونگی به‌روزرسانی تاندربرد را بیاموزید.</string>
<string name="onboarding_migration_thunderbird_link_open_error">هیچ برنامه‌ای برای باز کردن پیوند یافت نشد.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">گزینه \"Export to Mobile\" را انتخاب کنید</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">وارد کردن، به آخرین نسخه تاندربرد نیازمند است. <xliff:g id="link_text">%s</xliff:g></string>
</resources>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Käytätkö Thunderbirdiä jo tietokoneella?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Tuo asetukset</string>
<string name="onboarding_migration_thunderbird_new_account_title">Onko Thunderbird uusi tuttavuus sinulle?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Tuo tilisi asetukset vaivatta skannaamalla QR-koodi.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Mene Thunderbirdin tietokonesovelluksella:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">Asetukset Tilat-työkalupalkissa (vasen alareuna)</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Lisää sähköpostitili nyt</string>
<string name="onboarding_migration_thunderbird_import_title">Siirtymässä toisesta sovelluksesta tai laitteelta?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Tuo tilin asetukset nyt</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Utilisez-vous déjà Thunderbird pour ordinateur?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Ajoutez un compte de courriel maintenant</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importez facilement les paramètres de votre compte en balayant un code QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Dans Thunderbird pour ordinateur, accédez à :</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">« Paramètres » dans la barre doutils Espaces (en bas à gauche)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importer les paramètres</string>
<string name="onboarding_migration_thunderbird_new_account_title">Première fois sur Thunderbird?</string>
<string name="onboarding_migration_thunderbird_import_title">Passez-vous dune autre appli ou dun autre appareil à Thunderbird pour Android?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importez les paramètres de votre compte maintenant</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">La dernière version de Thunderbird pour ordinateur 128 est nécessaire à limportation. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Choisissez « Exporter pour mobile »</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Découvrir comment mettre Thunderbird à jour.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Aucune appli na été trouvée pour ouvrir le lien.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Ymportynstellingen</string>
<string name="onboarding_migration_thunderbird_new_account_title">Nij by Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Foegje no in e-mailaccount ta</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Brûke jo Thunderbird al op de desktop?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Gean yn Thunderbird op de desktop nei:</string>
<string name="onboarding_migration_thunderbird_import_title">Brûke jo in oare app of in oar apparaat?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Jo accountynstellingen no ymportearje</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Ymportearje ienfâldich jo accountynstellingen troch in QR-koade te scannen.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">Ynstellingen yn de Taakbalke (linksûnder)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Mear ynfo oer it bywurkjen fan Thunderbird.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Selektearje Eksportearje foar mobyl</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Foar ymportearjen is de nijste ferzje fan Thunderbird Desktop 128 fereaske. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_link_open_error">Gjin app fûn om de keppeling te iepenjen.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">An bhfuil Thunderbird in úsáid agat ar an deasc cheana féin?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Socruithe a allmhairiú</string>
<string name="onboarding_migration_thunderbird_new_account_title">Nua do Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Cuir cuntas ríomhphoist leis anois</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Iompórtáil do shocruithe cuntais go héasca trí chód QR a scanadh.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">I deasc Thunderbird, téigh chuig:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">Socruithe sa Bharra Uirlisí Spáis (bun ar chlé)</string>
<string name="onboarding_migration_thunderbird_import_title">Ag bogadh ó aip nó gléas eile?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Iompórtáil do shocruithe cuntais anois</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Roghnaigh Easpórtáil go Soghluaiste</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Teastaíonn an leagan is déanaí de Thunderbird Desktop 128 le hiompórtáil. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Foghlaim conas Thunderbird a nuashonrú.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Níor aimsíodh aon aip chun an nasc a oscailt.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">An cleachd thu Thunderbird air an desktop agad mu thràth?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Ann an Thunderbird desktop, tadhail air:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">“Roghainnean” air bàr-inneal Spaces (air an taobh chlì aig a bhonn)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Cha leig thu leas ach còd QR a sganadh airson roghainnean a chunntais agad ion-phortadh.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Tagh “Às-phortaich gu uidheam mobile”</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Ion-phortaichidh seo an tionndadh as ùire dhe Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Fiosraich mar a dhùraicheas tu Thunderbird.</string>
<string name="onboarding_migration_thunderbird_new_account_title">Air ùr-thighinn gu Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Cuir cunntas puist-d ris an-dràsta</string>
<string name="onboarding_migration_thunderbird_import_title">Airson a ghluasad o aplacaid no uidheam eile?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Ion-phortaich roghainnean a chunntais agad an-dràsta</string>
<string name="onboarding_migration_thunderbird_link_open_error">Cha dfhuair sinn lorg air aplacaid a dhfhosgladh an ceangal.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Ion-phortaich na roghainnean</string>
</resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Már használja az asztali Thunderbirdöt?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Beállítások importálása</string>
<string name="onboarding_migration_thunderbird_new_account_title">Új Thunderbird-felhasználó?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Válassza az „Exportálás mobilra” lehetőséget</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importálja a fiókjait könnyedén egy QR-kód leolvasásával.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Az asztali Thunderbirdben ugorjon ide:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">„Beállítások” a Helyek eszköztárban (bal lent)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Az importáláshoz az asztali Thunderbird 128-as verziója szükséges. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Tudja meg hogyan frissítse a Thunderbirdöt.</string>
<string name="onboarding_migration_thunderbird_import_title">Egy másik alkalmazásból vagy eszközről költözik át?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">E-mail-fiók hozzáadása most</string>
<string name="onboarding_migration_thunderbird_import_button_text">A fiókbeállítások importálása most</string>
<string name="onboarding_migration_thunderbird_link_open_error">Nem található alkalmazás a hivatkozás megnyitásához.</string>
</resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Sudah menggunakan Thunderbird di komputer/laptop?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Impor pengaturan</string>
<string name="onboarding_migration_thunderbird_new_account_title">Baru mengenal Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Tambahkan akun surel sekarang</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Impor pengaturan akun Anda dengan mudah dengan memindai kode Respons Cepat (QR).</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Di Thunderbird laptop/komputer, buka:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\'Pengaturan\' di Toolbar Spaces (kiri bawah)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Pilih \'Ekspor ke Seluler\'</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Pelajari cara memutakhirkan Thunderbird.</string>
<string name="onboarding_migration_thunderbird_import_title">Pindah dari aplikasi atau perangkat lain?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Impor pengaturan akun Anda sekarang</string>
<string name="onboarding_migration_thunderbird_link_open_error">Aplikasi untuk membuka tautan tidak ditemukan.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Pengimpiran memerlukan versi termutakhir Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Þegar að nota Thunderbird á vinnutölvu?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Flytja inn stillingar</string>
<string name="onboarding_migration_thunderbird_new_account_title">Nýr í Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Útbúðu núna tölvupóstreikning</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Flyttu inn stillingar notandaaðgangsins þíns með því að skanna QR-kóða.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Í Thunderbird fyrir borðtölvur skaltu fara í:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Lærðu hvernig á að uppfæra Thunderbird.</string>
<string name="onboarding_migration_thunderbird_import_title">Ertu að flytja frá öðru forriti eða tæki?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Veldu \'Flytja út í farsíma</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Innflutningur krefst nýjustu útgáfunnar af Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_import_button_text">Flyttu núna inn stillingar notandaaðgangsins þíns</string>
<string name="onboarding_migration_thunderbird_link_open_error">Ekkert forrit fannst til að opna tengilinn.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">Stillingar í svæðastikunni (neðst til hægri)</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Usi Thunderbird sul pc?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importa impostazioni</string>
<string name="onboarding_migration_thunderbird_new_account_title">Nuovo su Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Aggiungi ora un account email</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Sull\'app desktop Thunderbird, vai su:</string>
<string name="onboarding_migration_thunderbird_import_title">Provieni da un\'altra app o dispositivo?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importa ora le impostazioni</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\'Impostazioni\' nella barra degli spazi (in basso a sinistra)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importa facilmente le tue impostazioni scansionando il QRcode.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Seleziona \"Esporta sul telefono\"</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">L\'importazione richiede l\'ultima versione di Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Come aggiornare Thunderbird.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Nessuna app trovata per aprire il link</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">כבר משתמש בת\'אנדרבירד למחשב?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">יבא הגדרות</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">הוסף חשבון דוא\"ל עכשיו</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">בת\'אנדרבירד למחשב, לך אל:</string>
<string name="onboarding_migration_thunderbird_new_account_title">חדש בת\'אנדרבירד?</string>
<string name="onboarding_migration_thunderbird_import_title">עובר מיישום או מכשיר אחר?</string>
<string name="onboarding_migration_thunderbird_import_button_text">יבא את הגדרות החשבון שלך עכשיו</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">יבא בקלות את הגדרות החשבון שלך ע\"י סריקת ברקוד QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\'הגדרות\' בסרגל המרחבים (בתחתית בצד שמאל)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">בחרו \'ייצוא לנייד\'</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">ייבוא דורש את הגירסא האחרונה של ת\'אנדרבירד לשולחן העבודה 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">לימדו איך לעדכן את ת\'אנדרבירד.</string>
<string name="onboarding_migration_thunderbird_link_open_error">לא נמצאו אפליקציות לפתיחת הקישור.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">設定をインポート</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">デスクトップ版 Thunderbird をお使いですか?</string>
<string name="onboarding_migration_thunderbird_new_account_title">Thunderbird は初めてですか?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">メールアカウントを追加</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">デスクトップ版 Thunderbird で:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">QR コードをスキャンして、アカウント設定を簡単にインポートできます。</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">スペースツールバーの「設定」(左下) を開き</string>
<string name="onboarding_migration_thunderbird_import_title">別のアプリや端末からの移行ですか?</string>
<string name="onboarding_migration_thunderbird_import_button_text">アカウント設定をインポート</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Thunderbird の更新方法はこちら。</string>
<string name="onboarding_migration_thunderbird_link_open_error">リンクを開くアプリが見つかりません。</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">「モバイル向けのエクスポート/書き出し」を選択してください</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">インポートするには、デスクトップ版 Thunderbird 128 以降の最新版をお使いである必要があります。<xliff:g id="link_text">%s</xliff:g></string>
</resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Баптауларды импорттау</string>
</resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Jau naudojatės „Thunderbird“ kompiuteryje?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Kompiuteryje paleistoje „Thunderbird“ programoje atlikite šiuos veiksmus:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Paprastai importuokite savo paskyrų nuostatas, nuskenuodami QR kodą.</string>
</resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Bruker du allerede Thunderbird på PC?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importer innstillinger</string>
<string name="onboarding_migration_thunderbird_new_account_title">Er du ny til Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Legg til en E-postkonto nå</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\'Innstillinger\' i Områder-verktøylinjen (nederst til venstre)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Velg \'Eksporter til Mobil\'</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Importering krever den nyeste versjonen av Thunderbird 128 for PC. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Lær hvordan man oppdaterer Thunderbird.</string>
<string name="onboarding_migration_thunderbird_import_title">Flytter du fra en annen app eller enhet?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importér kontoinnstillingene dine nå</string>
<string name="onboarding_migration_thunderbird_link_open_error">Ingen apper ble funnet som kunne åpne lenken.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importér kontoinnstillingene enkelt ved å skanne en QR-kode.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">I Thunderbird på PC, gå til:</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Gebruikt u Thunderbird al op de desktop?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importinstellingen</string>
<string name="onboarding_migration_thunderbird_new_account_title">Nieuw bij Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Voeg nu een e-mailaccount toe</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importeer eenvoudig uw accountinstellingen door een QR-code te scannen.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Ga in Thunderbird op de desktop naar:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">Instellingen in de Taakbalk (linksonder)</string>
<string name="onboarding_migration_thunderbird_import_title">Gebruikt u een andere app of een ander apparaat?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Uw accountinstellingen nu importeren</string>
<string name="onboarding_migration_thunderbird_link_open_error">Geen app gevonden om de koppeling te openen.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Voor importeren is de nieuwste versie van Thunderbird Desktop 128 vereist. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Selecteer Exporteren voor mobiel</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Meer info over het updaten van Thunderbird.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importer innstillingar</string>
<string name="onboarding_migration_thunderbird_new_account_title">Er du ny Thunderbird-brukar?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Legg til e-postkonto no</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Bruker du allereie Thunderbird på Desktop-PC?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importer innstillingane dine enkelt, med å skanne ein QR-kode.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">Innstillingar i områdeverktøylinja (nede til venstre)</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importer kontoinnstillingane dine no</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">I Thunderbird Desktop, gå til:</string>
<string name="onboarding_migration_thunderbird_import_title">Flytt frå annan app eller eining?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Vel Eksport til mobil</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Import krev den nyaste versjonen av Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Lær deg korleis du oppdaterer Thunderbird.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Ingen app funnen til å opne linken med.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_new_account_title">Nie znasz jeszcze Thunderbirda?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Dodaj teraz konto e-mail</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Używasz już Thunderbirda na komputerze?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importuj ustawienia</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">„Ustawienia” na pasku miejsc (lewy dolny róg)</string>
<string name="onboarding_migration_thunderbird_import_title">Przechodzisz z innej aplikacji lub urządzenia?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">W prosty sposób importuj ustawienia konta poprzez zeskanowanie kodu QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">W wersji komputerowej Thunderbirda przejdź do:</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importuj teraz ustawienia konta</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Wybierz „Eksportuj do wersji na telefon”</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Do importu wymagany jest komputerowy Thunderbird w najnowszej wersji 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Dowiedz się, jak zaktualizować Thunderbirda.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Nie znaleziono aplikacji umożliwiającej otwarcie łącza.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importar configurações</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Adicionar uma conta de e-mail agora</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Já está usando o Thunderbird no computador?</string>
<string name="onboarding_migration_thunderbird_new_account_title">Novo ao Thunderbird?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importe facilmente as suas configurações de conta lendo um código QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">No Thunderbird de computador, vá até:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\'Configurações\' na barra de ferramentas de espaços (inferior esquerdo)</string>
<string name="onboarding_migration_thunderbird_import_title">Movendo de outro app ou dispositivo?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importar suas configurações de conta agora</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Selecione \'Exportar para dispositivo móvel\'</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Para importar é necessário a versão mais recente do Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Saiba como atualizar o Thunderbird.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Nenhum aplicativo encontrado para abrir o link.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Já está a usar o Thunderbird no computador?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importe facilmente as suas configurações de conta lendo um código QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">No Thunderbird de computador, vá até:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\'Configurações\' na barra de ferramentas de espaços (inferior esquerdo)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Selecione \'Exportar para dispositivo móvel\'</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Para importar é necessário a versão mais recente do Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Saiba como atualizar o Thunderbird.</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Adicionar uma conta de e-mail agora</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importar configurações</string>
<string name="onboarding_migration_thunderbird_new_account_title">Novo ao Thunderbird?</string>
<string name="onboarding_migration_thunderbird_import_title">Mover de outra app ou dispositivo?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importar as suas configurações de conta agora</string>
<string name="onboarding_migration_thunderbird_link_open_error">Nenhuma app encontrada para abrir a ligação.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Já está a usar o Thunderbird no computador?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Selecione \'Exportar para dispositivo móvel\'</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Saiba como atualizar o Thunderbird.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importe facilmente as suas configurações de conta lendo um código QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">No Thunderbird de computador, vá até:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\'Configurações\' na barra de ferramentas de espaços (inferior esquerdo)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Para importar é necessário a versão mais recente do Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importar configurações</string>
<string name="onboarding_migration_thunderbird_new_account_title">Novo ao Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Adicionar uma conta de e-mail agora</string>
<string name="onboarding_migration_thunderbird_import_title">Mover de outra app ou dispositivo?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importar as suas configurações de conta agora</string>
<string name="onboarding_migration_thunderbird_link_open_error">Nenhuma app encontrada para abrir a ligação.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Utilizați deja Thunderbird pe calculator?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importare configurări</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Puteți importa cu ușurință configurările contului dvs. prin scanarea unui cod QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">În versiunea Thunderbird din calculator, mergeți la:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">„Setări” în bara de instrumente (stânga jos)</string>
<string name="onboarding_migration_thunderbird_new_account_title">Nu sunteți familiarizat încă cu Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Adaugă un cont de e-mail</string>
<string name="onboarding_migration_thunderbird_import_title">Veniți de la o altă aplicație sau dispozitiv?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importați acum configurația contului dvs.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Selectați «Exportați la dispozitivul mobil»</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Aflați cum să actualizați Thunderbird.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Nu s-a găsit nicio aplicație pentru a deschide legătura.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Importarea necesită cea mai recentă versiune a Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Уже используете Thunderbird на компьютере?</string>
<string name="onboarding_migration_thunderbird_new_account_title">Новичок в Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Добавьте аккаунт эл. почты</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Импортируйте настройки</string>
<string name="onboarding_migration_thunderbird_import_title">Переходите с другого приложения или устройства?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\"Настройки\" в панели мест (внизу слева)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Можно легко импортировать настройки своего аккаунта сканированием QR-кода.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">В Thunderbird на компьютере перейдите в:</string>
<string name="onboarding_migration_thunderbird_import_button_text">Импортируйте настройки своего аккаунта</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Узнайте, как обновить Thunderbird.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Для импортирования требуется последняя версия Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Выберите \"Экспорт для мобильного\"</string>
<string name="onboarding_migration_thunderbird_link_open_error">Не найдено приложение, позволяющее открыть ссылку.</string>
</resources>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Používate Thunderbird na PC?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importovať nastavenia</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Jednoducho importujte nastavenia konta naskenovaním QR kódu.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">Nastavenia v paneli schránok (naľavo dole)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Naučte sa ako aktualizovať Thunderbird.</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Pridať teraz e-mailové konto</string>
<string name="onboarding_migration_thunderbird_link_open_error">Nenašla sa aplikácia na otvorenie odkazu.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">V počítačovej verzií Thunderbird choďte na:</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Na računalniku že uporabljate Thunderbird?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Uvozi nastavitve</string>
<string name="onboarding_migration_thunderbird_new_account_title">Je Thunderbird nov za vas?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Dodaj nov e-poštni račun zdaj</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Enostavno uvozite nastavitve računa tako, da preberete QR-kodo.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">V Thunderbirdu za računalnike pojdite na:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Izberite \'Izvozi v prenosno napravo\'.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Uvoz zahteva najnovejši Thunderbird za namizja (razl. 128). <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Naučite se kako posodobiti Thunderbird.</string>
<string name="onboarding_migration_thunderbird_import_title">Ste se preselili z drugega programa ali naprave?</string>
<string name="onboarding_migration_thunderbird_link_open_error">Za odpiranje povezave ni bilo mogoče najti programa.</string>
<string name="onboarding_migration_thunderbird_import_button_text">Uvozi nastavitve računa zdaj</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\'Nastavitve\' v orodni vrstici prostorov (spodaj levo)</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importoni rregullime</string>
<string name="onboarding_migration_thunderbird_new_account_title">Për herë të parë me Thunderbird-in?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Shtoni një llogari email që tani</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">E përdorni tashmë Thunderbird-in në desktop?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">Rregullime te Paneli i Hapësirave (majtas poshtë)</string>
<string name="onboarding_migration_thunderbird_import_title">Po kaloni prej një aplikacioni apo pajisje tjetër?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importoni lehtësisht rregullimet e llogarisë tuaj, duke skanuar një kod QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Te Thunderbird-i për desktop kaloni te:</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importoni që tani rregullimet e llogarisë tuaj</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Mësoni si të përditësoni Thunderbird-in.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Su gjet aplikacion për hapjen e lidhjes.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Përzgjidhni “Eksporto te Celular”</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Importimi lyp versionin më të ri të Thunderbird-it për Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_new_account_title">Нови сте у Thunderbird-у?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Већ користите Thunderbird на рачунару?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Додај имејл налог сада</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">У Thunderbird-у на рачунару идите на:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Изаберите „Извези на мобилни уређај“</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Научите како да ажурирате Thunderbird.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Увезите подешавања</string>
<string name="onboarding_migration_thunderbird_import_title">Прелазите са друге апликације или уређаја?</string>
<string name="onboarding_migration_thunderbird_link_open_error">Није пронађена ниједна апликација за отварање линка.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">За увоз је потребна најновија верзија Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">„Подешавања“ на траци са алаткама места (доле лево)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Лако увезите подешавања налога скенирањем QR кода.</string>
<string name="onboarding_migration_thunderbird_import_button_text">Увези подешавања налога сада</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Importera inställningar</string>
<string name="onboarding_migration_thunderbird_new_account_title">Är du ny på Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Lägg till ett e-postkonto nu</string>
<string name="onboarding_migration_thunderbird_qr_code_import_title">Använder du redan Thunderbird på datorn?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\'Inställningar\' i flikmenyn</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Importera enkelt dina kontoinställningar genom att skanna en QR-kod.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">I Thunderbird för datorer, gå till:</string>
<string name="onboarding_migration_thunderbird_import_title">Flytta från en annan app eller enhet?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Importera dina kontoinställningar nu</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Import kräver den senaste versionen av Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Lär dig hur du uppdaterar Thunderbird.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Välj \"Exportera till mobil\"</string>
<string name="onboarding_migration_thunderbird_link_open_error">Ingen app hittades för att öppna länken.</string>
</resources>

View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">ஏற்கனவே டெச்க்டாப்பில் தண்டர்பேர்டைப் பயன்படுத்துகிறீர்களா?</string>
<string name="onboarding_migration_thunderbird_new_account_title">தண்டர்பேர்டுக்கு புதியதா?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">அமைப்புகளை இறக்குமதி செய்யுங்கள்</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">இப்போது ஒரு மின்னஞ்சல் கணக்கைச் சேர்க்கவும்</string>
<string name="onboarding_migration_thunderbird_import_title">மற்றொரு பயன்பாடு அல்லது சாதனத்திலிருந்து நகர்கிறீர்களா?</string>
<string name="onboarding_migration_thunderbird_import_button_text">உங்கள் கணக்கு அமைப்புகளை இப்போது இறக்குமதி செய்யுங்கள்</string>
<string name="onboarding_migration_thunderbird_link_open_error">இணைப்பைத் திறக்க எந்த பயன்பாடும் கிடைக்கவில்லை.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">QR குறியீட்டை ச்கேன் செய்வதன் மூலம் உங்கள் கணக்கு அமைப்புகளை எளிதாக இறக்குமதி செய்யுங்கள்.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">தண்டர்பேர்ட் டெச்க்டாப்பில், செல்லுங்கள்:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">ச்பேச் கருவிப்பட்டியில் ‘அமைப்புகள்’ (கீழ் இடது)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">‘மொபைலுக்கு ஏற்றுமதி’ என்பதைத் தேர்ந்தெடுக்கவும்</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">இறக்குமதிக்கு தண்டர்பேர்ட் டெச்க்டாப் 128 இன் அண்மைக் கால பதிப்பு தேவைப்படுகிறது.<xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">தண்டர்பேர்டைப் புதுப்பிப்பது எப்படி என்பதை அறிக.</string>
</resources>

View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Bilgisayarınızda Thunderbird\'ü zaten kullanıyor musunuz?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Ayarları içe aktar</string>
<string name="onboarding_migration_thunderbird_new_account_title">Thunderbird\'de yeni misiniz?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Şimdi bir e-posta hesabı ekleyin</string>
<string name="onboarding_migration_thunderbird_import_title">Başka bir uygulamadan veya cihazdan geçiş mi yapıyorsunuz?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Hesap ayarlarınızı içe aktarın</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Bilgisayarınızdaki Thunderbird\'de şunları yapın:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Bir QR kodu okutarak hesap ayarlarınızı kolayca içe aktarabilirsiniz.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">Sekme araç çubuğundaki Ayarlar simgesine tıklayın (sol alt köşede)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Thunderbird\'ü nasıl güncelleyebileceğinizi öğrenin.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Bağlantıyı açacak uygulama bulunamadı.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Mobil için Dışa Aktarı seçin</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">İçe aktarma için Thunderbird Masaüstü 128\'in son sürümünü kullanmanız gerekir. <xliff:g id="link_text">%s</xliff:g></string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Уже використовуєте Thunderbird на комп\'ютері?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Імпорт налаштувань</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Додайте обліковий запис е-пошти зараз</string>
<string name="onboarding_migration_thunderbird_new_account_title">Уперше в Thunderbird?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Легко імпортуйте налаштування свого облікового запису, сканувавши QR-код.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">У Thunderbird для комп\'ютера перейдіть до:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">‘Налаштування’ на панелі інструментів Простори (внизу ліворуч)</string>
<string name="onboarding_migration_thunderbird_import_title">Переходите з іншого застосунку або пристрою?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Імпортуйте налаштування свого облікового запису зараз</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Для імпорту потрібна остання версія Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Виберіть «Експортувати на мобільний»</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Дізнайтеся, як оновити Thunderbird.</string>
<string name="onboarding_migration_thunderbird_link_open_error">Застосунку для відкриття посилання не знайдено.</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Đang sử dụng Thunderbird trên máy tính?</string>
<string name="onboarding_migration_thunderbird_new_account_title">Mới sử dụng Thunderbird?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">Thêm một tài khoản thư điện tử ngay bây giờ</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">Nhập các cài đặt</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">Dễ dàng nhập các cài đặt tài khoản của bạn chỉ bằng việc quét mã QR.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">Trong Thunderbird cho máy tính, vào tới:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">Chọn \"Xuất ra Di Động\"</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Nhập vào cần phiên bản mới nhất của Thunderbird Máy tính bản 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Học cách cập nhất Thunderbird.</string>
<string name="onboarding_migration_thunderbird_import_title">Chuyển từ một ứng dụng hay thiết bị khác?</string>
<string name="onboarding_migration_thunderbird_import_button_text">Nhập các cài đặt của tài khoản bạn ngay</string>
<string name="onboarding_migration_thunderbird_link_open_error">Không ứng dụng nào được tìm thấy để mở đường dẫn.</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">\"Cài đặt\" trong phần Thanh công cụ Không gian (góc dưới bên trái)</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">已经在使用桌面版 Thunderbird</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">导入设置</string>
<string name="onboarding_migration_thunderbird_new_account_title">第一次使用 Thunderbird</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">立即添加电子邮件账号</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">通过扫描二维码轻松导入您的账号设置。</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">在 Thunderbird 桌面版中,转到:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">空间工具栏中的“设置”(左下角)</string>
<string name="onboarding_migration_thunderbird_import_title">从其他应用或设备迁移?</string>
<string name="onboarding_migration_thunderbird_import_button_text">立即导入您的账号设置</string>
<string name="onboarding_migration_thunderbird_link_open_error">未找到用于打开此链接的应用。</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">选择“导出到移动设备”</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">需要使用最新的 Thunderbird 桌面版 128 版本导入。<xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">了解更新 Thunderbird 的方法。</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">是否已在使用 Thunderbird 電腦版?</string>
<string name="onboarding_migration_thunderbird_new_account_button_text">立即新增電子郵件帳戶</string>
<string name="onboarding_migration_thunderbird_qr_code_import_button_text">匯入設定</string>
<string name="onboarding_migration_thunderbird_new_account_title">是 Thunderbird 新手嗎?</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_intro">前往 Thunderbird 電腦版的:</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_1">設定(在畫面左下角)</string>
<string name="onboarding_migration_thunderbird_qr_code_import_text">透過掃描 QR Code 輕鬆匯入帳戶設定。</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">查看如何更新 Thunderbird。</string>
<string name="onboarding_migration_thunderbird_import_title">從其他應用程式或裝置轉移?</string>
<string name="onboarding_migration_thunderbird_import_button_text">立即匯入您的帳戶設定</string>
<string name="onboarding_migration_thunderbird_link_open_error">找不到可以打開連結的應用程式。</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">匯入需要最新的電腦版 Thunderbird。 <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_bullet_2_v2">選擇「匯出至行動版」</string>
</resources>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_update_thunderbird_url" translatable="false">https://support.mozilla.org/kb/updating-thunderbird</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="onboarding_migration_thunderbird_qr_code_import_title">Already using Thunderbird on desktop?</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_v2">Select Export to Mobile</string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_require_latest">Import requires the latest version of Thunderbird Desktop 128. <xliff:g id="link_text">%s</xliff:g></string>
<string name="onboarding_migration_thunderbird_qr_code_import_instructions_learn_update">Learn how to update Thunderbird.</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>
<string name="onboarding_migration_thunderbird_link_open_error">No app found to open the link.</string>
</resources>

View file

@ -0,0 +1,74 @@
package app.k9mail.feature.onboarding.migration.thunderbird
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import app.k9mail.core.ui.compose.testing.ComposeTest
import app.k9mail.core.ui.compose.testing.setContentWithTheme
import assertk.assertThat
import assertk.assertions.isEqualTo
import net.thunderbird.core.common.provider.BrandNameProvider
import org.junit.Test
class TbOnboardingMigrationScreenKtTest : ComposeTest() {
@Test
fun `pressing QrCodeImportButton should call onQrCodeScan`() = runComposeTest {
var qrCodeScanClickCounter = 0
setContentWithTheme {
TbOnboardingMigrationScreen(
onQrCodeScan = { qrCodeScanClickCounter++ },
onAddAccount = { error("Should not be called") },
onImport = { error("Should not be called") },
brandNameProvider = FakeBrandNameProvider,
)
}
composeTestRule.onNodeWithTag("QrCodeImportButton")
.performScrollTo()
.performClick()
assertThat(qrCodeScanClickCounter).isEqualTo(1)
}
@Test
fun `pressing AddAccountButton button should call onAddAccount`() = runComposeTest {
var addAccountClickCounter = 0
setContentWithTheme {
TbOnboardingMigrationScreen(
onQrCodeScan = { error("Should not be called") },
onAddAccount = { addAccountClickCounter++ },
onImport = { error("Should not be called") },
brandNameProvider = FakeBrandNameProvider,
)
}
composeTestRule.onNodeWithTag("onboarding_migration_new_account_button")
.performScrollTo()
.performClick()
assertThat(addAccountClickCounter).isEqualTo(1)
}
@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)
}
}
private object FakeBrandNameProvider : BrandNameProvider {
override val brandName = "Thunderbird"
}

View file

@ -0,0 +1,15 @@
plugins {
id(ThunderbirdPlugins.Library.androidCompose)
}
android {
namespace = "app.k9mail.feature.onboarding.permissions"
resourcePrefix = "onboarding_permissions_"
}
dependencies {
implementation(projects.core.common)
implementation(projects.core.android.permissions)
implementation(projects.core.ui.compose.designsystem)
implementation(projects.feature.account.common)
}

View file

@ -0,0 +1,48 @@
package app.k9mail.feature.onboarding.permissions.ui
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
import app.k9mail.core.ui.compose.designsystem.atom.icon.IconsWithBottomRightOverlay
@Composable
@Preview(showBackground = true)
internal fun PermissionBoxUnknownStatePreview() {
PreviewWithTheme {
PermissionBox(
icon = IconsWithBottomRightOverlay.person,
permissionState = PermissionsContract.UiPermissionState.Unknown,
title = "Contacts",
description = "Allow access to be able to display contact names and photos.",
onAllowClick = {},
)
}
}
@Composable
@Preview(showBackground = true)
internal fun PermissionBoxGrantedStatePreview() {
PreviewWithTheme {
PermissionBox(
icon = IconsWithBottomRightOverlay.person,
permissionState = PermissionsContract.UiPermissionState.Granted,
title = "Contacts",
description = "Allow access to be able to display contact names and photos.",
onAllowClick = {},
)
}
}
@Composable
@Preview(showBackground = true)
internal fun PermissionBoxDeniedStatePreview() {
PreviewWithTheme {
PermissionBox(
icon = IconsWithBottomRightOverlay.person,
permissionState = PermissionsContract.UiPermissionState.Denied,
title = "Contacts",
description = "Allow access to be able to display contact names and photos.",
onAllowClick = {},
)
}
}

View file

@ -0,0 +1,23 @@
package app.k9mail.feature.onboarding.permissions.ui
import androidx.compose.runtime.Composable
import app.k9mail.core.ui.compose.common.annotation.PreviewDevices
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
@Composable
@PreviewDevices
internal fun PermissionContentPreview() {
PreviewWithTheme {
PermissionsContent(
state = PermissionsContract.State(
isLoading = false,
contactsPermissionState = PermissionsContract.UiPermissionState.Granted,
notificationsPermissionState = PermissionsContract.UiPermissionState.Denied,
isNotificationsPermissionVisible = true,
isNextButtonVisible = false,
),
onEvent = {},
brandName = "BrandName",
)
}
}

View file

@ -0,0 +1,25 @@
package app.k9mail.feature.onboarding.permissions.ui
import androidx.compose.runtime.Composable
import app.k9mail.core.android.permissions.PermissionState
import app.k9mail.core.ui.compose.common.annotation.PreviewDevices
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
import kotlinx.coroutines.Dispatchers
import net.thunderbird.core.common.provider.BrandNameProvider
@Composable
@PreviewDevices
internal fun PermissionScreenPreview() {
PreviewWithTheme {
PermissionsScreen(
viewModel = PermissionsViewModel(
checkPermission = { PermissionState.Denied },
backgroundDispatcher = Dispatchers.Main.immediate,
),
brandNameProvider = object : BrandNameProvider {
override val brandName: String = "BrandName"
},
onNext = {},
)
}
}

View file

@ -0,0 +1,23 @@
package app.k9mail.feature.onboarding.permissions
import app.k9mail.core.android.permissions.corePermissionsAndroidModule
import app.k9mail.feature.onboarding.permissions.domain.PermissionsDomainContract.UseCase
import app.k9mail.feature.onboarding.permissions.domain.usecase.CheckPermission
import app.k9mail.feature.onboarding.permissions.domain.usecase.HasRuntimePermissions
import app.k9mail.feature.onboarding.permissions.ui.PermissionsViewModel
import org.koin.core.module.Module
import org.koin.core.module.dsl.viewModel
import org.koin.dsl.module
val featureOnboardingPermissionsModule: Module = module {
includes(corePermissionsAndroidModule)
factory<UseCase.CheckPermission> { CheckPermission(permissionChecker = get()) }
factory<UseCase.HasRuntimePermissions> { HasRuntimePermissions(permissionsModelChecker = get()) }
viewModel {
PermissionsViewModel(
checkPermission = get(),
)
}
}

View file

@ -0,0 +1,18 @@
package app.k9mail.feature.onboarding.permissions.domain
import app.k9mail.core.android.permissions.Permission
import app.k9mail.core.android.permissions.PermissionState
interface PermissionsDomainContract {
interface UseCase {
fun interface CheckPermission {
operator fun invoke(permission: Permission): PermissionState
}
fun interface HasRuntimePermissions {
operator fun invoke(): Boolean
}
}
}

View file

@ -0,0 +1,18 @@
package app.k9mail.feature.onboarding.permissions.domain.usecase
import app.k9mail.core.android.permissions.Permission
import app.k9mail.core.android.permissions.PermissionChecker
import app.k9mail.core.android.permissions.PermissionState
import app.k9mail.feature.onboarding.permissions.domain.PermissionsDomainContract.UseCase
/**
* Checks if a [Permission] has been granted to the app.
*/
class CheckPermission(
private val permissionChecker: PermissionChecker,
) : UseCase.CheckPermission {
override fun invoke(permission: Permission): PermissionState {
return permissionChecker.checkPermission(permission)
}
}

View file

@ -0,0 +1,12 @@
package app.k9mail.feature.onboarding.permissions.domain.usecase
import app.k9mail.core.android.permissions.PermissionsModelChecker
import app.k9mail.feature.onboarding.permissions.domain.PermissionsDomainContract
class HasRuntimePermissions(
private val permissionsModelChecker: PermissionsModelChecker,
) : PermissionsDomainContract.UseCase.HasRuntimePermissions {
override fun invoke(): Boolean {
return permissionsModelChecker.hasRuntimePermissions()
}
}

View file

@ -0,0 +1,129 @@
package app.k9mail.feature.onboarding.permissions.ui
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.k9mail.core.ui.compose.common.image.ImageWithOverlayCoordinate
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonFilled
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icon
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleLarge
import app.k9mail.core.ui.compose.theme2.MainTheme
import app.k9mail.feature.onboarding.permissions.R
import app.k9mail.feature.onboarding.permissions.ui.PermissionsContract.UiPermissionState
private val MAX_WIDTH = 500.dp
@Composable
internal fun PermissionBox(
icon: ImageWithOverlayCoordinate,
permissionState: UiPermissionState,
title: String,
description: String,
onAllowClick: () -> Unit,
) {
Column(
modifier = Modifier
.width(MAX_WIDTH)
.padding(horizontal = MainTheme.spacings.double),
) {
Row {
Box(
modifier = Modifier.padding(
end = MainTheme.spacings.double,
top = MainTheme.spacings.default,
bottom = MainTheme.spacings.default,
),
) {
IconWithPermissionStateOverlay(icon, permissionState)
}
Column {
TextTitleLarge(text = title)
TextBodyMedium(text = description)
}
}
val buttonAlpha by animateFloatAsState(
targetValue = if (permissionState == UiPermissionState.Granted) 0f else 1f,
label = "AllowButtonAlpha",
)
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.End,
) {
Spacer(modifier = Modifier.height(MainTheme.spacings.default))
ButtonFilled(
text = stringResource(R.string.onboarding_permissions_allow_button),
onClick = onAllowClick,
modifier = Modifier.alpha(buttonAlpha),
)
}
}
}
@Composable
private fun IconWithPermissionStateOverlay(
icon: ImageWithOverlayCoordinate,
permissionState: UiPermissionState,
) {
Box {
val iconSize = MainTheme.sizes.iconLarge
val overlayIconSize = iconSize / 2
val overlayIconOffset = overlayIconSize / 2
val scalingFactor = iconSize / icon.image.defaultHeight
val overlayOffsetX = (icon.overlayOffsetX * scalingFactor) - overlayIconOffset
val overlayOffsetY = (icon.overlayOffsetY * scalingFactor) - overlayIconOffset
Icon(
imageVector = icon.image,
modifier = Modifier.size(iconSize),
)
when (permissionState) {
UiPermissionState.Unknown -> Unit
UiPermissionState.Granted -> {
Icon(
imageVector = Icons.Filled.CheckCircle,
tint = MainTheme.colors.success,
modifier = Modifier
.size(overlayIconSize)
.offset(
x = overlayOffsetX,
y = overlayOffsetY,
),
)
}
UiPermissionState.Denied -> {
Icon(
imageVector = Icons.Filled.Cancel,
tint = MainTheme.colors.warning,
modifier = Modifier
.size(overlayIconSize)
.offset(
x = overlayOffsetX,
y = overlayOffsetY,
),
)
}
}
}
}

View file

@ -0,0 +1,190 @@
package app.k9mail.feature.onboarding.permissions.ui
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.k9mail.core.ui.compose.common.visibility.hide
import app.k9mail.core.ui.compose.designsystem.atom.DelayedCircularProgressIndicator
import app.k9mail.core.ui.compose.designsystem.atom.Surface
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonFilled
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonText
import app.k9mail.core.ui.compose.designsystem.atom.icon.IconsWithBottomRightOverlay
import app.k9mail.core.ui.compose.designsystem.atom.text.TextHeadlineSmall
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
import app.k9mail.core.ui.compose.designsystem.template.Scaffold
import app.k9mail.core.ui.compose.theme2.MainTheme
import app.k9mail.feature.account.common.ui.AppTitleTopHeader
import app.k9mail.feature.onboarding.permissions.R
import app.k9mail.feature.onboarding.permissions.ui.PermissionsContract.Event
import app.k9mail.feature.onboarding.permissions.ui.PermissionsContract.State
import net.thunderbird.core.ui.compose.common.modifier.testTagAsResourceId
import app.k9mail.feature.account.common.R as CommonR
@Composable
internal fun PermissionsContent(
state: State,
onEvent: (Event) -> Unit,
brandName: String,
) {
val scrollState = rememberScrollState()
Scaffold(
bottomBar = {
BottomBar(state, onEvent, scrollState)
},
) { innerPadding ->
ResponsiveWidthContainer(
modifier = Modifier
.fillMaxWidth()
.padding(innerPadding),
) { contentPadding ->
Column(
verticalArrangement = Arrangement.SpaceBetween,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxHeight()
.verticalScroll(state = scrollState)
.padding(contentPadding),
) {
HeaderArea(brandName = brandName)
ContentArea(state, onEvent)
// This provides some bottom padding but is also necessary to make the vertical arrangement have the
// desired effect of putting ContentArea() in the middle.
Spacer(modifier = Modifier.height(MainTheme.spacings.double))
}
}
}
}
@Composable
private fun HeaderArea(
brandName: String,
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
AppTitleTopHeader(
title = brandName,
)
TextHeadlineSmall(
text = stringResource(R.string.onboarding_permissions_screen_title),
modifier = Modifier.padding(horizontal = MainTheme.spacings.double),
)
Spacer(modifier = Modifier.height(MainTheme.spacings.double))
}
}
@Composable
private fun ContentArea(state: State, onEvent: (Event) -> Unit) {
Column(
verticalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxHeight()
.padding(MainTheme.spacings.double),
) {
if (state.isLoading) {
DelayedCircularProgressIndicator()
} else {
PermissionBoxes(state, onEvent)
}
}
}
@Composable
private fun PermissionBoxes(
state: State,
onEvent: (Event) -> Unit,
) {
PermissionBox(
icon = IconsWithBottomRightOverlay.person,
permissionState = state.contactsPermissionState,
title = stringResource(R.string.onboarding_permissions_contacts_title),
description = stringResource(R.string.onboarding_permissions_contacts_description),
onAllowClick = { onEvent(Event.AllowContactsPermissionClicked) },
)
if (state.isNotificationsPermissionVisible) {
Spacer(modifier = Modifier.height(MainTheme.spacings.quadruple))
PermissionBox(
icon = IconsWithBottomRightOverlay.notification,
permissionState = state.notificationsPermissionState,
title = stringResource(R.string.onboarding_permissions_notifications_title),
description = stringResource(R.string.onboarding_permissions_notifications_description),
onAllowClick = { onEvent(Event.AllowNotificationsPermissionClicked) },
)
}
}
@Composable
private fun BottomBar(
state: State,
onEvent: (Event) -> Unit,
scrollState: ScrollState,
) {
// Elevate the bottom bar when some scrollable content is "underneath" it
val elevation by animateDpAsState(
targetValue = if (scrollState.canScrollForward) 8.dp else 0.dp,
label = "BottomBarElevation",
)
Surface(
tonalElevation = elevation,
) {
ResponsiveWidthContainer(
modifier = Modifier.fillMaxWidth(),
) { contentPadding ->
Row(
modifier = Modifier
.padding(
start = MainTheme.spacings.quadruple,
end = MainTheme.spacings.quadruple,
top = MainTheme.spacings.default,
bottom = MainTheme.spacings.double,
)
.fillMaxWidth()
.padding(contentPadding),
horizontalArrangement = Arrangement.End,
) {
Crossfade(
targetState = state.isNextButtonVisible,
label = "NextButton",
) { isNextButtonVisible ->
ButtonFilled(
text = stringResource(CommonR.string.account_common_button_next),
onClick = { onEvent(Event.NextClicked) },
modifier = Modifier.hide(!isNextButtonVisible)
.testTagAsResourceId("onboarding_permissions_next_button"),
)
ButtonText(
text = stringResource(R.string.onboarding_permissions_skip_button),
onClick = { onEvent(Event.NextClicked) },
modifier = Modifier.hide(isNextButtonVisible)
.testTagAsResourceId("onboarding_permissions_skip_button"),
)
}
}
}
}
}

View file

@ -0,0 +1,40 @@
package app.k9mail.feature.onboarding.permissions.ui
import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel
interface PermissionsContract {
interface ViewModel : UnidirectionalViewModel<State, Event, Effect>
data class State(
val isLoading: Boolean = true,
val contactsPermissionState: UiPermissionState = UiPermissionState.Unknown,
val notificationsPermissionState: UiPermissionState = UiPermissionState.Unknown,
val isNotificationsPermissionVisible: Boolean = false,
val isNextButtonVisible: Boolean = false,
)
sealed interface Event {
data object LoadPermissionState : Event
data object AllowContactsPermissionClicked : Event
data object AllowNotificationsPermissionClicked : Event
data class ContactsPermissionResult(val success: Boolean) : Event
data class NotificationsPermissionResult(val success: Boolean) : Event
data object NextClicked : Event
}
sealed interface Effect {
data object RequestContactsPermission : Effect
data object RequestNotificationsPermission : Effect
data object NavigateNext : Effect
}
enum class UiPermissionState {
Unknown,
Granted,
Denied,
}
}

View file

@ -0,0 +1,63 @@
package app.k9mail.feature.onboarding.permissions.ui
import android.Manifest
import android.os.Build
import androidx.activity.compose.BackHandler
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import app.k9mail.core.ui.compose.common.mvi.observe
import app.k9mail.feature.onboarding.permissions.ui.PermissionsContract.Effect
import app.k9mail.feature.onboarding.permissions.ui.PermissionsContract.Event
import net.thunderbird.core.common.provider.BrandNameProvider
import org.koin.androidx.compose.koinViewModel
import org.koin.compose.koinInject
@Composable
fun PermissionsScreen(
viewModel: PermissionsContract.ViewModel = koinViewModel<PermissionsViewModel>(),
brandNameProvider: BrandNameProvider = koinInject(),
onNext: () -> Unit,
) {
val contactsPermissionLauncher = rememberLauncherForActivityResult(RequestPermission()) { success ->
viewModel.event(Event.ContactsPermissionResult(success))
}
val notificationsPermissionLauncher = rememberLauncherForActivityResult(RequestPermission()) { success ->
viewModel.event(Event.NotificationsPermissionResult(success))
}
val (state, dispatch) = viewModel.observe { effect ->
when (effect) {
Effect.RequestContactsPermission -> contactsPermissionLauncher.requestContactsPermission()
Effect.RequestNotificationsPermission -> notificationsPermissionLauncher.requestNotificationsPermission()
Effect.NavigateNext -> onNext()
}
}
BackHandler {
// no back navigation
}
LaunchedEffect(key1 = Unit) {
dispatch(Event.LoadPermissionState)
}
PermissionsContent(
state = state.value,
onEvent = dispatch,
brandName = brandNameProvider.brandName,
)
}
private fun ManagedActivityResultLauncher<String, Boolean>.requestContactsPermission() {
launch(Manifest.permission.READ_CONTACTS)
}
private fun ManagedActivityResultLauncher<String, Boolean>.requestNotificationsPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
launch(Manifest.permission.POST_NOTIFICATIONS)
}
}

View file

@ -0,0 +1,108 @@
package app.k9mail.feature.onboarding.permissions.ui
import androidx.lifecycle.viewModelScope
import app.k9mail.core.android.permissions.Permission
import app.k9mail.core.android.permissions.PermissionState
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
import app.k9mail.feature.onboarding.permissions.domain.PermissionsDomainContract.UseCase
import app.k9mail.feature.onboarding.permissions.ui.PermissionsContract.Effect
import app.k9mail.feature.onboarding.permissions.ui.PermissionsContract.Event
import app.k9mail.feature.onboarding.permissions.ui.PermissionsContract.State
import app.k9mail.feature.onboarding.permissions.ui.PermissionsContract.UiPermissionState
import app.k9mail.feature.onboarding.permissions.ui.PermissionsContract.ViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class PermissionsViewModel(
private val checkPermission: UseCase.CheckPermission,
private val backgroundDispatcher: CoroutineDispatcher = Dispatchers.IO,
) : BaseViewModel<State, Event, Effect>(initialState = State(isLoading = true)), ViewModel {
override fun event(event: Event) {
when (event) {
Event.LoadPermissionState -> handleOneTimeEvent(event, ::loadPermissionState)
Event.AllowContactsPermissionClicked -> handleAllowContactsPermissionClicked()
Event.AllowNotificationsPermissionClicked -> handleAllowNotificationsPermissionClicked()
is Event.ContactsPermissionResult -> handleContactsPermissionResult(event.success)
is Event.NotificationsPermissionResult -> handleNotificationsPermissionResult(event.success)
Event.NextClicked -> handleNextClicked()
}
}
private fun loadPermissionState() {
viewModelScope.launch {
val (contactsPermissionState, notificationsPermissionState) = withContext(backgroundDispatcher) {
arrayOf(
checkPermission(Permission.Contacts),
checkPermission(Permission.Notifications),
)
}
val contactsUiPermissionState = when (contactsPermissionState) {
PermissionState.GrantedImplicitly -> error("Unexpected case")
PermissionState.Granted -> UiPermissionState.Granted
PermissionState.Denied -> UiPermissionState.Unknown
}
val notificationsUiPermissionState = when (notificationsPermissionState) {
PermissionState.GrantedImplicitly -> UiPermissionState.Unknown
PermissionState.Granted -> UiPermissionState.Granted
PermissionState.Denied -> UiPermissionState.Unknown
}
val isNotificationsPermissionVisible = notificationsPermissionState != PermissionState.GrantedImplicitly
updateState { state ->
state.copy(
isLoading = false,
contactsPermissionState = contactsUiPermissionState,
notificationsPermissionState = notificationsUiPermissionState,
isNotificationsPermissionVisible = isNotificationsPermissionVisible,
)
}
updateNextButtonState()
}
}
private fun handleAllowContactsPermissionClicked() {
emitEffect(Effect.RequestContactsPermission)
}
private fun handleAllowNotificationsPermissionClicked() {
emitEffect(Effect.RequestNotificationsPermission)
}
private fun handleContactsPermissionResult(success: Boolean) {
updateState { state ->
state.copy(
contactsPermissionState = if (success) UiPermissionState.Granted else UiPermissionState.Denied,
)
}
updateNextButtonState()
}
private fun handleNotificationsPermissionResult(success: Boolean) {
updateState { state ->
state.copy(
notificationsPermissionState = if (success) UiPermissionState.Granted else UiPermissionState.Denied,
)
}
updateNextButtonState()
}
private fun updateNextButtonState() {
updateState { state ->
val isContactsPermissionGranted = state.contactsPermissionState == UiPermissionState.Granted
val isNotificationsPermissionGrantedOrHidden = !state.isNotificationsPermissionVisible ||
state.notificationsPermissionState == UiPermissionState.Granted
state.copy(
isNextButtonVisible = isContactsPermissionGranted && isNotificationsPermissionGrantedOrHidden,
)
}
}
private fun handleNextClicked() {
emitEffect(Effect.NavigateNext)
}
}

Some files were not shown because too many files have changed in this diff Show more