From 3713d265c6b6368d10a0adc11edb4f130025664c Mon Sep 17 00:00:00 2001 From: Louis CAD Date: Wed, 18 Dec 2024 09:48:00 +0100 Subject: [PATCH 01/16] chore: Show error message if the env.properties file is missing --- app/build.gradle.kts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f2f59e121..fb556da20 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,4 @@ -import org.jetbrains.kotlin.konan.properties.loadProperties +import java.util.Properties plugins { alias(libs.plugins.android.application) @@ -15,9 +15,12 @@ val sharedCompileSdk: Int by rootProject.extra val sharedMinSdk: Int by rootProject.extra val sharedJavaVersion: JavaVersion by rootProject.extra -val envProperties = loadProperties("env.properties") -val sentryAuthToken = envProperties.getProperty("sentryAuthToken").takeIf { it.isNotEmpty() } - ?: error("The `sentryAuthToken` property in `env.properties` must be defined and not empty (see `env.example.properties`).") +val envProperties = file("env.properties").takeIf { it.exists() }?.let { file -> + Properties().also { it.load(file.reader()) } +} + +val sentryAuthToken = envProperties?.getProperty("sentryAuthToken").takeUnless { it.isNullOrBlank() } + ?: error("The `sentryAuthToken` property in `env.properties` must be specified (see `env.example.properties`).") android { namespace = "com.infomaniak.swisstransfer" From 245af4d30d86cd38e78b9c9a7b68b49e9f7a639e Mon Sep 17 00:00:00 2001 From: Louis CAD Date: Wed, 18 Dec 2024 09:56:02 +0100 Subject: [PATCH 02/16] fix: Point to the root env.properties file --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index fb556da20..a96b557a6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,7 +15,7 @@ val sharedCompileSdk: Int by rootProject.extra val sharedMinSdk: Int by rootProject.extra val sharedJavaVersion: JavaVersion by rootProject.extra -val envProperties = file("env.properties").takeIf { it.exists() }?.let { file -> +val envProperties = rootProject.file("env.properties").takeIf { it.exists() }?.let { file -> Properties().also { it.load(file.reader()) } } From e2168c8f6e9ddaa36a0fe7970749107533156aa4 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 18 Dec 2024 10:25:50 +0100 Subject: [PATCH 03/16] chore: Add new logic for toDestination without kotlin reflect --- .../ui/navigation/NavigationDestination.kt | 65 +++++++++---------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt index d00600ccf..391f1a37b 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt @@ -17,24 +17,23 @@ */ package com.infomaniak.swisstransfer.ui.navigation -import android.os.Bundle import androidx.compose.animation.AnimatedContentScope import androidx.compose.runtime.Composable import androidx.navigation.NavBackStackEntry import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import androidx.navigation.navDeepLink +import androidx.navigation.toRoute +import com.infomaniak.sentry.SentryLog import com.infomaniak.swisstransfer.BuildConfig import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.components.TransferTypeUi import kotlinx.serialization.Serializable -import kotlin.reflect.KClass -import kotlin.reflect.full.primaryConstructor /** * Sealed class representing the navigation arguments for the main navigation flow. */ @Serializable -sealed class MainNavigation : NavigationDestination() { +sealed class MainNavigation() : NavigationDestination() { var enableTransition = true @Serializable @@ -57,7 +56,7 @@ sealed class MainNavigation : NavigationDestination() { } } } - + @Serializable data class TransferDetailsDestination(val transferUuid: String) : MainNavigation() @@ -65,7 +64,31 @@ sealed class MainNavigation : NavigationDestination() { data object SettingsDestination : MainNavigation() companion object { + private val TAG = MainNavigation::class.java.simpleName val startDestination = SentDestination + + val entries = listOf( + SentDestination::class, + ReceivedDestination::class, + TransferDetailsDestination::class, + SettingsDestination::class, + ) + + fun NavBackStackEntry.toMainDestination(): MainNavigation? { + return runCatching { + val destinationRoute = destination.route ?: error("Destination route cannot be empty") + when (entries.firstOrNull { destinationRoute.contains(it.qualifiedName.toString()) }) { + SentDestination::class -> this.toRoute() + ReceivedDestination::class -> this.toRoute() + TransferDetailsDestination::class -> this.toRoute() + SettingsDestination::class -> this.toRoute() + else -> error("Destination $destinationRoute is not handled") + } + }.getOrElse { exception -> + SentryLog.e(TAG, "toMainDestination: Failure", exception) + null + } + } } } @@ -98,34 +121,4 @@ sealed class NewTransferNavigation : NavigationDestination() { * Sealed class representing navigation arguments with a title resource. */ @Serializable -sealed class NavigationDestination { - - companion object { - - inline fun NavBackStackEntry.toDestination(): T? { - return toDestination(T::class, backStackEntry = this) - } - - fun toDestination(kClass: KClass, backStackEntry: NavBackStackEntry?): T? { - - fun kClassFromRoute(route: String) = kClass.sealedSubclasses.firstOrNull { - route.contains(it.qualifiedName.toString()) - } - - if (backStackEntry == null) return null - - val route = backStackEntry.destination.route ?: "" - val args = backStackEntry.arguments - val subclass = kClassFromRoute(route) ?: return null - - return createInstance(subclass, args) - } - - private fun createInstance(kClass: KClass, bundle: Bundle?): T? { - return kClass.primaryConstructor?.let { - val args = it.parameters.associateWith { parameter -> bundle?.get(parameter.name) } - it.callBy(args) - } ?: kClass.objectInstance - } - } -} +sealed class NavigationDestination From 02c1dea3ec889146d30d2fd703b2945ff9cda4b6 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 18 Dec 2024 10:26:33 +0100 Subject: [PATCH 04/16] chore: Use toMainDestination instead --- .../com/infomaniak/swisstransfer/ui/screen/main/MainScreen.kt | 4 ++-- .../swisstransfer/ui/screen/main/components/MainScaffold.kt | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/MainScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/MainScreen.kt index a42714170..fe06e199f 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/MainScreen.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/MainScreen.kt @@ -25,7 +25,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.infomaniak.swisstransfer.ui.components.BrandTopAppBar import com.infomaniak.swisstransfer.ui.navigation.MainNavigation -import com.infomaniak.swisstransfer.ui.navigation.NavigationDestination.Companion.toDestination +import com.infomaniak.swisstransfer.ui.navigation.MainNavigation.Companion.toMainDestination import com.infomaniak.swisstransfer.ui.screen.main.components.MainScaffold import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewAllWindows @@ -37,7 +37,7 @@ fun MainScreen() { val navBackStackEntry by navController.currentBackStackEntryAsState() val currentDestination by remember(navBackStackEntry) { - derivedStateOf { navBackStackEntry?.toDestination() ?: MainNavigation.startDestination } + derivedStateOf { navBackStackEntry?.toMainDestination() ?: MainNavigation.startDestination } } MainScaffold( diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/components/MainScaffold.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/components/MainScaffold.kt index 563d53799..c66aa7f66 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/components/MainScaffold.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/components/MainScaffold.kt @@ -17,7 +17,6 @@ */ package com.infomaniak.swisstransfer.ui.screen.main.components -import android.content.Intent import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.material3.HorizontalDivider @@ -26,10 +25,8 @@ import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteType import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.navigation.NavController import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController -import com.infomaniak.core2.extensions.parcelableExtra import com.infomaniak.swisstransfer.ui.components.BrandTopAppBar import com.infomaniak.swisstransfer.ui.navigation.MainNavigation import com.infomaniak.swisstransfer.ui.navigation.NavigationItem From 7137428a2967d7ecae673adaf78b31f0e8ea2b3d Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 18 Dec 2024 10:28:00 +0100 Subject: [PATCH 05/16] chore: Remove useless code --- .../swisstransfer/ui/navigation/NavigationDestination.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt index 391f1a37b..394acafc9 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt @@ -33,7 +33,7 @@ import kotlinx.serialization.Serializable * Sealed class representing the navigation arguments for the main navigation flow. */ @Serializable -sealed class MainNavigation() : NavigationDestination() { +sealed class MainNavigation : NavigationDestination() { var enableTransition = true @Serializable From efee9cf1a57f8a059a2d34bb87a046b76b3e9bfa Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Wed, 18 Dec 2024 10:31:06 +0100 Subject: [PATCH 06/16] refactor: Remove now unused `TransferDetailsDestination` --- .../swisstransfer/ui/navigation/NavigationDestination.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt index 394acafc9..d63d7e5a4 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt @@ -57,9 +57,6 @@ sealed class MainNavigation : NavigationDestination() { } } - @Serializable - data class TransferDetailsDestination(val transferUuid: String) : MainNavigation() - @Serializable data object SettingsDestination : MainNavigation() @@ -70,7 +67,6 @@ sealed class MainNavigation : NavigationDestination() { val entries = listOf( SentDestination::class, ReceivedDestination::class, - TransferDetailsDestination::class, SettingsDestination::class, ) @@ -80,7 +76,6 @@ sealed class MainNavigation : NavigationDestination() { when (entries.firstOrNull { destinationRoute.contains(it.qualifiedName.toString()) }) { SentDestination::class -> this.toRoute() ReceivedDestination::class -> this.toRoute() - TransferDetailsDestination::class -> this.toRoute() SettingsDestination::class -> this.toRoute() else -> error("Destination $destinationRoute is not handled") } From 572f985746a51ed6361c1ec3e469be76fe9b51d9 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Wed, 18 Dec 2024 11:00:58 +0100 Subject: [PATCH 07/16] fix: Destination UI now correctly updates when app is minified --- .../ui/navigation/NavigationDestination.kt | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt index d63d7e5a4..abe2f6dcd 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt @@ -36,9 +36,19 @@ import kotlinx.serialization.Serializable sealed class MainNavigation : NavigationDestination() { var enableTransition = true + /** + * DO NOT RENAME THIS. + * EVER. + * Because of the minification, it will break the `toMainDestination()` function. + */ @Serializable data object SentDestination : MainNavigation() + /** + * DO NOT RENAME THIS. + * EVER. + * Because of the minification, it will break the `toMainDestination()` function. + */ @Serializable data class ReceivedDestination(val transferUuid: String? = null) : MainNavigation() { @@ -57,6 +67,11 @@ sealed class MainNavigation : NavigationDestination() { } } + /** + * DO NOT RENAME THIS. + * EVER. + * Because of the minification, it will break the `toMainDestination()` function. + */ @Serializable data object SettingsDestination : MainNavigation() @@ -64,19 +79,25 @@ sealed class MainNavigation : NavigationDestination() { private val TAG = MainNavigation::class.java.simpleName val startDestination = SentDestination + /** + * If these classes have to be renamed, they need to be renamed in this `list` too. + */ val entries = listOf( - SentDestination::class, - ReceivedDestination::class, - SettingsDestination::class, + "SentDestination", + "ReceivedDestination", + "SettingsDestination", ) fun NavBackStackEntry.toMainDestination(): MainNavigation? { return runCatching { val destinationRoute = destination.route ?: error("Destination route cannot be empty") - when (entries.firstOrNull { destinationRoute.contains(it.qualifiedName.toString()) }) { - SentDestination::class -> this.toRoute() - ReceivedDestination::class -> this.toRoute() - SettingsDestination::class -> this.toRoute() + /** + * If these classes have to be renamed, they need to be renamed in this `when` too. + */ + when (entries.firstOrNull { destinationRoute.contains(it) }) { + "SentDestination" -> this.toRoute() + "ReceivedDestination" -> this.toRoute() + "SettingsDestination" -> this.toRoute() else -> error("Destination $destinationRoute is not handled") } }.getOrElse { exception -> From 87f12b5541797f7f8499890ca86d5618f79f103b Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 18 Dec 2024 11:06:48 +0100 Subject: [PATCH 08/16] chore: New release Alpha 2 --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a96b557a6..88bcd9f2d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -30,8 +30,8 @@ android { applicationId = "com.infomaniak.swisstransfer" minSdk = sharedMinSdk targetSdk = sharedCompileSdk - versionCode = 1 // 0_00_000_01 TODO: Update when released in prod - versionName = "0.0.1-Alpha1" + versionCode = 2 // 0_00_000_02 TODO: Update when released in prod + versionName = "0.0.2-Alpha2" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { From 32762669c7f53fce6d21f5e47d3380f7aebf4f6c Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Wed, 18 Dec 2024 11:18:36 +0100 Subject: [PATCH 09/16] chore: New release 1.0.0-Alpha2 --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 88bcd9f2d..d9050460e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -30,8 +30,8 @@ android { applicationId = "com.infomaniak.swisstransfer" minSdk = sharedMinSdk targetSdk = sharedCompileSdk - versionCode = 2 // 0_00_000_02 TODO: Update when released in prod - versionName = "0.0.2-Alpha2" + versionCode = 1_00_000_00 + versionName = "1.0.0-Alpha2" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { From 802195e10a762977f5983bdc216cf0b948b25ccb Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Wed, 18 Dec 2024 11:24:40 +0100 Subject: [PATCH 10/16] test: Add test about Destinations names --- .../NavigationDestinationUnitTest.kt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt diff --git a/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt b/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt new file mode 100644 index 000000000..54aff35d6 --- /dev/null +++ b/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt @@ -0,0 +1,38 @@ +/* + * Infomaniak SwissTransfer - Android + * Copyright (C) 2024 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.swisstransfer + +import com.infomaniak.swisstransfer.ui.navigation.MainNavigation +import org.junit.Assert.assertEquals +import org.junit.Test + +class NavigationDestinationUnitTest { + + /** + * Make sure that NavigationDestination names are not changed without changing the `entries` list, because of minification issue. + */ + @Test + fun check_destinations_names_are_correct() { + val sent = MainNavigation.SentDestination::class.simpleName + val received = MainNavigation.ReceivedDestination::class.simpleName + val settings = MainNavigation.SettingsDestination::class.simpleName + assertEquals(MainNavigation.Companion.entries.find { it == sent }, sent) + assertEquals(MainNavigation.Companion.entries.find { it == received }, received) + assertEquals(MainNavigation.Companion.entries.find { it == settings }, settings) + } +} From b79a608eba5cfc2dcf2a6fb40e1a908f6928f013 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Wed, 18 Dec 2024 12:39:25 +0100 Subject: [PATCH 11/16] refactor: Simplify comments --- .../ui/navigation/NavigationDestination.kt | 40 +++++-------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt index abe2f6dcd..5fb1defea 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt @@ -36,19 +36,11 @@ import kotlinx.serialization.Serializable sealed class MainNavigation : NavigationDestination() { var enableTransition = true - /** - * DO NOT RENAME THIS. - * EVER. - * Because of the minification, it will break the `toMainDestination()` function. - */ + // If it has to be renamed, don't forget to rename `*DestinationName` in the companion object too. @Serializable data object SentDestination : MainNavigation() - /** - * DO NOT RENAME THIS. - * EVER. - * Because of the minification, it will break the `toMainDestination()` function. - */ + // If it has to be renamed, don't forget to rename `*DestinationName` in the companion object too. @Serializable data class ReceivedDestination(val transferUuid: String? = null) : MainNavigation() { @@ -67,11 +59,7 @@ sealed class MainNavigation : NavigationDestination() { } } - /** - * DO NOT RENAME THIS. - * EVER. - * Because of the minification, it will break the `toMainDestination()` function. - */ + // If it has to be renamed, don't forget to rename `*DestinationName` in the companion object too. @Serializable data object SettingsDestination : MainNavigation() @@ -79,25 +67,19 @@ sealed class MainNavigation : NavigationDestination() { private val TAG = MainNavigation::class.java.simpleName val startDestination = SentDestination - /** - * If these classes have to be renamed, they need to be renamed in this `list` too. - */ - val entries = listOf( - "SentDestination", - "ReceivedDestination", - "SettingsDestination", - ) + // If these classes have to be renamed, they need to be renamed here too. + val sentDestinationName = "SentDestination" + val receivedDestinationName = "ReceivedDestination" + val settingsDestinationName = "SettingsDestination" + val entries = listOf(sentDestinationName, receivedDestinationName, settingsDestinationName) fun NavBackStackEntry.toMainDestination(): MainNavigation? { return runCatching { val destinationRoute = destination.route ?: error("Destination route cannot be empty") - /** - * If these classes have to be renamed, they need to be renamed in this `when` too. - */ when (entries.firstOrNull { destinationRoute.contains(it) }) { - "SentDestination" -> this.toRoute() - "ReceivedDestination" -> this.toRoute() - "SettingsDestination" -> this.toRoute() + sentDestinationName -> this.toRoute() + receivedDestinationName -> this.toRoute() + settingsDestinationName -> this.toRoute() else -> error("Destination $destinationRoute is not handled") } }.getOrElse { exception -> From d33cb24a37e52ad01a21f410776dce7658878183 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Wed, 18 Dec 2024 12:52:14 +0100 Subject: [PATCH 12/16] refactor: Rename `entries` into `destinationsNames` --- .../swisstransfer/ui/navigation/NavigationDestination.kt | 4 ++-- .../swisstransfer/NavigationDestinationUnitTest.kt | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt index 5fb1defea..298bcab19 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/navigation/NavigationDestination.kt @@ -71,12 +71,12 @@ sealed class MainNavigation : NavigationDestination() { val sentDestinationName = "SentDestination" val receivedDestinationName = "ReceivedDestination" val settingsDestinationName = "SettingsDestination" - val entries = listOf(sentDestinationName, receivedDestinationName, settingsDestinationName) + val destinationsNames = listOf(sentDestinationName, receivedDestinationName, settingsDestinationName) fun NavBackStackEntry.toMainDestination(): MainNavigation? { return runCatching { val destinationRoute = destination.route ?: error("Destination route cannot be empty") - when (entries.firstOrNull { destinationRoute.contains(it) }) { + when (destinationsNames.firstOrNull { destinationRoute.contains(it) }) { sentDestinationName -> this.toRoute() receivedDestinationName -> this.toRoute() settingsDestinationName -> this.toRoute() diff --git a/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt b/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt index 54aff35d6..3ce98dd48 100644 --- a/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt +++ b/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt @@ -31,8 +31,8 @@ class NavigationDestinationUnitTest { val sent = MainNavigation.SentDestination::class.simpleName val received = MainNavigation.ReceivedDestination::class.simpleName val settings = MainNavigation.SettingsDestination::class.simpleName - assertEquals(MainNavigation.Companion.entries.find { it == sent }, sent) - assertEquals(MainNavigation.Companion.entries.find { it == received }, received) - assertEquals(MainNavigation.Companion.entries.find { it == settings }, settings) + assertEquals(MainNavigation.Companion.destinationsNames.find { it == sent }, sent) + assertEquals(MainNavigation.Companion.destinationsNames.find { it == received }, received) + assertEquals(MainNavigation.Companion.destinationsNames.find { it == settings }, settings) } } From f0b05ac3a19ab1a0ba0191bb5063349213f019bc Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Wed, 18 Dec 2024 12:58:23 +0100 Subject: [PATCH 13/16] test: Factorize test --- .../swisstransfer/NavigationDestinationUnitTest.kt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt b/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt index 3ce98dd48..4b1751062 100644 --- a/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt +++ b/app/src/test/java/com/infomaniak/swisstransfer/NavigationDestinationUnitTest.kt @@ -18,7 +18,7 @@ package com.infomaniak.swisstransfer import com.infomaniak.swisstransfer.ui.navigation.MainNavigation -import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull import org.junit.Test class NavigationDestinationUnitTest { @@ -28,11 +28,9 @@ class NavigationDestinationUnitTest { */ @Test fun check_destinations_names_are_correct() { - val sent = MainNavigation.SentDestination::class.simpleName - val received = MainNavigation.ReceivedDestination::class.simpleName - val settings = MainNavigation.SettingsDestination::class.simpleName - assertEquals(MainNavigation.Companion.destinationsNames.find { it == sent }, sent) - assertEquals(MainNavigation.Companion.destinationsNames.find { it == received }, received) - assertEquals(MainNavigation.Companion.destinationsNames.find { it == settings }, settings) + val destinationsNames = MainNavigation.Companion.destinationsNames + assertNotNull(destinationsNames.find { it == MainNavigation.SentDestination::class.simpleName }) + assertNotNull(destinationsNames.find { it == MainNavigation.ReceivedDestination::class.simpleName }) + assertNotNull(destinationsNames.find { it == MainNavigation.SettingsDestination::class.simpleName }) } } From dc6f78e6dabf72c62b05f14921f737bf1a07e7a9 Mon Sep 17 00:00:00 2001 From: Kevin Boulongne Date: Wed, 18 Dec 2024 13:58:45 +0100 Subject: [PATCH 14/16] fix: SwissTransferCard click now correctly displays its shape --- .../ui/components/SwissTransferCard.kt | 17 +++++++++++++---- .../importfiles/components/ImportedFilesCard.kt | 3 +-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferCard.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferCard.kt index 5e8f63299..4f3b5d0bb 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferCard.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferCard.kt @@ -17,6 +17,7 @@ */ package com.infomaniak.swisstransfer.ui.components +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.padding @@ -27,6 +28,7 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp import com.infomaniak.swisstransfer.ui.theme.CustomShapes import com.infomaniak.swisstransfer.ui.theme.Margin @@ -34,10 +36,17 @@ import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewLightAndDark @Composable -fun SwissTransferCard(modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) { +fun SwissTransferCard(modifier: Modifier = Modifier, onClick: (() -> Unit)? = null, content: @Composable ColumnScope.() -> Unit) { Card( - modifier = modifier, - shape = CustomShapes.MEDIUM, + modifier = modifier + .clip(shape = CustomShapes.MEDIUM) + .then( + other = if (onClick == null) { + Modifier + } else { + Modifier.clickable(onClick = onClick) + } + ), colors = CardDefaults.cardColors(contentColor = SwissTransferTheme.colors.secondaryTextColor), content = content, ) @@ -51,7 +60,7 @@ private fun SwissTransferCardPreview() { SwissTransferCard( modifier = Modifier .size(300.dp, 200.dp) - .padding(Margin.Medium) + .padding(Margin.Medium), ) { Column(Modifier.padding(Margin.Large)) { Text("Hello World!") diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/ImportedFilesCard.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/ImportedFilesCard.kt index d33fb85a6..342e53c9f 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/ImportedFilesCard.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/ImportedFilesCard.kt @@ -18,7 +18,6 @@ package com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.components import android.os.Parcelable -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items @@ -73,7 +72,7 @@ fun ImportedFilesCard( } } - SwissTransferCard(modifier.clickable { navigateToFileDetails() }) { + SwissTransferCard(modifier = modifier, onClick = navigateToFileDetails) { Row(verticalAlignment = Alignment.CenterVertically) { TextDotText( firstText = { From db966c7965add712bd857e97abf6fc0fd1f6d3a6 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 18 Dec 2024 10:11:41 +0100 Subject: [PATCH 15/16] feat: Factorize send transfer logic to a reusable class --- .../newtransfer/ImportFilesViewModel.kt | 92 ++---------- .../screen/newtransfer/TransferSendManager.kt | 142 ++++++++++++++++++ .../importfiles/ImportFilesScreen.kt | 12 +- 3 files changed, 158 insertions(+), 88 deletions(-) create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/TransferSendManager.kt diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/ImportFilesViewModel.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/ImportFilesViewModel.kt index e34cf2667..ca2a72d18 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/ImportFilesViewModel.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/ImportFilesViewModel.kt @@ -18,7 +18,6 @@ package com.infomaniak.swisstransfer.ui.screen.newtransfer import android.net.Uri -import android.util.Log import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -26,9 +25,6 @@ import androidx.compose.runtime.setValue import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.infomaniak.core2.appintegrity.AppIntegrityManager -import com.infomaniak.core2.appintegrity.AppIntegrityManager.Companion.APP_INTEGRITY_MANAGER_TAG -import com.infomaniak.multiplatform_swisstransfer.SharedApiUrlCreator import com.infomaniak.multiplatform_swisstransfer.common.interfaces.upload.RemoteUploadFile import com.infomaniak.multiplatform_swisstransfer.common.interfaces.upload.UploadFileSession import com.infomaniak.multiplatform_swisstransfer.common.utils.mapToList @@ -36,7 +32,6 @@ import com.infomaniak.multiplatform_swisstransfer.data.NewUploadSession import com.infomaniak.multiplatform_swisstransfer.managers.AppSettingsManager import com.infomaniak.multiplatform_swisstransfer.managers.UploadManager import com.infomaniak.sentry.SentryLog -import com.infomaniak.swisstransfer.BuildConfig import com.infomaniak.swisstransfer.di.IoDispatcher import com.infomaniak.swisstransfer.ui.screen.main.settings.DownloadLimitOption import com.infomaniak.swisstransfer.ui.screen.main.settings.DownloadLimitOption.Companion.toTransferOption @@ -51,31 +46,27 @@ import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.TransferOp import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.components.TransferTypeUi import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.components.TransferTypeUi.Companion.toTransferTypeUi import com.infomaniak.swisstransfer.ui.utils.GetSetCallbacks -import com.infomaniak.swisstransfer.workers.UploadWorker import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class ImportFilesViewModel @Inject constructor( private val appSettingsManager: AppSettingsManager, - private val appIntegrityManager: AppIntegrityManager, private val savedStateHandle: SavedStateHandle, private val importationFilesManager: ImportationFilesManager, - private val sharedApiUrlCreator: SharedApiUrlCreator, private val uploadManager: UploadManager, - private val uploadWorkerScheduler: UploadWorker.Scheduler, + private val transferSendManager: TransferSendManager, @IoDispatcher private val ioDispatcher: CoroutineDispatcher, ) : ViewModel() { - private val _sendActionResult = MutableStateFlow(SendActionResult.NotStarted) - val sendActionResult = _sendActionResult.asStateFlow() - - private val _integrityCheckResult = MutableStateFlow(AppIntegrityResult.Idle) - val integrityCheckResult = _integrityCheckResult.asStateFlow() + val sendActionResult by transferSendManager::sendActionResult + val integrityCheckResult by transferSendManager::integrityCheckResult @OptIn(FlowPreview::class) val importedFilesDebounced = importationFilesManager.importedFiles @@ -138,82 +129,19 @@ class ImportFilesViewModel @Inject constructor( } } - private fun sendTransfer(attestationToken: String) { - _sendActionResult.update { SendActionResult.Pending } + fun sendTransfer() { viewModelScope.launch(ioDispatcher) { - runCatching { - val uuid = uploadManager.createAndGetUpload(generateNewUploadSession()).uuid - uploadManager.initUploadSession( - attestationHeaderName = AppIntegrityManager.ATTESTATION_TOKEN_HEADER, - attestationToken = attestationToken, - )!! // TODO: Handle ContainerErrorsException here - uploadWorkerScheduler.scheduleWork(uuid) - _sendActionResult.update { - val totalSize = importationFilesManager.importedFiles.value.sumOf { it.fileSize } - SendActionResult.Success(totalSize) - } - }.onFailure { exception -> - SentryLog.e(TAG, "Failed to start the upload", exception) - _sendActionResult.update { SendActionResult.Failure } - } + transferSendManager.sendTransfer(generateNewUploadSession()) } } fun resetSendActionResult() { - _sendActionResult.value = SendActionResult.NotStarted - } - - //region App Integrity - fun checkAppIntegrity() { - _integrityCheckResult.value = AppIntegrityResult.Ongoing - viewModelScope.launch(ioDispatcher) { - runCatching { - appIntegrityManager.getChallenge( - onSuccess = { requestAppIntegrityToken(appIntegrityManager) }, - onFailure = ::setFailedIntegrityResult, - ) - }.onFailure { exception -> - SentryLog.e(TAG, "Failed to start the upload", exception) - _sendActionResult.update { SendActionResult.Failure } - } - } - } - - private fun requestAppIntegrityToken(appIntegrityManager: AppIntegrityManager) { - appIntegrityManager.requestClassicIntegrityVerdictToken( - onSuccess = { token -> - SentryLog.i(APP_INTEGRITY_MANAGER_TAG, "request for app integrity token successful $token") - getApiIntegrityVerdict(appIntegrityManager, token) - }, - onFailure = ::setFailedIntegrityResult, - ) - } - - private fun getApiIntegrityVerdict(appIntegrityManager: AppIntegrityManager, appIntegrityToken: String) { - viewModelScope.launch(ioDispatcher) { - appIntegrityManager.getApiIntegrityVerdict( - integrityToken = appIntegrityToken, - packageName = BuildConfig.APPLICATION_ID, - targetUrl = sharedApiUrlCreator.createUploadContainerUrl, - onSuccess = { attestationToken -> - SentryLog.i(APP_INTEGRITY_MANAGER_TAG, "Api verdict check") - Log.i(APP_INTEGRITY_MANAGER_TAG, "getApiIntegrityVerdict: $attestationToken") - _integrityCheckResult.value = AppIntegrityResult.Success - sendTransfer(attestationToken) - }, - onFailure = ::setFailedIntegrityResult, - ) - } - } - - private fun setFailedIntegrityResult() { - _integrityCheckResult.value = AppIntegrityResult.Fail + transferSendManager.resetSendActionResult() } fun resetIntegrityCheckResult() { - _integrityCheckResult.value = AppIntegrityResult.Idle + transferSendManager.resetIntegrityCheckResult() } - //endregion private suspend fun removeOldData() { importationFilesManager.removeLocalCopyFolder() diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/TransferSendManager.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/TransferSendManager.kt new file mode 100644 index 000000000..3f03691b7 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/TransferSendManager.kt @@ -0,0 +1,142 @@ +/* + * Infomaniak SwissTransfer - Android + * Copyright (C) 2024 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.swisstransfer.ui.screen.newtransfer + +import android.util.Log +import com.infomaniak.core2.appintegrity.AppIntegrityManager +import com.infomaniak.core2.appintegrity.AppIntegrityManager.Companion.APP_INTEGRITY_MANAGER_TAG +import com.infomaniak.multiplatform_swisstransfer.SharedApiUrlCreator +import com.infomaniak.multiplatform_swisstransfer.data.NewUploadSession +import com.infomaniak.multiplatform_swisstransfer.managers.UploadManager +import com.infomaniak.sentry.SentryLog +import com.infomaniak.swisstransfer.BuildConfig +import com.infomaniak.swisstransfer.ui.screen.newtransfer.ImportFilesViewModel.AppIntegrityResult +import com.infomaniak.swisstransfer.ui.screen.newtransfer.ImportFilesViewModel.SendActionResult +import com.infomaniak.swisstransfer.workers.UploadWorker +import dagger.hilt.android.scopes.ViewModelScoped +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@ViewModelScoped +class TransferSendManager @Inject constructor( + private val appIntegrityManager: AppIntegrityManager, + private val importationFilesManager: ImportationFilesManager, + private val sharedApiUrlCreator: SharedApiUrlCreator, + private val uploadManager: UploadManager, + private val uploadWorkerScheduler: UploadWorker.Scheduler, +) { + + private val _sendActionResult = MutableStateFlow(SendActionResult.NotStarted) + val sendActionResult = _sendActionResult.asStateFlow() + + private val _integrityCheckResult = MutableStateFlow(AppIntegrityResult.Idle) + val integrityCheckResult = _integrityCheckResult.asStateFlow() + + //region App Integrity + suspend fun sendTransfer(newUploadSession: NewUploadSession) { + _integrityCheckResult.value = AppIntegrityResult.Ongoing + coroutineScope { + runCatching { + appIntegrityManager.getChallenge( + onSuccess = { requestAppIntegrityToken(appIntegrityManager, newUploadSession) }, + onFailure = ::setFailedIntegrityResult, + ) + }.onFailure { exception -> + SentryLog.e(TAG, "Failed to start the upload", exception) + _sendActionResult.update { SendActionResult.Failure } + } + } + } + + private fun CoroutineScope.requestAppIntegrityToken( + appIntegrityManager: AppIntegrityManager, + newUploadSession: NewUploadSession, + ) { + appIntegrityManager.requestClassicIntegrityVerdictToken( + onSuccess = { token -> + SentryLog.i(APP_INTEGRITY_MANAGER_TAG, "request for app integrity token successful $token") + getApiIntegrityVerdict(appIntegrityManager, token, newUploadSession) + }, + onFailure = ::setFailedIntegrityResult, + ) + } + + private fun CoroutineScope.getApiIntegrityVerdict( + appIntegrityManager: AppIntegrityManager, + appIntegrityToken: String, + newUploadSession: NewUploadSession, + ) { + launch { + appIntegrityManager.getApiIntegrityVerdict( + integrityToken = appIntegrityToken, + packageName = BuildConfig.APPLICATION_ID, + targetUrl = sharedApiUrlCreator.createUploadContainerUrl, + onSuccess = { attestationToken -> + SentryLog.i(APP_INTEGRITY_MANAGER_TAG, "Api verdict check") + Log.i(APP_INTEGRITY_MANAGER_TAG, "getApiIntegrityVerdict: $attestationToken") + _integrityCheckResult.value = AppIntegrityResult.Success + sendTransfer(attestationToken, newUploadSession) + }, + onFailure = ::setFailedIntegrityResult, + ) + } + } + + private fun setFailedIntegrityResult() { + _integrityCheckResult.value = AppIntegrityResult.Fail + } + + fun resetIntegrityCheckResult() { + _integrityCheckResult.value = AppIntegrityResult.Idle + } + //endregion + + fun resetSendActionResult() { + _sendActionResult.value = SendActionResult.NotStarted + } + + private fun CoroutineScope.sendTransfer(attestationToken: String, newUploadSession: NewUploadSession) { + _sendActionResult.update { SendActionResult.Pending } + launch { + runCatching { + val uuid = uploadManager.createAndGetUpload(newUploadSession).uuid + uploadManager.initUploadSession( + attestationHeaderName = AppIntegrityManager.ATTESTATION_TOKEN_HEADER, + attestationToken = attestationToken, + )!! // TODO: Handle ContainerErrorsException here + uploadWorkerScheduler.scheduleWork(uuid) + _sendActionResult.update { + val totalSize = importationFilesManager.importedFiles.value.sumOf { it.fileSize } + SendActionResult.Success(totalSize) + } + }.onFailure { exception -> + SentryLog.e(TAG, "Failed to start the upload", exception) + _sendActionResult.update { SendActionResult.Failure } + } + } + } + + companion object { + private val TAG = TransferSendManager::class.java.simpleName + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/ImportFilesScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/ImportFilesScreen.kt index f8b338d51..2e40b756b 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/ImportFilesScreen.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/ImportFilesScreen.kt @@ -144,7 +144,7 @@ fun ImportFilesScreen( addFiles = importFilesViewModel::importFiles, closeActivity = closeActivity, integrityCheckResult = { integrityCheckResult }, - checkAppIntegrity = importFilesViewModel::checkAppIntegrity, + sendTransfer = importFilesViewModel::sendTransfer, shouldStartByPromptingUserForFiles = true, isTransferStarted = { sendActionResult != SendActionResult.NotStarted }, snackbarHostState = snackbarHostState, @@ -202,7 +202,7 @@ private fun ImportFilesScreen( closeActivity: () -> Unit, shouldStartByPromptingUserForFiles: Boolean, integrityCheckResult: () -> AppIntegrityResult, - checkAppIntegrity: () -> Unit, + sendTransfer: () -> Unit, isTransferStarted: () -> Boolean, snackbarHostState: SnackbarHostState? = null, ) { @@ -226,7 +226,7 @@ private fun ImportFilesScreen( shouldShowEmailAddressesFields = { shouldShowEmailAddressesFields }, transferAuthorEmail = transferAuthorEmail, integrityCheckResult = integrityCheckResult, - checkAppIntegrityThenSendTransfer = checkAppIntegrity, + sendTransfer = sendTransfer, isTransferStarted = isTransferStarted, ) }, @@ -406,7 +406,7 @@ private fun SendButton( shouldShowEmailAddressesFields: () -> Boolean, transferAuthorEmail: GetSetCallbacks, integrityCheckResult: () -> AppIntegrityResult, - checkAppIntegrityThenSendTransfer: () -> Unit, + sendTransfer: () -> Unit, isTransferStarted: () -> Boolean, ) { val remainingFilesCount = filesToImportCount() @@ -431,7 +431,7 @@ private fun SendButton( showIndeterminateProgress = { integrityCheckResult() == AppIntegrityResult.Ongoing || isTransferStarted() }, enabled = { importedFiles().isNotEmpty() && !isImporting && isSenderEmailCorrect && !isTransferStarted() }, progress = progress, - onClick = { checkAppIntegrityThenSendTransfer() }, + onClick = { sendTransfer() }, ) } @@ -498,7 +498,7 @@ private fun Preview(@PreviewParameter(FileUiListPreviewParameter::class) files: closeActivity = {}, shouldStartByPromptingUserForFiles = false, integrityCheckResult = { AppIntegrityResult.Idle }, - checkAppIntegrity = {}, + sendTransfer = {}, isTransferStarted = { false }, ) } From c83d626f297c7d3ab8d34fc1d3427835f3fdfb45 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 18 Dec 2024 14:18:48 +0100 Subject: [PATCH 16/16] docs: Add todo to simplify ui state of the import screen --- .../swisstransfer/ui/screen/newtransfer/TransferSendManager.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/TransferSendManager.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/TransferSendManager.kt index 3f03691b7..edef6f222 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/TransferSendManager.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/TransferSendManager.kt @@ -46,6 +46,7 @@ class TransferSendManager @Inject constructor( private val uploadWorkerScheduler: UploadWorker.Scheduler, ) { + // TODO: Merge these two ui states in a single one for the whole flow of logic private val _sendActionResult = MutableStateFlow(SendActionResult.NotStarted) val sendActionResult = _sendActionResult.asStateFlow()