diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferAlertDialog.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferAlertDialog.kt
new file mode 100644
index 000000000..e2462c187
--- /dev/null
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferAlertDialog.kt
@@ -0,0 +1,134 @@
+/*
+ * 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.components
+
+import androidx.annotation.StringRes
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.*
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import com.infomaniak.swisstransfer.R
+import com.infomaniak.swisstransfer.ui.theme.Margin
+import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun SwissTransferAlertDialog(
+ modifier: Modifier = Modifier,
+ @StringRes titleRes: Int,
+ @StringRes descriptionRes: Int,
+ onDismiss: () -> Unit,
+ onConfirmation: () -> Unit,
+ shouldEnableConfirmButton: () -> Boolean = { true },
+ content: @Composable (ColumnScope.() -> Unit)? = null,
+) {
+ BasicAlertDialog(
+ onDismissRequest = onDismiss,
+ modifier = Modifier
+ .wrapContentHeight()
+ .fillMaxWidth(),
+ ) {
+ Card(shape = RoundedCornerShape(Margin.Medium)) {
+ BasicAlertDialogContent(
+ modifier = modifier,
+ titleRes = titleRes,
+ descriptionRes = descriptionRes,
+ additionalContent = content,
+ onDismiss = onDismiss,
+ onConfirmation = onConfirmation,
+ shouldEnableConfirmButton = shouldEnableConfirmButton,
+ )
+ }
+ }
+}
+
+@Composable
+private fun BasicAlertDialogContent(
+ modifier: Modifier,
+ @StringRes titleRes: Int,
+ @StringRes descriptionRes: Int,
+ additionalContent: @Composable (ColumnScope.() -> Unit)? = null,
+ onDismiss: () -> Unit,
+ onConfirmation: () -> Unit,
+ shouldEnableConfirmButton: () -> Boolean = { true },
+) {
+ Column(modifier.padding(Margin.Large)) {
+ TitleAndDescription(titleRes, descriptionRes)
+ Spacer(Modifier.height(Margin.Large))
+ additionalContent?.let {
+ it()
+ Spacer(Modifier.height(Margin.Large))
+ }
+ ActionButtons(onDismiss, onConfirmation, shouldEnableConfirmButton)
+ }
+}
+
+@Composable
+private fun TitleAndDescription(titleRes: Int, descriptionRes: Int) {
+ Text(
+ text = stringResource(titleRes),
+ style = SwissTransferTheme.typography.bodyMedium,
+ color = SwissTransferTheme.colors.primaryTextColor,
+ )
+ Spacer(Modifier.height(Margin.Large))
+ Text(
+ text = stringResource(descriptionRes),
+ style = SwissTransferTheme.typography.bodyRegular,
+ color = SwissTransferTheme.colors.secondaryTextColor,
+ )
+}
+
+@Composable
+private fun ActionButtons(onDismissRequest: () -> Unit, onConfirmation: () -> Unit, shouldEnable: () -> Boolean) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.End,
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ SmallButton(
+ style = ButtonType.TERTIARY,
+ titleRes = R.string.buttonCancel,
+ onClick = onDismissRequest,
+ )
+ Spacer(Modifier.width(Margin.Micro))
+ SmallButton(
+ titleRes = R.string.buttonConfirm,
+ onClick = onConfirmation,
+ enabled = shouldEnable
+ )
+ }
+}
+
+@Preview
+@Composable
+private fun PreviewAlertDialog() {
+ SwissTransferTheme {
+ Surface {
+ SwissTransferAlertDialog(
+ titleRes = R.string.settingsOptionPassword,
+ descriptionRes = R.string.settingsPasswordDescription,
+ onDismiss = {},
+ onConfirmation = {},
+ )
+ }
+ }
+}
diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferTextField.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferTextField.kt
index 1dc9e6ada..a38b97104 100644
--- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferTextField.kt
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferTextField.kt
@@ -20,6 +20,7 @@ package com.infomaniak.swisstransfer.ui.components
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
@@ -30,6 +31,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
@@ -57,7 +59,9 @@ fun SwissTransferTextField(
maxLineNumber: Int = if (minLineNumber > 1) Int.MAX_VALUE else 1,
isPassword: Boolean = false,
keyboardType: KeyboardType = KeyboardType.Text,
- errorMessage: () -> String? = { null },
+ imeAction: ImeAction = ImeAction.Default,
+ keyboardActions: KeyboardActions = KeyboardActions.Default,
+ errorMessage: @Composable () -> String? = { null },
supportingText: String? = null,
onValueChange: ((String) -> Unit)? = null,
) {
@@ -72,6 +76,17 @@ fun SwissTransferTextField(
unfocusedSupportingTextColor = SwissTransferTheme.colors.tertiaryTextColor,
)
+ @Composable
+ fun getSupportingText(): (@Composable () -> Unit)? {
+ val displayText = if (text.isEmpty()) {
+ supportingText
+ } else {
+ errorMessage() ?: supportingText
+ }
+
+ return displayText?.let { @Composable { Text(it) } }
+ }
+
OutlinedTextField(
modifier = modifier,
value = text,
@@ -95,9 +110,11 @@ fun SwissTransferTextField(
keyboardOptions = KeyboardOptions(
keyboardType = if (isPassword) KeyboardType.Password else keyboardType,
autoCorrectEnabled = true,
+ imeAction = imeAction,
),
- isError = errorMessage() != null,
- supportingText = (errorMessage() ?: supportingText)?.let { { Text(it) } },
+ keyboardActions = keyboardActions,
+ isError = errorMessage() != null && text.isNotEmpty(),
+ supportingText = getSupportingText(),
)
}
diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsViewModel.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsViewModel.kt
index bd66f0b39..732d2ce31 100644
--- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsViewModel.kt
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsViewModel.kt
@@ -25,7 +25,6 @@ import com.infomaniak.multiplatform_swisstransfer.common.models.Theme
import com.infomaniak.multiplatform_swisstransfer.common.models.ValidityPeriod
import com.infomaniak.multiplatform_swisstransfer.managers.AppSettingsManager
import com.infomaniak.swisstransfer.di.IoDispatcher
-import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.PasswordTransferOption
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.launch
@@ -54,11 +53,4 @@ class SettingsViewModel @Inject constructor(
fun setEmailLanguage(emailLanguage: EmailLanguage) = viewModelScope.launch(ioDispatcher) {
appSettingsManager.setEmailLanguage(emailLanguage)
}
-
- data class AppSettingsData(
- val validityPeriod: ValidityPeriod,
- val downloadLimit: DownloadLimit,
- val passwordOption: PasswordTransferOption,
- val emailLanguage: EmailLanguage,
- )
}
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 264b23edc..7375b875f 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,15 +18,16 @@
package com.infomaniak.swisstransfer.ui.screen.newtransfer
import android.net.Uri
+import androidx.compose.runtime.*
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.infomaniak.multiplatform_swisstransfer.common.interfaces.appSettings.AppSettings
import com.infomaniak.multiplatform_swisstransfer.common.interfaces.upload.RemoteUploadFile
import com.infomaniak.multiplatform_swisstransfer.common.interfaces.upload.UploadFileSession
import com.infomaniak.multiplatform_swisstransfer.common.models.EmailLanguage
import com.infomaniak.multiplatform_swisstransfer.common.utils.mapToList
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.di.IoDispatcher
@@ -36,8 +37,12 @@ import com.infomaniak.swisstransfer.ui.screen.main.settings.EmailLanguageOption
import com.infomaniak.swisstransfer.ui.screen.main.settings.EmailLanguageOption.Companion.toAdvancedOption
import com.infomaniak.swisstransfer.ui.screen.main.settings.ValidityPeriodOption
import com.infomaniak.swisstransfer.ui.screen.main.settings.ValidityPeriodOption.Companion.toAdvancedOption
+import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingOption
+import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.AdvancedOptionsCallbacks
+import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.AdvancedOptionsState
import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.PasswordTransferOption
import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.components.TransferType
+import com.infomaniak.swisstransfer.ui.utils.GetSetCallbacks
import com.infomaniak.swisstransfer.workers.UploadWorker
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
@@ -48,6 +53,7 @@ import javax.inject.Inject
@HiltViewModel
class ImportFilesViewModel @Inject constructor(
+ private val appSettingsManager: AppSettingsManager,
private val savedStateHandle: SavedStateHandle,
private val importationFilesManager: ImportationFilesManager,
private val uploadManager: UploadManager,
@@ -104,10 +110,6 @@ class ImportFilesViewModel @Inject constructor(
}
}
- fun selectTransferType(type: TransferType) {
- _selectedTransferType.value = type
- }
-
fun sendTransfer() {
viewModelScope.launch(ioDispatcher) {
runCatching {
@@ -146,53 +148,109 @@ class ImportFilesViewModel @Inject constructor(
}
//region Transfer Type
- private val _selectedTransferType = MutableStateFlow(TransferType.LINK)
- val selectedTransferType: StateFlow = _selectedTransferType
+ val selectedTransferType = savedStateHandle.getStateFlow(SELECTED_TRANSFER_TYPE, TransferType.LINK)
- sealed class SendActionResult {
- data class Success(val totalSize: Long) : SendActionResult()
- data object Failure : SendActionResult()
+ fun selectTransferType(type: TransferType) {
+ savedStateHandle[SELECTED_TRANSFER_TYPE] = type
}
//endregion
//region Transfer Advanced Options
- private val _selectedValidityPeriodOption = MutableStateFlow(null)
- val selectedValidityPeriodOption: StateFlow = _selectedValidityPeriodOption.asStateFlow()
+ val selectedValidityPeriodOption = savedStateHandle.getStateFlow(
+ key = SELECTED_VALIDITY_PERIOD_KEY,
+ initialValue = ValidityPeriodOption.THIRTY
+ )
- private val _selectedDownloadLimitOption = MutableStateFlow(null)
- val selectedDownloadLimitOption: StateFlow = _selectedDownloadLimitOption.asStateFlow()
+ val selectedDownloadLimitOption = savedStateHandle.getStateFlow(
+ key = SELECTED_DOWNLOAD_LIMIT_KEY,
+ initialValue = DownloadLimitOption.TWO_HUNDRED_FIFTY,
+ )
- private val _selectedPasswordOption = MutableStateFlow(PasswordTransferOption.NONE)
- val selectedPasswordOption: StateFlow = _selectedPasswordOption.asStateFlow()
+ val selectedPasswordOption = savedStateHandle.getStateFlow(
+ key = SELECTED_PASSWORD_OPTION_KEY,
+ initialValue = PasswordTransferOption.NONE,
+ )
- private val _selectedLanguageOption = MutableStateFlow(null)
- val selectedLanguageOption: StateFlow = _selectedLanguageOption.asStateFlow()
+ val selectedLanguageOption = savedStateHandle.getStateFlow(
+ key = SELECTED_LANGUAGE_KEY,
+ initialValue = EmailLanguageOption.FRENCH,
+ )
- fun selectTransferValidityPeriod(validityPeriodOption: ValidityPeriodOption) {
- _selectedValidityPeriodOption.value = validityPeriodOption
+ private fun selectTransferValidityPeriod(validityPeriodOption: ValidityPeriodOption) {
+ savedStateHandle[SELECTED_VALIDITY_PERIOD_KEY] = validityPeriodOption
}
- fun selectTransferDownloadLimit(downloadLimit: DownloadLimitOption) {
- _selectedDownloadLimitOption.value = downloadLimit
+ private fun selectTransferDownloadLimit(downloadLimit: DownloadLimitOption) {
+ savedStateHandle[SELECTED_DOWNLOAD_LIMIT_KEY] = downloadLimit
}
- fun selectTransferPasswordOption(passwordOption: PasswordTransferOption) {
- _selectedPasswordOption.value = passwordOption
+ private fun selectTransferPasswordOption(passwordOption: PasswordTransferOption) {
+ savedStateHandle[SELECTED_PASSWORD_OPTION_KEY] = passwordOption
+ }
+
+ private fun selectTransferLanguage(language: EmailLanguageOption) {
+ savedStateHandle[SELECTED_LANGUAGE_KEY] = language
+ }
+
+ fun initTransferAdvancedOptionsValues() {
+ viewModelScope.launch(ioDispatcher) {
+ appSettingsManager.getAppSettings()?.let {
+ selectTransferValidityPeriod(it.validityPeriod.toAdvancedOption())
+ selectTransferDownloadLimit(it.downloadLimit.toAdvancedOption())
+ selectTransferLanguage(it.emailLanguage.toAdvancedOption())
+ } ?: run {
+ SentryLog.e(TAG, "AppSettings is null in ImportFilesScreen, it should not happened")
+ selectTransferValidityPeriod(ValidityPeriodOption.THIRTY)
+ selectTransferDownloadLimit(DownloadLimitOption.TWO_HUNDRED_FIFTY)
+ selectTransferLanguage(EmailLanguageOption.FRENCH)
+ }
+ }
}
- fun selectTransferLanguage(language: EmailLanguageOption) {
- _selectedLanguageOption.value = language
+ fun getTransferAdvancedOptionsCallbacks(advancedOptionsStates: () -> List): AdvancedOptionsCallbacks {
+ return AdvancedOptionsCallbacks(
+ advancedOptionsStates = advancedOptionsStates,
+ onAdvancedOptionsValueSelected = ::onAdvancedOptionsValueSelected,
+ password = GetSetCallbacks(
+ get = { transferPassword },
+ set = { transferPassword = it },
+ ),
+ isPasswordValid = { isPasswordValid },
+ )
}
- fun initTransferAdvancedOptionsValues(safeAppSettings: AppSettings) {
- selectTransferValidityPeriod(safeAppSettings.validityPeriod.toAdvancedOption())
- selectTransferDownloadLimit(safeAppSettings.downloadLimit.toAdvancedOption())
- selectTransferLanguage(safeAppSettings.emailLanguage.toAdvancedOption())
+ private fun onAdvancedOptionsValueSelected(option: SettingOption) {
+ when (option) {
+ is ValidityPeriodOption -> selectTransferValidityPeriod(option)
+ is DownloadLimitOption -> selectTransferDownloadLimit(option)
+ is PasswordTransferOption -> selectTransferPasswordOption(option)
+ is EmailLanguageOption -> selectTransferLanguage(option)
+ }
}
//endregion
+ //region Password
+ private var transferPassword by mutableStateOf("")
+
+ private val isPasswordValid by derivedStateOf { transferPassword.length in PASSWORD_MIN_LENGTH..PASSWORD_MAX_LENGTH }
+ //endregion
+
+ sealed class SendActionResult {
+ data class Success(val totalSize: Long) : SendActionResult()
+ data object Failure : SendActionResult()
+ }
+
companion object {
private val TAG = ImportFilesViewModel::class.java.simpleName
+
+ private const val PASSWORD_MIN_LENGTH = 6
+ private const val PASSWORD_MAX_LENGTH = 25
+
private const val IS_VIEW_MODEL_RESTORED_KEY = "IS_VIEW_MODEL_RESTORED_KEY"
+ private const val SELECTED_TRANSFER_TYPE = "SELECTED_TRANSFER_TYPE"
+ private const val SELECTED_VALIDITY_PERIOD_KEY = "SELECTED_VALIDITY_PERIOD_KEY"
+ private const val SELECTED_DOWNLOAD_LIMIT_KEY = "SELECTED_DOWNLOAD_LIMIT_KEY"
+ private const val SELECTED_PASSWORD_OPTION_KEY = "SELECTED_PASSWORD_OPTION_KEY"
+ private const val SELECTED_LANGUAGE_KEY = "SELECTED_TRANSFER_LANGUAGE_KEY"
}
}
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 0030e5444..58c80a789 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
@@ -41,7 +41,6 @@ import com.infomaniak.swisstransfer.ui.components.*
import com.infomaniak.swisstransfer.ui.previewparameter.FileUiListPreviewParameter
import com.infomaniak.swisstransfer.ui.screen.main.settings.DownloadLimitOption
import com.infomaniak.swisstransfer.ui.screen.main.settings.EmailLanguageOption
-import com.infomaniak.swisstransfer.ui.screen.main.settings.SettingsViewModel
import com.infomaniak.swisstransfer.ui.screen.main.settings.ValidityPeriodOption
import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingOption
import com.infomaniak.swisstransfer.ui.screen.newtransfer.ImportFilesViewModel
@@ -58,75 +57,64 @@ private const val TOTAL_FILE_SIZE: Long = 50_000_000_000L
@Composable
fun ImportFilesScreen(
importFilesViewModel: ImportFilesViewModel = hiltViewModel(),
- settingsViewModel: SettingsViewModel = hiltViewModel(),
closeActivity: () -> Unit,
navigateToUploadProgress: (transferType: TransferType, totalSize: Long) -> Unit,
) {
val files by importFilesViewModel.importedFilesDebounced.collectAsStateWithLifecycle()
val filesToImportCount by importFilesViewModel.filesToImportCount.collectAsStateWithLifecycle()
val currentSessionFilesCount by importFilesViewModel.currentSessionFilesCount.collectAsStateWithLifecycle()
+
val selectedTransferType by importFilesViewModel.selectedTransferType.collectAsStateWithLifecycle()
+
val validityPeriodState by importFilesViewModel.selectedValidityPeriodOption.collectAsStateWithLifecycle()
val downloadLimitState by importFilesViewModel.selectedDownloadLimitOption.collectAsStateWithLifecycle()
val passwordOptionState by importFilesViewModel.selectedPasswordOption.collectAsStateWithLifecycle()
val emailLanguageState by importFilesViewModel.selectedLanguageOption.collectAsStateWithLifecycle()
- val appSettings by settingsViewModel.appSettingsFlow.collectAsStateWithLifecycle(null)
+
val sendActionResult by importFilesViewModel.sendActionResult.collectAsStateWithLifecycle()
HandleSendActionResult({ sendActionResult }, { selectedTransferType }, navigateToUploadProgress)
- fun onAdvancedOptionsValueSelected(option: SettingOption) {
- when (option) {
- is ValidityPeriodOption -> importFilesViewModel.selectTransferValidityPeriod(option)
- is DownloadLimitOption -> importFilesViewModel.selectTransferDownloadLimit(option)
- is PasswordTransferOption -> importFilesViewModel.selectTransferPasswordOption(option)
- is EmailLanguageOption -> importFilesViewModel.selectTransferLanguage(option)
- }
- }
-
- appSettings?.let { safeAppSettings ->
- importFilesViewModel.initTransferAdvancedOptionsValues(safeAppSettings)
-
- val advancedOptionsCallbacks = AdvancedOptionsCallbacks(
- advancedOptionsStates = {
- listOf(
- AdvancedOptionsState(
- advancedSettingType = TransferAdvancedSettingType.VALIDITY_DURATION,
- settingState = { validityPeriodState },
- ),
- AdvancedOptionsState(
- advancedSettingType = TransferAdvancedSettingType.DOWNLOAD_NUMBER_LIMIT,
- settingState = { downloadLimitState },
- ),
- AdvancedOptionsState(
- advancedSettingType = TransferAdvancedSettingType.PASSWORD,
- settingState = { passwordOptionState },
- ),
- AdvancedOptionsState(
- advancedSettingType = TransferAdvancedSettingType.LANGUAGE,
- settingState = { emailLanguageState },
- ),
- )
- },
- onAdvancedOptionsValueSelected = ::onAdvancedOptionsValueSelected,
- )
+ LaunchedEffect(Unit) { importFilesViewModel.initTransferAdvancedOptionsValues() }
+
+ val advancedOptionsCallbacks = importFilesViewModel.getTransferAdvancedOptionsCallbacks(
+ advancedOptionsStates = {
+ listOf(
+ AdvancedOptionsState(
+ advancedSettingType = TransferAdvancedSettingType.VALIDITY_DURATION,
+ settingState = { validityPeriodState },
+ ),
+ AdvancedOptionsState(
+ advancedSettingType = TransferAdvancedSettingType.DOWNLOAD_NUMBER_LIMIT,
+ settingState = { downloadLimitState },
+ ),
+ AdvancedOptionsState(
+ advancedSettingType = TransferAdvancedSettingType.PASSWORD,
+ settingState = { passwordOptionState },
+ ),
+ AdvancedOptionsState(
+ advancedSettingType = TransferAdvancedSettingType.LANGUAGE,
+ settingState = { emailLanguageState },
+ ),
+ )
+ },
+ )
- ImportFilesScreen(
- files = { files },
- filesToImportCount = { filesToImportCount },
- currentSessionFilesCount = { currentSessionFilesCount },
- selectedTransferType = GetSetCallbacks(
- get = { selectedTransferType },
- set = importFilesViewModel::selectTransferType,
- ),
- advancedOptionsCallbacks = advancedOptionsCallbacks,
- removeFileByUid = importFilesViewModel::removeFileByUid,
- addFiles = importFilesViewModel::importFiles,
- closeActivity = closeActivity,
- sendTransfer = importFilesViewModel::sendTransfer,
- initialShowUploadSourceChoiceBottomSheet = true,
- )
- }
+ ImportFilesScreen(
+ files = { files },
+ filesToImportCount = { filesToImportCount },
+ currentSessionFilesCount = { currentSessionFilesCount },
+ selectedTransferType = GetSetCallbacks(
+ get = { selectedTransferType },
+ set = importFilesViewModel::selectTransferType,
+ ),
+ advancedOptionsCallbacks = advancedOptionsCallbacks,
+ removeFileByUid = importFilesViewModel::removeFileByUid,
+ addFiles = importFilesViewModel::importFiles,
+ closeActivity = closeActivity,
+ sendTransfer = importFilesViewModel::sendTransfer,
+ initialShowUploadSourceChoiceBottomSheet = true,
+ )
}
@Composable
@@ -159,7 +147,7 @@ private fun ImportFilesScreen(
) {
val context = LocalContext.current
var showUploadSourceChoiceBottomSheet by rememberSaveable { mutableStateOf(initialShowUploadSourceChoiceBottomSheet) }
- var showOptionBottomSheet by rememberSaveable { mutableStateOf(null) }
+ var showAdvancedOption by rememberSaveable { mutableStateOf(null) }
val importedFiles = files()
val humanReadableSize = remember(importedFiles) {
@@ -174,8 +162,8 @@ private fun ImportFilesScreen(
addFiles(uris)
}
- fun closeOptionBottomSheet() {
- showOptionBottomSheet = null
+ fun closeAdvancedOption() {
+ showAdvancedOption = null
}
BottomStickyButtonScaffold(
@@ -209,37 +197,11 @@ private fun ImportFilesScreen(
ImportFilesTitle(Modifier.padding(vertical = Margin.Medium), titleRes = R.string.advancedSettingsTitle)
TransferAdvancedSettings(
advancedSettingsItemsStates = advancedOptionsCallbacks.advancedOptionsStates,
- onClick = { selectedOption -> showOptionBottomSheet = selectedOption },
+ onClick = { selectedOption -> showAdvancedOption = selectedOption },
)
}
- ValidityPeriodBottomSheet(
- isBottomSheetVisible = { showOptionBottomSheet == TransferAdvancedSettingType.VALIDITY_DURATION },
- onOptionClicked = { advancedOptionsCallbacks.onAdvancedOptionsValueSelected(it) },
- closeBottomSheet = ::closeOptionBottomSheet,
- initialValue = advancedOptionsCallbacks.advancedOptionsStates()[0].settingState(),
- )
-
- DownloadLimitBottomSheet(
- isBottomSheetVisible = { showOptionBottomSheet == TransferAdvancedSettingType.DOWNLOAD_NUMBER_LIMIT },
- onOptionClicked = { advancedOptionsCallbacks.onAdvancedOptionsValueSelected(it) },
- closeBottomSheet = ::closeOptionBottomSheet,
- initialValue = advancedOptionsCallbacks.advancedOptionsStates()[1].settingState(),
- )
-
- PasswordOptionBottomSheet(
- isBottomSheetVisible = { showOptionBottomSheet == TransferAdvancedSettingType.PASSWORD },
- onOptionClicked = { advancedOptionsCallbacks.onAdvancedOptionsValueSelected(it) },
- closeBottomSheet = ::closeOptionBottomSheet,
- initialValue = advancedOptionsCallbacks.advancedOptionsStates()[2].settingState(),
- )
-
- EmailLanguageBottomSheet(
- isBottomSheetVisible = { showOptionBottomSheet == TransferAdvancedSettingType.LANGUAGE },
- onOptionClicked = { advancedOptionsCallbacks.onAdvancedOptionsValueSelected(it) },
- closeBottomSheet = ::closeOptionBottomSheet,
- initialValue = advancedOptionsCallbacks.advancedOptionsStates()[3].settingState(),
- )
+ AdvancedOptions({ showAdvancedOption }, advancedOptionsCallbacks, ::closeAdvancedOption)
UploadSourceChoiceBottomSheet(
isVisible = { showUploadSourceChoiceBottomSheet },
@@ -284,6 +246,41 @@ private fun ColumnScope.EmailAddressesTextFields(selectedTransferType: () -> Tra
}
}
+@Composable
+private fun AdvancedOptions(
+ selectedTransferType: () -> TransferAdvancedSettingType?,
+ advancedOptionsCallbacks: AdvancedOptionsCallbacks,
+ closeAdvancedOption: () -> Unit,
+) {
+ when (selectedTransferType()) {
+ TransferAdvancedSettingType.VALIDITY_DURATION -> ValidityPeriodBottomSheet(
+ onOptionClicked = { advancedOptionsCallbacks.onAdvancedOptionsValueSelected(it) },
+ closeBottomSheet = closeAdvancedOption,
+ initialValue = advancedOptionsCallbacks.advancedOptionsStates()[0].settingState(),
+ )
+ TransferAdvancedSettingType.DOWNLOAD_NUMBER_LIMIT -> DownloadLimitBottomSheet(
+ onOptionClicked = { advancedOptionsCallbacks.onAdvancedOptionsValueSelected(it) },
+ closeBottomSheet = closeAdvancedOption,
+ initialValue = advancedOptionsCallbacks.advancedOptionsStates()[1].settingState(),
+ )
+ TransferAdvancedSettingType.PASSWORD -> PasswordOptionAlertDialog(
+ password = advancedOptionsCallbacks.password,
+ onConfirmation = { passwordOption ->
+ advancedOptionsCallbacks.onAdvancedOptionsValueSelected(passwordOption)
+ closeAdvancedOption()
+ },
+ closeAlertDialog = closeAdvancedOption,
+ isPasswordValid = advancedOptionsCallbacks.isPasswordValid,
+ )
+ TransferAdvancedSettingType.LANGUAGE -> EmailLanguageBottomSheet(
+ onOptionClicked = { advancedOptionsCallbacks.onAdvancedOptionsValueSelected(it) },
+ closeBottomSheet = closeAdvancedOption,
+ initialValue = advancedOptionsCallbacks.advancedOptionsStates()[3].settingState(),
+ )
+ null -> Unit
+ }
+}
+
@Composable
private fun SendButton(
filesToImportCount: () -> Int,
@@ -326,6 +323,8 @@ private fun ImportFilesTitle(modifier: Modifier = Modifier, @StringRes titleRes:
data class AdvancedOptionsCallbacks(
val advancedOptionsStates: () -> List,
val onAdvancedOptionsValueSelected: (SettingOption) -> Unit,
+ val password: GetSetCallbacks,
+ val isPasswordValid: () -> Boolean,
)
data class AdvancedOptionsState(
@@ -345,35 +344,39 @@ enum class PasswordTransferOption(
@PreviewAllWindows
@Composable
private fun ImportFilesScreenPreview(@PreviewParameter(FileUiListPreviewParameter::class) files: List) {
+ val advancedOptionsCallbacks = AdvancedOptionsCallbacks(
+ advancedOptionsStates = {
+ listOf(
+ AdvancedOptionsState(
+ advancedSettingType = TransferAdvancedSettingType.VALIDITY_DURATION,
+ settingState = { ValidityPeriodOption.THIRTY },
+ ),
+ AdvancedOptionsState(
+ advancedSettingType = TransferAdvancedSettingType.DOWNLOAD_NUMBER_LIMIT,
+ settingState = { DownloadLimitOption.TWO_HUNDRED_FIFTY },
+ ),
+ AdvancedOptionsState(
+ advancedSettingType = TransferAdvancedSettingType.PASSWORD,
+ settingState = { PasswordTransferOption.NONE },
+ ),
+ AdvancedOptionsState(
+ advancedSettingType = TransferAdvancedSettingType.LANGUAGE,
+ settingState = { EmailLanguageOption.FRENCH },
+ ),
+ )
+ },
+ onAdvancedOptionsValueSelected = {},
+ password = GetSetCallbacks(get = { "password" }, set = {}),
+ isPasswordValid = { true },
+ )
+
SwissTransferTheme {
ImportFilesScreen(
files = { files },
filesToImportCount = { 0 },
currentSessionFilesCount = { 0 },
selectedTransferType = GetSetCallbacks(get = { TransferType.QR_CODE }, set = {}),
- advancedOptionsCallbacks = AdvancedOptionsCallbacks(
- advancedOptionsStates = {
- listOf(
- AdvancedOptionsState(
- advancedSettingType = TransferAdvancedSettingType.VALIDITY_DURATION,
- settingState = { ValidityPeriodOption.THIRTY },
- ),
- AdvancedOptionsState(
- advancedSettingType = TransferAdvancedSettingType.DOWNLOAD_NUMBER_LIMIT,
- settingState = { DownloadLimitOption.TWO_HUNDRED_FIFTY },
- ),
- AdvancedOptionsState(
- advancedSettingType = TransferAdvancedSettingType.PASSWORD,
- settingState = { PasswordTransferOption.NONE },
- ),
- AdvancedOptionsState(
- advancedSettingType = TransferAdvancedSettingType.LANGUAGE,
- settingState = { EmailLanguageOption.FRENCH },
- ),
- )
- },
- onAdvancedOptionsValueSelected = {},
- ),
+ advancedOptionsCallbacks = advancedOptionsCallbacks,
removeFileByUid = {},
addFiles = {},
closeActivity = {},
diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/TransferOptionsBottomSheets.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/TransferOptionsBottomSheets.kt
index c87c85628..158cd60c6 100644
--- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/TransferOptionsBottomSheets.kt
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/TransferOptionsBottomSheets.kt
@@ -36,7 +36,6 @@ import com.infomaniak.swisstransfer.ui.utils.PreviewAllWindows
@Composable
private fun TransferOptionBottomSheetScaffold(
- isBottomSheetVisible: () -> Boolean,
onOptionClicked: (SettingOption) -> Unit,
closeBottomSheet: () -> Unit,
initialValue: SettingOption?,
@@ -53,35 +52,31 @@ private fun TransferOptionBottomSheetScaffold(
else -> 0
}
- if (isBottomSheetVisible()) {
- SwissTransferBottomSheet(
- onDismissRequest = closeBottomSheet,
- titleRes = titleRes,
- content = {
- SingleSelectOptions(
- items = optionEntries,
- selectedItem = { selectedPosition },
- setSelectedItem = { position ->
- val selectedValue = optionEntries[position]
- selectedItem = selectedValue
- onOptionClicked(selectedValue)
- closeBottomSheet()
- },
- )
- },
- )
- }
+ SwissTransferBottomSheet(
+ onDismissRequest = closeBottomSheet,
+ titleRes = titleRes,
+ content = {
+ SingleSelectOptions(
+ items = optionEntries,
+ selectedItem = { selectedPosition },
+ setSelectedItem = { position ->
+ val selectedValue = optionEntries[position]
+ selectedItem = selectedValue
+ onOptionClicked(selectedValue)
+ closeBottomSheet()
+ },
+ )
+ },
+ )
}
@Composable
fun ValidityPeriodBottomSheet(
- isBottomSheetVisible: () -> Boolean,
onOptionClicked: (ValidityPeriodOption) -> Unit,
closeBottomSheet: () -> Unit,
initialValue: SettingOption?,
) {
TransferOptionBottomSheetScaffold(
- isBottomSheetVisible = isBottomSheetVisible,
closeBottomSheet = closeBottomSheet,
initialValue = initialValue,
titleRes = R.string.settingsOptionValidityPeriod,
@@ -92,13 +87,11 @@ fun ValidityPeriodBottomSheet(
@Composable
fun DownloadLimitBottomSheet(
- isBottomSheetVisible: () -> Boolean,
onOptionClicked: (DownloadLimitOption) -> Unit,
closeBottomSheet: () -> Unit,
initialValue: SettingOption?,
) {
TransferOptionBottomSheetScaffold(
- isBottomSheetVisible = isBottomSheetVisible,
closeBottomSheet = closeBottomSheet,
initialValue = initialValue,
titleRes = R.string.settingsOptionDownloadLimit,
@@ -107,32 +100,13 @@ fun DownloadLimitBottomSheet(
)
}
-@Composable
-fun PasswordOptionBottomSheet(
- isBottomSheetVisible: () -> Boolean,
- onOptionClicked: (PasswordTransferOption) -> Unit,
- closeBottomSheet: () -> Unit,
- initialValue: SettingOption?,
-) {
- TransferOptionBottomSheetScaffold(
- isBottomSheetVisible = isBottomSheetVisible,
- closeBottomSheet = closeBottomSheet,
- initialValue = initialValue,
- titleRes = R.string.settingsOptionPassword,
- optionEntries = PasswordTransferOption.entries,
- onOptionClicked = { onOptionClicked(it as PasswordTransferOption) },
- )
-}
-
@Composable
fun EmailLanguageBottomSheet(
- isBottomSheetVisible: () -> Boolean,
onOptionClicked: (EmailLanguageOption) -> Unit,
closeBottomSheet: () -> Unit,
initialValue: SettingOption?,
) {
TransferOptionBottomSheetScaffold(
- isBottomSheetVisible = isBottomSheetVisible,
closeBottomSheet = closeBottomSheet,
initialValue = initialValue,
titleRes = R.string.settingsOptionEmailLanguage,
@@ -147,7 +121,6 @@ private fun ValidityPeriodOptionBottomSheetPreview() {
SwissTransferTheme {
Surface {
ValidityPeriodBottomSheet(
- isBottomSheetVisible = { true },
onOptionClicked = {},
closeBottomSheet = {},
initialValue = ValidityPeriodOption.SEVEN,
diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/PasswordOptionAlertDialog.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/PasswordOptionAlertDialog.kt
new file mode 100644
index 000000000..798f47356
--- /dev/null
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/PasswordOptionAlertDialog.kt
@@ -0,0 +1,130 @@
+/*
+ * 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.importfiles.components
+
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.height
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Switch
+import androidx.compose.material3.Text
+import androidx.compose.runtime.*
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.tooling.preview.Preview
+import com.infomaniak.swisstransfer.R
+import com.infomaniak.swisstransfer.ui.components.SwissTransferAlertDialog
+import com.infomaniak.swisstransfer.ui.components.SwissTransferTextField
+import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.PasswordTransferOption
+import com.infomaniak.swisstransfer.ui.screen.newtransfer.upload.components.WeightOneSpacer
+import com.infomaniak.swisstransfer.ui.theme.Margin
+import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme
+import com.infomaniak.swisstransfer.ui.utils.GetSetCallbacks
+
+@Composable
+fun PasswordOptionAlertDialog(
+ password: GetSetCallbacks,
+ closeAlertDialog: () -> Unit,
+ onConfirmation: (PasswordTransferOption) -> Unit,
+ isPasswordValid: () -> Boolean,
+) {
+
+ var isPasswordActivated by rememberSaveable { mutableStateOf(password.get().isNotEmpty()) }
+ var lastValidPassword by remember { mutableStateOf("") }
+
+ fun onDismiss() {
+ isPasswordActivated = lastValidPassword.isNotEmpty()
+ password.set(lastValidPassword)
+ closeAlertDialog()
+ }
+
+ fun onConfirmButtonClicked() {
+ val passwordOption = if (isPasswordActivated) {
+ PasswordTransferOption.ACTIVATED
+ } else {
+ password.set("")
+ PasswordTransferOption.NONE
+ }
+
+ lastValidPassword = password.get()
+ onConfirmation(passwordOption)
+ }
+
+ SwissTransferAlertDialog(
+ titleRes = R.string.settingsOptionPassword,
+ descriptionRes = R.string.settingsPasswordDescription,
+ onDismiss = ::onDismiss,
+ onConfirmation = ::onConfirmButtonClicked,
+ shouldEnableConfirmButton = { if (isPasswordActivated) isPasswordValid() else true },
+ ) {
+ ActivatePasswordSwitch(isChecked = isPasswordActivated, onCheckedChange = { isPasswordActivated = it })
+ AnimatedPasswordInput(isPasswordActivated, password, isPasswordValid)
+ }
+}
+
+@Composable
+private fun ActivatePasswordSwitch(isChecked: Boolean, onCheckedChange: (Boolean) -> Unit) {
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Text(
+ text = stringResource(R.string.settingsPasswordToggleDescription),
+ style = SwissTransferTheme.typography.bodyMedium,
+ color = SwissTransferTheme.colors.primaryTextColor,
+ )
+ WeightOneSpacer(minWidth = Margin.Medium)
+ Switch(isChecked, onCheckedChange)
+ }
+}
+
+@Composable
+private fun ColumnScope.AnimatedPasswordInput(
+ isChecked: Boolean,
+ password: GetSetCallbacks,
+ isPasswordValid: () -> Boolean
+) {
+ AnimatedVisibility(isChecked) {
+ Spacer(Modifier.height(Margin.Mini))
+ SwissTransferTextField(
+ label = stringResource(R.string.settingsOptionPassword),
+ isPassword = true,
+ initialValue = password.get(),
+ imeAction = ImeAction.Done,
+ errorMessage = { if (isPasswordValid()) null else stringResource(R.string.errorTransferPasswordLength) },
+ onValueChange = { password.set(it) },
+ )
+ }
+}
+
+@Preview
+@Composable
+fun Preview() {
+ SwissTransferTheme {
+ Surface {
+ PasswordOptionAlertDialog(
+ password = GetSetCallbacks(get = { "pass" }, set = {}),
+ closeAlertDialog = {},
+ onConfirmation = {},
+ isPasswordValid = { false },
+ )
+ }
+ }
+}
diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/components/WeightOneSpacer.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/components/WeightOneSpacer.kt
index a3ffffc86..b61046b71 100644
--- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/components/WeightOneSpacer.kt
+++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/components/WeightOneSpacer.kt
@@ -17,9 +17,7 @@
*/
package com.infomaniak.swisstransfer.ui.screen.newtransfer.upload.components
-import androidx.compose.foundation.layout.ColumnScope
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
@@ -29,3 +27,9 @@ fun ColumnScope.WeightOneSpacer(minHeight: Dp) {
Spacer(modifier = Modifier.height(minHeight))
Spacer(modifier = Modifier.weight(1f))
}
+
+@Composable
+fun RowScope.WeightOneSpacer(minWidth: Dp) {
+ Spacer(modifier = Modifier.width(minWidth))
+ Spacer(modifier = Modifier.weight(1f))
+}
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 462a84421..07953fbaf 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -18,6 +18,8 @@
Erweiterte Einstellungen
Dateien hinzufügen
+ Abbrechen
+ Bestätigen
Link kopieren
Download
Auswahl herunterladen
@@ -30,7 +32,9 @@
Datei entfernen
Passwort anzeigen
Neuer Transfer
- Heruntergeladene Übertragung: %d/%d
+ Heruntergeladene Übertragung : %d/%d
+ Das Passwort muss zwischen 6 und 25 Zeichen lang sein
+ Abgelaufen am %s
Verfällt in %d Tagen
- %d Datei
@@ -80,6 +84,8 @@
Hell
System
Dauer der Gültigkeit
+ Deine Empfänger müssen das Passwort eingeben, um die Dateien herunterzuladen.
+ Schutz aktivieren
Sentry ist ein Tool, das ausschliesslich von Infomaniak gehostet und verwaltet wird, um die Stabilität der Anwendung in Echtzeit zu überwachen und unseren Entwicklern automatisch alle technischen Fehler zu melden.\n\nAnhand dieser Daten kann unser Team die Anwendung schnell korrigieren und optimieren, was zu einem besseren Nutzererlebnis für Sie führt.
Wähle ein Thema aus
Einstellungen
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 7dc09751b..8840028d5 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -18,6 +18,8 @@
Ajustes avanzados
Añadir archivos
+ Cancelar
+ Confirme
Copiar enlace
Descargar
Descargar la selección
@@ -30,8 +32,9 @@
Eliminar archivo
Mostrar contraseña
Nueva transferencia
- Transferencia descargada: %d/%d
+ Transferencia descargada : %d/%d
La contraseña debe tener entre 6 y 25 caracteres
+ Expirado el %s
Caduca en %d días
- %d archivo
@@ -81,6 +84,8 @@
Luz
Sistema
Periodo de validez
+ Los destinatarios tendrán que introducir la contraseña para descargar los archivos.
+ Activar la protección
Sentry es una herramienta alojada y gestionada en exclusiva por Infomaniak para supervisar la estabilidad de la aplicación en tiempo real e informar automáticamente de cualquier error técnico a nuestros desarrolladores.\n\nEstos datos permiten a nuestro equipo corregir y optimizar rápidamente la aplicación, lo que se traduce en una mejor experiencia de usuario para usted.
Seleccione un tema
Parámetros
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index e3c924940..5c505fc63 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -18,6 +18,8 @@
Paramètres avancés
Ajouter des fichiers
+ Annuler
+ Confirmer
Copier le lien
Télécharger
Télécharger la sélection
@@ -31,6 +33,8 @@
Afficher le mot de passe
Nouveau transfert
Transfert téléchargé : %d/%d\u0020
+ Le mot de passe doit comporter entre 6 et 25 caractères
+ Expiré le %s
Expire dans %d jours
- %d fichier
@@ -81,6 +85,8 @@
Clair
Système
Durée de validité
+ Tes destinataires devront saisir le mot de passe pour télécharger les fichiers.
+ Activer la protection
Sentry est un outil hébergé et géré exclusivement par Infomaniak pour surveiller en temps réel la stabilité de l’application et signaler automatiquement d’éventuelles erreurs techniques à nos développeurs.\n\nCes données permettent à notre équipe de rapidement corriger et optimiser l’application, ce qui se traduit par une meilleure expérience d’utilisation pour vous.
Sélectionne un thème
Paramètres
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index ff79304c9..659893cb6 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -18,6 +18,8 @@
Impostazioni avanzate
Aggiunta di file
+ Annulla
+ Conferma
Copia link
Scaricare
Scarica la selezione
@@ -30,7 +32,9 @@
Rimuovi il file
Mostra password
Nuovo trasferimento
- Trasferimento scaricato: %d/%d
+ Trasferimento scaricato : %d/%d
+ La password deve essere compresa tra 6 e 24 caratteri
+ Scaduto il %s
Scade tra %d giorni
- %d file
@@ -80,6 +84,8 @@
Chiaro
Sistema
Periodo di validità
+ I destinatari dovranno inserire la password per scaricare i file.
+ Attivare la protezione
Sentry è uno strumento ospitato e gestito esclusivamente da Infomaniak per monitorare la stabilità dell’applicazione in tempo reale e segnalare automaticamente eventuali errori tecnici ai nostri sviluppatori.\n\nQuesti dati consentono al nostro team di correggere e ottimizzare rapidamente l’applicazione, migliorando l’esperienza dell’utente.
Seleziona un tema
Parametri
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 52cf92544..4b878b5e1 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -23,6 +23,8 @@
Advanced settings
Add files
+ Cancel
+ Confirm
Copy link
Download
Download selection
@@ -36,6 +38,8 @@
Show password
New transfer
Downloaded transfer: %d/%d\u0020
+ The password must be between 6 and 25 characters
+ Expired on %s
Expires in %d days
- %d file
@@ -85,6 +89,8 @@
Light
System
Validity period
+ Your recipients will need to enter the password to download the files.
+ Activate protection
Sentry is a tool hosted and managed exclusively by Infomaniak to monitor the stability of the application in real time and automatically report any technical errors to our developers.\n\nThis data enables our team to quickly correct and optimise the application, resulting in a better user experience for you.
Select a theme
Settings
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 5ac4e109d..2e95b54ec 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -20,7 +20,7 @@ qrose = "1.0.1"
recaptcha = "18.6.1"
sentry = "4.12.0"
serialization = "1.7.1"
-swisstransfer = "0.7.0"
+swisstransfer = "0.7.1"
workmanager = "2.9.1"
[libraries]