Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Mail validation screen #254

Draft
wants to merge 41 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
980ed6a
feat: First try at OtpTextField
LunarX Dec 5, 2024
e5c16b6
feat: Basic structure of the user email validation screen
LunarX Dec 6, 2024
568f676
feat: Import strings
LunarX Dec 6, 2024
ebf0b13
feat: Control spacing between each character
LunarX Dec 10, 2024
b6c3053
refactor: Make it so otp text field always has a "focused" visual cue…
LunarX Dec 10, 2024
c2f0e7a
feat: Add isEnabled to OtpTextField
LunarX Dec 10, 2024
db1c674
feat: Make otp load when a code is entered
LunarX Dec 10, 2024
2225e9c
fix: Correctly filter out forbidden characters
LunarX Dec 10, 2024
95fa100
fix: System contextual menu not displaying at the correct coordinates
LunarX Dec 10, 2024
b2b0b5c
feat: Adapt layout for large screens
LunarX Dec 10, 2024
cbd70db
feat: Make email validation screen scrollable
LunarX Dec 11, 2024
d349dd4
refactor: Regroup layout style choice with its enum
LunarX Dec 11, 2024
682200b
refactor: Extract OtpTextField to its own file
LunarX Dec 11, 2024
04a427f
refactor: Clean the OtpTextField file and add missing doc/preview
LunarX Dec 11, 2024
15b7fa5
feat: Add actions when the topappbar buttons are clicked
LunarX Dec 11, 2024
033861c
refactor: Reorder enum at the end of the file
LunarX Dec 11, 2024
afcce96
refactor: Remove hardcoded values
LunarX Dec 11, 2024
8f531ab
refactor: Move validate user email files to their own package
LunarX Dec 11, 2024
2670b36
feat: Validate email otp code using the correct api route
LunarX Dec 11, 2024
9513e6b
Merge remote-tracking branch 'origin/main' into t3
LunarX Dec 12, 2024
76051d8
fix: Adapt to the new button argument signature
LunarX Dec 12, 2024
8cf9cfa
feat: Add resend email code button timer
LunarX Dec 12, 2024
09b8865
feat: Disable buttons while the code is being verified
LunarX Dec 12, 2024
642f23d
feat: Remove "select all" from the current text toolbar
LunarX Dec 16, 2024
d1ae597
feat: Show snackbar when unknown validation api error occurs
LunarX Dec 16, 2024
0bcbc2d
refactor: Keep logic contained inside the inner ValidateUserEmailScreen
LunarX Dec 16, 2024
b9cff14
Merge remote-tracking branch 'origin/main' into t2
LunarX Dec 16, 2024
838ec11
feat: Take user email as nav arg
LunarX Dec 16, 2024
c6954b0
refactor: Use a data class to pass named parameters to method's lambd…
LunarX Dec 16, 2024
d153401
feat: Extract CodeVerification to its own file
LunarX Dec 16, 2024
c09d04c
refactor: Extract ResendCodeCountDownButton to its own file
LunarX Dec 16, 2024
3c90939
Merge remote-tracking branch 'origin/main' into mail-validation-ui
LunarX Dec 16, 2024
e731a5a
feat: Automatically open email validation screen when catching the as…
LunarX Dec 16, 2024
c627352
feat: Open mail apps when clicking on the associated button
LunarX Dec 17, 2024
0a5806a
refactor: Use a UiState to define the ValidateUserEmailScreen state
LunarX Dec 17, 2024
69f9fdd
refactor: Shorten long lines
LunarX Dec 17, 2024
07fef3a
Merge remote-tracking branch 'origin/main' into mail-validation-ui
LunarX Dec 17, 2024
ec33f4e
feat: Add resend email code api call to the button
LunarX Dec 17, 2024
4a13692
Merge remote-tracking branch 'origin/main' into mail-validation-ui
LunarX Dec 18, 2024
e776e53
feat: Update verifyEmailCode call to new kmp version
LunarX Dec 18, 2024
8cde32f
wip
LunarX Dec 18, 2024
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
1 change: 1 addition & 0 deletions Core2/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<resources>
<string name="anErrorHasOccurred">Ein Fehler ist aufgetreten</string>
<string name="buttonCancel">Abbrechen</string>
<string name="buttonNext">Weiter</string>
<string name="buttonRetry">Wiederholen</string>
Expand Down
1 change: 1 addition & 0 deletions Core2/src/main/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<resources>
<string name="anErrorHasOccurred">Se ha producido un error</string>
<string name="buttonCancel">Cancelar</string>
<string name="buttonNext">Siguiente</string>
<string name="buttonRetry">Reintentar</string>
Expand Down
1 change: 1 addition & 0 deletions Core2/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<resources>
<string name="anErrorHasOccurred">Une erreur est survenue</string>
<string name="buttonCancel">Annuler</string>
<string name="buttonNext">Suivant</string>
<string name="buttonRetry">Réessayer</string>
Expand Down
1 change: 1 addition & 0 deletions Core2/src/main/res/values-it/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<resources>
<string name="anErrorHasOccurred">Si è verificato un errore</string>
<string name="buttonCancel">Annulla</string>
<string name="buttonNext">Avanti</string>
<string name="buttonRetry">Riprova</string>
Expand Down
1 change: 1 addition & 0 deletions Core2/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<resources>
<string name="anErrorHasOccurred">An error has occurred</string>
<string name="buttonCancel">Cancel</string>
<string name="buttonNext">Next</string>
<string name="buttonRetry">Retry</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ sealed class NewTransferNavigation : NavigationDestination() {
@Serializable
data object TransferTypeDestination : NewTransferNavigation()
@Serializable
data object ValidateUserEmailDestination : NewTransferNavigation()
data class ValidateUserEmailDestination(val userEmail: String) : NewTransferNavigation()

@Serializable
data class UploadProgressDestination(val transferType: TransferTypeUi, val totalSize: Long) : NewTransferNavigation()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ 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.multiplatform_swisstransfer.network.exceptions.ContainerErrorsException
import com.infomaniak.sentry.SentryLog
import com.infomaniak.swisstransfer.di.IoDispatcher
import com.infomaniak.swisstransfer.ui.screen.main.settings.DownloadLimitOption
Expand Down Expand Up @@ -141,11 +142,19 @@ class ImportFilesViewModel @Inject constructor(
}
}.onFailure { exception ->
SentryLog.e(TAG, "Failed to start the upload", exception)
_sendActionResult.update { SendActionResult.Failure }
val result = when (exception) {
is ContainerErrorsException.EmailValidationRequired -> SendActionResult.RequireEmailValidation
else -> SendActionResult.Failure
}
_sendActionResult.update { result }
}
}
}

fun setDefaultActionResult() {
_sendActionResult.value = SendActionResult.NotStarted
}

private suspend fun removeOldData() {
importationFilesManager.removeLocalCopyFolder()
uploadManager.removeAllUploadSession()
Expand Down Expand Up @@ -262,6 +271,7 @@ class ImportFilesViewModel @Inject constructor(
data object Pending : SendActionResult()
data class Success(val totalSize: Long) : SendActionResult()
data object Failure : SendActionResult()
data object RequireEmailValidation : SendActionResult()
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ import androidx.navigation.toRoute
import com.infomaniak.swisstransfer.ui.navigation.NewTransferNavigation
import com.infomaniak.swisstransfer.ui.navigation.NewTransferNavigation.*
import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.ImportFilesScreen
import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.ValidateUserEmailScreen
import com.infomaniak.swisstransfer.ui.screen.newtransfer.upload.UploadErrorScreen
import com.infomaniak.swisstransfer.ui.screen.newtransfer.upload.UploadProgressScreen
import com.infomaniak.swisstransfer.ui.screen.newtransfer.upload.UploadSuccessScreen
import com.infomaniak.swisstransfer.ui.screen.newtransfer.validateemail.ValidateUserEmailScreen

@Composable
fun NewTransferNavHost(navController: NavHostController, closeActivity: () -> Unit) {
Expand All @@ -40,10 +40,18 @@ fun NewTransferNavHost(navController: NavHostController, closeActivity: () -> Un
navigateToUploadProgress = { transferType, totalSize ->
navController.navigate(UploadProgressDestination(transferType, totalSize))
},
navigateToEmailValidation = { email ->
navController.navigate(ValidateUserEmailDestination(email))
}
)
}
composable<ValidateUserEmailDestination> {
ValidateUserEmailScreen()
val args = it.toRoute<ValidateUserEmailDestination>()
ValidateUserEmailScreen(
closeActivity = closeActivity,
navigateBack = { navController.popBackStack() },
emailToValidate = args.userEmail,
)
}
composable<UploadProgressDestination> {
val args = it.toRoute<UploadProgressDestination>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ fun ImportFilesScreen(
importFilesViewModel: ImportFilesViewModel = hiltViewModel<ImportFilesViewModel>(),
closeActivity: () -> Unit,
navigateToUploadProgress: (transferType: TransferTypeUi, totalSize: Long) -> Unit,
navigateToEmailValidation: (email: String) -> Unit,
) {
val files by importFilesViewModel.importedFilesDebounced.collectAsStateWithLifecycle()
val filesToImportCount by importFilesViewModel.filesToImportCount.collectAsStateWithLifecycle()
Expand All @@ -73,7 +74,13 @@ fun ImportFilesScreen(

val sendActionResult by importFilesViewModel.sendActionResult.collectAsStateWithLifecycle()

HandleSendActionResult({ sendActionResult }, { selectedTransferType }, navigateToUploadProgress)
HandleSendActionResult(
getSendActionResult = { sendActionResult },
setDefaultActionResult = { importFilesViewModel.setDefaultActionResult() },
transferType = { selectedTransferType },
navigateToUploadProgress = navigateToUploadProgress,
navigateToEmailValidation = { navigateToEmailValidation(importFilesViewModel.transferAuthorEmail.get()) },
)

LaunchedEffect(Unit) { importFilesViewModel.initTransferOptionsValues() }

Expand Down Expand Up @@ -133,13 +140,22 @@ fun ImportFilesScreen(
@Composable
private fun HandleSendActionResult(
getSendActionResult: () -> SendActionResult?,
setDefaultActionResult: () -> Unit,
transferType: () -> TransferTypeUi,
navigateToUploadProgress: (transferType: TransferTypeUi, totalSize: Long) -> Unit,
navigateToEmailValidation: () -> Unit,
) {
LaunchedEffect(getSendActionResult()) {
when (val actionResult = getSendActionResult()) {
is SendActionResult.Success -> navigateToUploadProgress(transferType(), actionResult.totalSize)
is SendActionResult.Success -> {
navigateToUploadProgress(transferType(), actionResult.totalSize)
setDefaultActionResult()
}
is SendActionResult.Failure -> Unit // TODO: Show error
is SendActionResult.RequireEmailValidation -> {
navigateToEmailValidation()
setDefaultActionResult()
}
else -> Unit
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@ import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import com.infomaniak.swisstransfer.R
import com.infomaniak.swisstransfer.ui.images.AppImages
import com.infomaniak.swisstransfer.ui.images.ThemedImage
import com.infomaniak.swisstransfer.ui.images.illus.uploadAd.MetallicSafe
import com.infomaniak.swisstransfer.ui.images.illus.uploadAd.MountainGondola
import com.infomaniak.swisstransfer.ui.images.illus.uploadAd.SwissWithFlag
import com.infomaniak.swisstransfer.ui.utils.TextUtils

enum class UploadProgressAdType(
@StringRes private val descriptionTemplate: Int,
Expand All @@ -54,17 +52,6 @@ enum class UploadProgressAdType(

@Composable
fun description(): AnnotatedString {
val template = stringResource(descriptionTemplate)
val templateArgument = stringResource(descriptionAccentuatedPart)

val description = String.format(template, templateArgument)

val startIndex = description.indexOf(templateArgument)
val endIndex = startIndex + templateArgument.length

return buildAnnotatedString {
append(description)
addStyle(style = SpanStyle(fontWeight = FontWeight.Bold), start = startIndex, end = endIndex)
}
return TextUtils.assembleWithBoldArgument(stringResource(descriptionTemplate), stringResource(descriptionAccentuatedPart))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.infomaniak.swisstransfer.ui.screen.newtransfer.validateemail

import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.platform.TextToolbar
import androidx.compose.ui.platform.TextToolbarStatus

class HideSelectAllTextToolbar(private val previousToolbar: TextToolbar) : TextToolbar {
override val status: TextToolbarStatus get() = previousToolbar.status

override fun showMenu(
rect: Rect,
onCopyRequested: (() -> Unit)?,
onPasteRequested: (() -> Unit)?,
onCutRequested: (() -> Unit)?,
onSelectAllRequested: (() -> Unit)?,
onAutofillRequested: (() -> Unit)?,
) {
previousToolbar.showMenu(
rect,
onCopyRequested,
onPasteRequested,
onCutRequested,
null, // Disable "Select All"
onAutofillRequested,
)
}

override fun showMenu(
rect: Rect,
onCopyRequested: (() -> Unit)?,
onPasteRequested: (() -> Unit)?,
onCutRequested: (() -> Unit)?,
onSelectAllRequested: (() -> Unit)?
) {
previousToolbar.showMenu(
rect,
onCopyRequested,
onPasteRequested,
onCutRequested,
null, // Disable "Select All"
)
}

override fun hide() {
previousToolbar.hide()
}
}
Loading
Loading