feat: Easy device migration (login with a QR code).

This commit is contained in:
Mateusz Armatys
2025-04-08 16:13:51 +02:00
committed by MargeBot
parent 7a3bf9690a
commit a7e90670e9
11 changed files with 5023 additions and 6 deletions
File diff suppressed because it is too large Load Diff
@@ -264,7 +264,7 @@ abstract class AppDatabase :
companion object {
const val name = "db-mail"
const val version = 40
const val version = 41
internal val migrations = listOf(
AppDatabaseMigrations.MIGRATION_1_2,
@@ -305,7 +305,8 @@ abstract class AppDatabase :
AppDatabaseMigrations.MIGRATION_36_37,
AppDatabaseMigrations.MIGRATION_37_38,
AppDatabaseMigrations.MIGRATION_38_39,
AppDatabaseMigrations.MIGRATION_39_40
AppDatabaseMigrations.MIGRATION_39_40,
AppDatabaseMigrations.MIGRATION_40_41
)
fun buildDatabase(context: Context): AppDatabase = databaseBuilder<AppDatabase>(context, name)
@@ -308,4 +308,10 @@ object AppDatabaseMigrations {
UserSettingsDatabase.MIGRATION_8.migrate(db)
}
}
val MIGRATION_40_41 = object : Migration(40, 41) {
override fun migrate(db: SupportSQLiteDatabase) {
AccountDatabase.MIGRATION_10.migrate(db)
}
}
}
@@ -259,6 +259,9 @@ internal fun NavGraphBuilder.addSettings(navController: NavHostController) {
},
onBackClick = {
navController.navigateBack()
},
onSignOut = {
navController.navigate(Destination.Dialog.SignOut(it))
}
)
)
+1
View File
@@ -9,4 +9,5 @@
<!-- Mail already handle the Notification Permission (after successful login). -->
<bool name="core_feature_notifications_permission_request_enabled">false</bool>
<integer name="core_feature_auth_user_check_max_free_user_count">2</integer>
<bool name="core_feature_device_migration_enabled">true</bool>
</resources>
@@ -78,7 +78,8 @@ internal class SettingsScreenTest : HiltInstrumentedTest() {
onClearCacheClick = {},
onBackClick = {},
onExportLogsClick = {},
onCustomizeToolbarClick = {}
onCustomizeToolbarClick = {},
onSignOut = {}
),
LogsExportFeatureSetting(enabled = false, internalEnabled = false)
)
+5 -1
View File
@@ -59,7 +59,7 @@ kotlinx-serialization = "1.6.3"
material = "1.12.0"
mockk = "1.13.13"
play-review = "2.0.2"
proton-core = "31.0.0"
proton-core = "32.0.0"
kotlinpoet-ksp = "2.0.0"
leakcanary = "2.12"
okhttp = "4.12.0"
@@ -189,6 +189,7 @@ proton-core-accountRecoveryTest = { module = "me.proton.core:account-recovery-te
proton-core-auth = { module = "me.proton.core:auth", version.ref = "proton-core" }
proton-core-authTest = { module = "me.proton.core:auth-test", version.ref = "proton-core" }
proton-core-authFido = { module = "me.proton.core:auth-fido", version.ref = "proton-core" }
proton-core-biometric = { module = "me.proton.core:biometric", version.ref = "proton-core" }
proton-core-challenge = { module = "me.proton.core:challenge", version.ref = "proton-core" }
proton-core-contact = { module = "me.proton.core:contact", version.ref = "proton-core" }
proton-core-contact-domain = { module = "me.proton.core:contact-domain", version.ref = "proton-core" }
@@ -200,6 +201,7 @@ proton-core-crypto = { module = "me.proton.core:crypto", version.ref = "proton-c
proton-core-cryptoValidator = { module = "me.proton.core:crypto-validator", version.ref = "proton-core" }
proton-core-data = { module = "me.proton.core:data", version.ref = "proton-core" }
proton-core-dataRoom = { module = "me.proton.core:data-room", version.ref = "proton-core" }
proton-core-deviceMigration = { module = "me.proton.core:device-migration", version.ref = "proton-core" }
proton-core-domain = { module = "me.proton.core:domain", version.ref = "proton-core" }
proton-core-eventManager = { module = "me.proton.core:event-manager", version.ref = "proton-core" }
proton-core-featureFlag = { module = "me.proton.core:feature-flag", version.ref = "proton-core" }
@@ -273,6 +275,7 @@ appLibs = [
"proton-core-accountRecovery",
"proton-core-auth",
"proton-core-authFido",
"proton-core-biometric",
"proton-core-challenge",
"proton-core-contact",
"proton-core-country",
@@ -280,6 +283,7 @@ appLibs = [
"proton-core-cryptoValidator",
"proton-core-data",
"proton-core-dataRoom",
"proton-core-deviceMigration",
"proton-core-domain",
"proton-core-eventManager",
"proton-core-featureFlag",
@@ -64,6 +64,7 @@ dependencies {
implementation(libs.proton.core.account)
implementation(libs.proton.core.accountManager)
implementation(libs.proton.core.deviceMigration)
implementation(libs.proton.core.key)
implementation(libs.proton.core.user)
implementation(libs.proton.core.userSettings)
@@ -52,6 +52,8 @@ import me.proton.core.compose.component.ProtonSettingsList
import me.proton.core.compose.component.ProtonSettingsTopBar
import me.proton.core.compose.theme.ProtonDimens
import me.proton.core.compose.theme.ProtonTheme
import me.proton.core.devicemigration.presentation.settings.SignInToAnotherDeviceItem
import me.proton.core.domain.entity.UserId
import me.proton.core.presentation.utils.formatByteToHumanReadable
import me.proton.core.usersettings.presentation.compose.view.CrashReportSettingToggleItem
import me.proton.core.usersettings.presentation.compose.view.TelemetrySettingToggleItem
@@ -118,6 +120,16 @@ fun MainSettingsScreen(
onAccountClicked = actions.onAccountClick
)
}
item {
// Note: `SignInToAnotherDeviceItem` modifies its own visibility.
SignInToAnotherDeviceItem(
content = { label, onClick ->
ProtonSettingsItem(name = label, onClick = onClick)
Divider()
},
onLogOut = actions.onSignOut
)
}
item { ProtonSettingsHeader(title = string.mail_settings_app_settings) }
item {
ProtonSettingsItem(
@@ -343,7 +355,8 @@ object MainSettingsScreen {
val onSwipeActionsClick: () -> Unit,
val onClearCacheClick: () -> Unit,
val onExportLogsClick: (isInternalFeatureEnabled: Boolean) -> Unit,
val onBackClick: () -> Unit
val onBackClick: () -> Unit,
val onSignOut: (UserId) -> Unit
)
}
@@ -50,6 +50,7 @@ object SettingsScreenPreviewData {
onClearCacheClick = {},
onExportLogsClick = {},
onBackClick = {},
onCustomizeToolbarClick = {}
onCustomizeToolbarClick = {},
onSignOut = {}
)
}
@@ -50,6 +50,7 @@ object AccountTestData {
requiredAccountType = Internal,
secondFactorEnabled = true,
twoPassModeEnabled = true,
passphrase = null,
password = null,
fido2AuthenticationOptionsJson = null
)
@@ -70,6 +71,7 @@ object AccountTestData {
requiredAccountType = Internal,
secondFactorEnabled = true,
twoPassModeEnabled = true,
passphrase = null,
password = null,
fido2AuthenticationOptionsJson = null
)
@@ -90,6 +92,7 @@ object AccountTestData {
requiredAccountType = Internal,
secondFactorEnabled = true,
twoPassModeEnabled = true,
passphrase = null,
password = null,
fido2AuthenticationOptionsJson = null
)
@@ -110,6 +113,7 @@ object AccountTestData {
requiredAccountType = Internal,
secondFactorEnabled = true,
twoPassModeEnabled = true,
passphrase = null,
password = null,
fido2AuthenticationOptionsJson = null
)