Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Core
Submodule Core updated 53 files
+1 −0 AGENTS.md
+3 −0 Auth/build.gradle.kts
+24 −0 Auth/src/fdroid/kotlin/com/infomaniak/core/auth/backup/BlockStoreBackup.kt
+0 −4 Auth/src/main/kotlin/com/infomaniak/core/auth/BaseCredentialManager.kt
+82 −0 Auth/src/main/kotlin/com/infomaniak/core/auth/backup/BlockStoreCredentialsBackup.kt
+41 −4 Auth/src/main/kotlin/com/infomaniak/core/auth/backup/RestoreFromBackupManagerImpl.kt
+4 −1 Auth/src/main/kotlin/com/infomaniak/core/auth/room/UserDao.kt
+120 −0 Auth/src/standard/kotlin/com/infomaniak/core/auth/backup/BlockStoreBackup.kt
+8 −1 Auth/src/test/java/com/infomaniak/core/auth/BaseAccountUtilsTest.kt
+10 −0 Common/src/main/kotlin/com/infomaniak/core/common/backup/FullBackupAgent.kt
+3 −0 Common/src/main/res/values-da/strings.xml
+3 −0 Common/src/main/res/values-de/strings.xml
+3 −0 Common/src/main/res/values-el/strings.xml
+3 −0 Common/src/main/res/values-es/strings.xml
+3 −0 Common/src/main/res/values-fi/strings.xml
+3 −0 Common/src/main/res/values-fr/strings.xml
+3 −0 Common/src/main/res/values-it/strings.xml
+3 −0 Common/src/main/res/values-nb/strings.xml
+3 −0 Common/src/main/res/values-nl/strings.xml
+3 −0 Common/src/main/res/values-pl/strings.xml
+3 −0 Common/src/main/res/values-pt/strings.xml
+3 −0 Common/src/main/res/values-sv/strings.xml
+3 −0 Common/src/main/res/values/strings.xml
+3 −25 CrossAppLogin/Front/lint-baseline.xml
+3 −3 InAppUpdate/lint-baseline.xml
+2 −2 KSuite/KSuitePro/lint-baseline.xml
+61 −61 KSuite/MyKSuite/lint-baseline.xml
+1 −0 LICENSES.md
+3 −3 Onboarding/lint-baseline.xml
+6 −3 Sentry/src/main/kotlin/com/infomaniak/core/sentry/SentryConfig.kt
+4 −4 TwoFactorAuth/Front/lint-baseline.xml
+62 −0 Ui/Compose/Basics/src/main/kotlin/com/infomaniak/core/ui/compose/basics/ClipboardCopyManager.kt
+2 −2 Ui/Compose/BottomStickyButtonScaffolds/lint-baseline.xml
+2 −0 Ui/Compose/ContactCard/build.gradle.kts
+5 −4 Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardShareExt.kt
+5 −5 Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardViewModel.kt
+2 −1 ...ntactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewActionsBottomSheet.kt
+0 −1 Ui/Compose/ContactCard/src/main/res/values-da/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-de/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-el/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-es/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-fi/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-fr/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-it/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-nb/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-nl/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-pl/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-pt/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values-sv/strings.xml
+0 −1 Ui/Compose/ContactCard/src/main/res/values/strings.xml
+34 −0 Ui/Compose/ContactCard/src/test/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardShareExtTest.kt
+37 −0 Ui/Compose/Theme/src/main/kotlin/com/infomaniak/core/ui/compose/theme/MaterialPreviewTheme.kt
+3 −1 gradle/core.versions.toml
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@
<application
android:name=".ui.MainApplication"
android:allowBackup="true"
android:backupAgent=".backup.SwissTransferFullBackupAgent"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_rules"
android:fullBackupOnly="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/appName"
android:networkSecurityConfig="@xml/network_security_config"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Infomaniak SwissTransfer - Android
* Copyright (C) 2026 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 <http://www.gnu.org/licenses/>.
*/
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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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<Boolean> = 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<AssociatedUserDataCleanable> = 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<Boolean> = 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 },
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
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
Expand Down Expand Up @@ -64,6 +66,7 @@
emptyState: @Composable () -> Unit,
modifier: Modifier = Modifier,
) {
val movableEmptyState = remember(emptyState) { movableContentOf { emptyState() } }

Check warning on line 69 in app/src/main/java/com/infomaniak/swisstransfer/ui/components/transfer/TransferItemList.kt

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused "movableEmptyState" local variable.

See more on https://sonarcloud.io/project/issues?id=Infomaniak_android-SwissTransfer&issues=AaDyHJy7w3WFV53qy_bQ&open=AaDyHJy7w3WFV53qy_bQ&pullRequest=698
val headerContent = @Composable {
Column(verticalArrangement = Arrangement.spacedBy(Margin.Mini)) {
SmallOrMediumWindowScreenTitle(title = header.title)
Expand All @@ -79,10 +82,10 @@
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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Unit>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
}
}
Expand Down Expand Up @@ -217,9 +221,7 @@ private fun ExistingTransferFilesDetailsTopBar(
@Composable
private fun ExistingTransferFilesDetailsBottomBar(
selectedFiles: () -> List<FileUi>,
transferIdType: TransferIdType,
direction: TransferDirection,
filesDetailsViewModel: FilesDetailsViewModel,
onDownloadSelectionClick: () -> Unit,
onCancelSelection: () -> Unit,
) {
val writePermissionManager = rememberPermissionManagerState(PermissionType.WriteExternalStorage)
Expand All @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -125,6 +126,7 @@ private fun ThreePaneScaffoldNavigator<DestinationContent>.HandleDeepLink(
}
}

@Suppress("ComposeViewModelForwarding")
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
private fun ListPane(
Expand Down
20 changes: 12 additions & 8 deletions app/src/main/res/xml/backup_rules.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@
-->

<full-backup-content>
<include domain="root" path="." />
<include domain="file" path="." />
<include domain="sharedpref" path="." />
<include domain="external" path="." />
<include domain="database" path="." />
<include domain="sharedpref" path="AccountPreferences" />

<exclude domain="database" path="user_database" />
<exclude domain="database" path="user_database-shm" />
<exclude domain="database" path="user_database-wal" />
<include domain="database" path="user_database" />
<include domain="database" path="swisstransfer" />

<include domain="sharedpref" path="AccountPreferences" />

<include domain="file" path="AppSettings.realm" />
<include domain="file" path="AppSettings.realm.management/" />

<!-- Actual user id for this Realm DB is always -1. -->
<include domain="file" path="Transfers--1.realm" />
<include domain="file" path="Transfers--1.realm.management/" />
</full-backup-content>
38 changes: 26 additions & 12 deletions app/src/main/res/xml/data_extraction_rules.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,36 @@
-->
<data-extraction-rules>
<cloud-backup>
<include domain="root" path="." />
<include domain="file" path="." />
<include domain="sharedpref" path="." />
<include domain="external" path="." />
<include domain="database" path="." />
<include domain="sharedpref" path="AccountPreferences" />

<include domain="database" path="user_database" />
<include domain="database" path="swisstransfer" />

<include domain="sharedpref" path="AccountPreferences" />

<exclude domain="database" path="user_database" />
<exclude domain="database" path="user_database-shm" />
<exclude domain="database" path="user_database-wal" />
<include domain="file" path="AppSettings.realm" />
<include domain="file" path="AppSettings.realm.management/" />

<!-- Actual user id for this Realm DB is always -1. -->
<include domain="file" path="Transfers--1.realm" />
<include domain="file" path="Transfers--1.realm.management/" />
</cloud-backup>

<device-transfer>
<include domain="root" path="." />
<include domain="file" path="." />
<include domain="file" path="thumbnails" />

<include domain="database" path="." />
<include domain="sharedpref" path="." />
<include domain="external" path="." />

<include domain="sharedpref" path="AccountPreferences" />

<include domain="file" path="AppSettings.realm" />
<include domain="file" path="AppSettings.realm.management/" />

<include domain="file" path="AppSettings.realm" />
<include domain="file" path="AppSettings.realm.management/" />

<!-- Actual user id for this Realm DB is always -1. -->
<include domain="file" path="Transfers--1.realm" />
<include domain="file" path="Transfers--1.realm.management/" />
</device-transfer>
</data-extraction-rules>
Loading