diff --git a/Core b/Core
index 12d648f83..157673f75 160000
--- a/Core
+++ b/Core
@@ -1 +1 @@
-Subproject commit 12d648f832cba5b1ee7554c9f135993033b7f40b
+Subproject commit 157673f75373404f1e73a2ff20b347a75ec92600
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7464268d7..d181cb7e2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -38,9 +38,11 @@
.
+ */
+package com.infomaniak.swisstransfer.backup
+
+import android.app.backup.FullBackupDataOutput
+import com.infomaniak.core.auth.backup.withBlockStoreCredentialsBackup
+import com.infomaniak.core.common.backup.FullBackupAgent
+import com.infomaniak.swisstransfer.ui.MainApplication
+
+class SwissTransferFullBackupAgent : FullBackupAgent(RestorationPolicy.AllBackedUpFiles) {
+
+ override fun onCreate() {
+ super.onCreate()
+ MainApplication.configureSentry()
+ }
+
+ override fun onFullBackup(data: FullBackupDataOutput) = withBlockStoreCredentialsBackup {
+ super.onFullBackup(data)
+ }
+}
diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/MainApplication.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/MainApplication.kt
index c2909c467..6559203e6 100644
--- a/app/src/main/java/com/infomaniak/swisstransfer/ui/MainApplication.kt
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/MainApplication.kt
@@ -18,6 +18,8 @@
package com.infomaniak.swisstransfer.ui
import android.app.Application
+import android.app.backup.BackupAgent
+import android.content.Context
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import com.infomaniak.core.common.AssociatedUserDataCleanable
@@ -93,8 +95,6 @@ class MainApplication : Application(), Configuration.Provider {
override val workManagerConfiguration: Configuration
get() = Configuration.Builder().setWorkerFactory(workerFactory).build()
- private val applicationScope = CoroutineScope(Dispatchers.Default + CoroutineName("MainApplication"))
-
override fun onCreate() {
super.onCreate()
@@ -136,30 +136,37 @@ class MainApplication : Application(), Configuration.Provider {
)
}
- /**
- * Reasons to discard Sentry events :
- * - Application is in Debug mode
- * - User deactivated Sentry tracking in DataManagement settings
- * - The exception was a NetworkException or a [CancellationException] or a [KmpNetworkException],
- * and we don't want to send them to Sentry
- */
- private fun configureSentry() {
- val isSentryEnabled: StateFlow = dataManagementDataStore.data
- .map { prefs ->
- prefs[IsSentryAuthorized.dataStoreKey] ?: DataManagementPreferencesDefaults.IsSentryAuthorizedDefault
- }
- .stateIn(applicationScope, SharingStarted.Eagerly, initialValue = false)
-
- this.configureSentry(
- isDebug = BuildConfig.DEBUG,
- isSentryTrackingEnabled = { isSentryEnabled.value },
- isFilteredException = { exception -> exception is KmpNetworkException },
- )
- }
-
companion object {
@JvmStatic
var userDataCleanableList: List = emptyList()
private set
+
+ private val applicationScope = CoroutineScope(Dispatchers.Default + CoroutineName("MainApplication"))
+
+ context(context: BackupAgent)
+ fun configureSentry() {
+ context.configureSentry()
+ }
+
+ /**
+ * Reasons to discard Sentry events :
+ * - Application is in Debug mode
+ * - User deactivated Sentry tracking in DataManagement settings
+ * - The exception was a NetworkException or a [CancellationException] or a [KmpNetworkException],
+ * and we don't want to send them to Sentry
+ */
+ private fun Context.configureSentry() {
+ val isSentryEnabled: StateFlow = dataManagementDataStore.data
+ .map { prefs ->
+ prefs[IsSentryAuthorized.dataStoreKey] ?: DataManagementPreferencesDefaults.IsSentryAuthorizedDefault
+ }
+ .stateIn(applicationScope, SharingStarted.Eagerly, initialValue = false)
+
+ configureSentry(
+ isDebug = BuildConfig.DEBUG,
+ isSentryTrackingEnabled = { isSentryEnabled.value },
+ isFilteredException = { exception -> exception is KmpNetworkException },
+ )
+ }
}
}
diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/transfer/TransferItemList.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/transfer/TransferItemList.kt
index dc2b33b35..85934b826 100644
--- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/transfer/TransferItemList.kt
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/transfer/TransferItemList.kt
@@ -32,6 +32,8 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.movableContentOf
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
@@ -64,6 +66,7 @@ fun TransferItemList(
emptyState: @Composable () -> Unit,
modifier: Modifier = Modifier,
) {
+ val movableEmptyState = remember(emptyState) { movableContentOf { emptyState() } }
val headerContent = @Composable {
Column(verticalArrangement = Arrangement.spacedBy(Margin.Mini)) {
SmallOrMediumWindowScreenTitle(title = header.title)
@@ -79,10 +82,10 @@ fun TransferItemList(
if (header.showWhenEmpty()) {
Column(modifier = Modifier.fillMaxHeight()) {
Box(modifier = Modifier.padding(horizontal = Margin.Medium, vertical = Margin.Large)) { headerContent() }
- Box(modifier = Modifier.weight(1.0f)) { emptyState() }
+ Box(modifier = Modifier.weight(1.0f)) { movableEmptyState() }
}
} else {
- emptyState()
+ movableEmptyState()
}
} else {
TransferItemList(
diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt
index fc9f963a0..b3af72bcc 100644
--- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt
@@ -67,6 +67,7 @@ fun SettingItem(
.fillMaxWidth()
.heightIn(min = ITEM_MIN_HEIGHT)
+ @Suppress("ComposeModifierReused") // Fine because it's only used once at a time.
onClick?.let {
SharpRippleButton(
modifier = itemModifier,
diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transferdetails/TransferDownloadComposeUi.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transferdetails/TransferDownloadComposeUi.kt
index 75de5870b..53962a43a 100644
--- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transferdetails/TransferDownloadComposeUi.kt
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transferdetails/TransferDownloadComposeUi.kt
@@ -289,6 +289,7 @@ class TransferDownloadComposeUi(
@Composable
private fun DownloadStatus(
+ @Suppress("SlotReused") // Irrelevant for our use case where the parameters change on each when branch.
button: @Composable (
data: ButtonData,
action: CallableState,
diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transferdetails/components/ExistingTransferFilesDetailsScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transferdetails/components/ExistingTransferFilesDetailsScreen.kt
index 268d94e2f..348f7b6c0 100644
--- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transferdetails/components/ExistingTransferFilesDetailsScreen.kt
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transferdetails/components/ExistingTransferFilesDetailsScreen.kt
@@ -127,10 +127,14 @@ fun ExistingTransferFilesDetailsScreen(
val selectedFiles = fileList.filter { it.uid in selectedUids }
ExistingTransferFilesDetailsBottomBar(
selectedFiles = { selectedFiles },
- transferIdType = transferIdType,
- filesDetailsViewModel = filesDetailsViewModel,
+ onDownloadSelectionClick = {
+ filesDetailsViewModel.triggerFilesSelectionDownload(
+ transferIdType = transferIdType,
+ selectedFiles = selectedFiles,
+ direction = transferDirection
+ )
+ },
onCancelSelection = onCancelSelection,
- direction = transferDirection,
)
}
}
@@ -217,9 +221,7 @@ private fun ExistingTransferFilesDetailsTopBar(
@Composable
private fun ExistingTransferFilesDetailsBottomBar(
selectedFiles: () -> List,
- transferIdType: TransferIdType,
- direction: TransferDirection,
- filesDetailsViewModel: FilesDetailsViewModel,
+ onDownloadSelectionClick: () -> Unit,
onCancelSelection: () -> Unit,
) {
val writePermissionManager = rememberPermissionManagerState(PermissionType.WriteExternalStorage)
@@ -229,7 +231,7 @@ private fun ExistingTransferFilesDetailsBottomBar(
labelResId = R.string.buttonDownloadSelected,
enabled = selectedFiles().isNotEmpty(),
onClick = writePermissionManager.dropIfDenied {
- filesDetailsViewModel.triggerFilesSelectionDownload(transferIdType, selectedFiles(), direction)
+ onDownloadSelectionClick()
onCancelSelection()
},
modifier = Modifier.weight(1f),
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 777cdf19f..748153edb 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
@@ -66,6 +66,7 @@ import com.infomaniak.swisstransfer.ui.utils.isWindowSmall
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
+@Suppress("ComposeViewModelForwarding")
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
fun TransfersScreenWrapper(
@@ -125,6 +126,7 @@ private fun ThreePaneScaffoldNavigator.HandleDeepLink(
}
}
+@Suppress("ComposeViewModelForwarding")
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
private fun ListPane(
diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml
index 04b95c673..981c6ab66 100644
--- a/app/src/main/res/xml/backup_rules.xml
+++ b/app/src/main/res/xml/backup_rules.xml
@@ -17,13 +17,17 @@
-->
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
index c2056997a..46181ad04 100644
--- a/app/src/main/res/xml/data_extraction_rules.xml
+++ b/app/src/main/res/xml/data_extraction_rules.xml
@@ -23,22 +23,36 @@
-->
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+