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 122b5c294..e845db59a 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 @@ -26,6 +26,7 @@ import androidx.navigation.navDeepLink import androidx.navigation.toRoute import com.infomaniak.core.sentry.SentryLog import com.infomaniak.swisstransfer.BuildConfig +import com.infomaniak.swisstransfer.ui.MatomoSwissTransfer import com.infomaniak.swisstransfer.ui.navigation.MainNavigation.SettingsDestination.getDeeplinkDirection import com.infomaniak.swisstransfer.ui.screen.main.DeeplinkViewModel.Companion.SENT_DEEPLINK_SUFFIX import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.components.TransferTypeUi @@ -35,7 +36,7 @@ import kotlinx.serialization.Serializable * Sealed class representing the navigation arguments for the main navigation flow. */ @Serializable -sealed class MainNavigation : NavigationDestination() { +sealed class MainNavigation(override val matomoValue: String) : NavigationDestination() { protected inline fun NavGraphBuilder.getDeeplinkDirection( noinline content: @Composable (AnimatedContentScope.(NavBackStackEntry) -> Unit), @@ -50,7 +51,7 @@ sealed class MainNavigation : NavigationDestination() { // If it has to be renamed, don't forget to rename `*DestinationName` in the companion object too. @Serializable - data class SentDestination(val transferUuid: String? = null) : MainNavigation() { + data class SentDestination(val transferUuid: String? = null) : MainNavigation("SentScreen") { companion object { fun NavGraphBuilder.sentDestination(content: @Composable (AnimatedContentScope.(NavBackStackEntry) -> Unit)) { @@ -61,7 +62,7 @@ sealed class MainNavigation : NavigationDestination() { // 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() { + data class ReceivedDestination(val transferUuid: String? = null) : MainNavigation("ReceivedScreen") { companion object { fun NavGraphBuilder.receivedDestination(content: @Composable (AnimatedContentScope.(NavBackStackEntry) -> Unit)) { @@ -71,7 +72,7 @@ sealed class MainNavigation : NavigationDestination() { } @Serializable - data object SettingsDestination : MainNavigation() + data object SettingsDestination : MainNavigation("SettingsScreen") companion object { private val TAG = MainNavigation::class.java.simpleName @@ -110,43 +111,81 @@ sealed class MainNavigation : NavigationDestination() { * Sealed class representing the navigation arguments for the new transfer flow. */ @Serializable -sealed class NewTransferNavigation : NavigationDestination() { +sealed class NewTransferNavigation(override val matomoValue: String) : NavigationDestination() { @Serializable - data object ImportFilesDestination : NewTransferNavigation() + data object ImportFilesDestination : NewTransferNavigation("ImportFileScreen") @Serializable - data class ValidateUserEmailDestination(val authorEmail: String) : NewTransferNavigation() + data class ValidateUserEmailDestination(val authorEmail: String) : NewTransferNavigation("ValidateUserEmailScreen") @Serializable data class UploadProgressDestination( val transferType: TransferTypeUi, val totalSize: Long, val authorEmail: String?, - ) : NewTransferNavigation() + ) : NewTransferNavigation("UploadProgressScreen") @Serializable data class UploadSuccessDestination( val transferType: TransferTypeUi, val transferUuid: String, val transferUrl: String, - ) : NewTransferNavigation() + ) : NewTransferNavigation("UploadSuccessScreen") @Serializable data class UploadErrorDestination( val transferType: TransferTypeUi, val totalSize: Long, val authorEmail: String?, - ) : NewTransferNavigation() + ) : NewTransferNavigation("UploadErrorScreen") @Serializable - data object UploadIntegrityErrorDestination : NewTransferNavigation() + data object UploadIntegrityErrorDestination : NewTransferNavigation("UploadIntegrityErrorScreen") @Serializable - data object NewTransferFilesDetailsDestination : NewTransferNavigation() + data object NewTransferFilesDetailsDestination : NewTransferNavigation("NewTransferFilesDetailsScreen") companion object { val startDestination = ImportFilesDestination + + private val TAG = NewTransferNavigation::class.java.simpleName + + private const val importFilesDestinationName = "ImportFilesDestination" + private const val ValidateUserEmailDestinationName = "ValidateUserEmailDestination" + private const val UploadProgressDestinationName = "UploadProgressDestination" + private const val UploadSuccessDestinationName = "UploadSuccessDestination" + private const val UploadErrorDestinationName = "UploadErrorDestination" + private const val UploadIntegrityErrorDestinationName = "UploadIntegrityErrorDestination" + private const val NewTransferFilesDetailsDestinationName = "NewTransferFilesDetailsDestination" + val newTransferDestinationsNames = listOf( + importFilesDestinationName, + ValidateUserEmailDestinationName, + UploadProgressDestinationName, + UploadSuccessDestinationName, + UploadErrorDestinationName, + UploadIntegrityErrorDestinationName, + NewTransferFilesDetailsDestinationName, + ) + + fun NavBackStackEntry.toNewTransferDestination(): NewTransferNavigation? { + return runCatching { + val destinationRoute = destination.route ?: error("Destination route cannot be empty") + when (newTransferDestinationsNames.firstOrNull(destinationRoute::contains)) { + importFilesDestinationName -> this.toRoute() + ValidateUserEmailDestinationName -> this.toRoute() + UploadProgressDestinationName -> this.toRoute() + UploadSuccessDestinationName -> this.toRoute() + UploadErrorDestinationName -> this.toRoute() + UploadIntegrityErrorDestinationName -> this.toRoute() + NewTransferFilesDetailsDestinationName -> this.toRoute() + else -> error("Destination $destinationRoute is not handled") + } + }.getOrElse { exception -> + SentryLog.e(TAG, "toNewTransferDestination: Failure", exception) + null + } + } } } @@ -154,4 +193,11 @@ sealed class NewTransferNavigation : NavigationDestination() { * Sealed class representing navigation arguments with a title resource. */ @Serializable -sealed class NavigationDestination +sealed class NavigationDestination { + + abstract val matomoValue: String + + fun trackScreen() { + MatomoSwissTransfer.trackScreen(path = "/$matomoValue", title = matomoValue) + } +} 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 12a4ae24b..dbb97aab1 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 @@ -36,7 +36,9 @@ fun MainScreen(deeplinkTransferDirection: TransferDirection? = null) { val hideBottomBar = rememberSaveable { mutableStateOf(false) } val currentDestination by remember(navBackStackEntry) { - derivedStateOf { navBackStackEntry?.toMainDestination() ?: MainNavigation.startDestination } + val destination = navBackStackEntry?.toMainDestination() + destination?.trackScreen() + derivedStateOf { destination ?: MainNavigation.startDestination } } MainScaffold( diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transfers/TransfersScreenWrapper.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transfers/TransfersScreenWrapper.kt index 6e7f7be5e..9f7f8ec0d 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transfers/TransfersScreenWrapper.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transfers/TransfersScreenWrapper.kt @@ -33,6 +33,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.infomaniak.multiplatform_swisstransfer.common.models.TransferDirection import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.MatomoSwissTransfer import com.infomaniak.swisstransfer.ui.components.* import com.infomaniak.swisstransfer.ui.images.AppImages.AppIllus import com.infomaniak.swisstransfer.ui.images.illus.mascotWithMagnifyingGlass.MascotWithMagnifyingGlass @@ -140,6 +141,8 @@ private fun ThreePaneScaffoldNavigator.navigateToDetails( direction: TransferDirection, transferUuid: String, ) { + val destinationName = "${direction.name.lowercase()}TransferDetail" + MatomoSwissTransfer.trackScreen(path = destinationName, title = destinationName) selectItem(context, windowAdaptiveInfo, DestinationContent.RootLevel(direction, transferUuid)) } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/NewTransferScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/NewTransferScreen.kt index b04e83365..36f41aa4b 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/NewTransferScreen.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/NewTransferScreen.kt @@ -24,12 +24,14 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.infomaniak.swisstransfer.R import com.infomaniak.swisstransfer.ui.components.ButtonType import com.infomaniak.swisstransfer.ui.components.SmallButton import com.infomaniak.swisstransfer.ui.components.SwissTransferAlertDialog import com.infomaniak.swisstransfer.ui.navigation.NewTransferNavigation +import com.infomaniak.swisstransfer.ui.navigation.NewTransferNavigation.Companion.toNewTransferDestination import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewAllWindows @@ -41,8 +43,12 @@ fun NewTransferScreen( ) { val navController = rememberNavController() + val navBackStackEntry by navController.currentBackStackEntryAsState() + var displayConfirmationDialog by rememberSaveable { mutableStateOf(false) } + navBackStackEntry?.toNewTransferDestination()?.trackScreen() + NewTransferNavHost( navController = navController, startDestination = startDestination,