diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/EmailAddressChip.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/EmailAddressChip.kt new file mode 100644 index 000000000..59751fce3 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/EmailAddressChip.kt @@ -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 . + */ +package com.infomaniak.swisstransfer.ui.components + +import android.content.res.Configuration +import androidx.compose.material3.SuggestionChip +import androidx.compose.material3.SuggestionChipDefaults +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.infomaniak.swisstransfer.ui.theme.CustomShapes +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme + +@Composable +fun EmailAddressChip( + text: String, + modifier: Modifier = Modifier, +) { + SuggestionChip( + onClick = { }, + label = { + Text( + text = text, + style = SwissTransferTheme.typography.bodyRegular, + ) + }, + modifier = modifier, + enabled = false, + shape = CustomShapes.ROUNDED, + colors = SuggestionChipDefaults.suggestionChipColors( + disabledContainerColor = SwissTransferTheme.colors.emailAddressChipColor, + disabledLabelColor = SwissTransferTheme.colors.onEmailAddressChipColor + ), + border = null, + ) +} + +@Preview(name = "Light mode") +@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL) +@Composable +private fun EmailAddressChipPreview() { + SwissTransferTheme { + Surface { + EmailAddressChip(text = "test.test@ik.me") + } + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/EmptyState.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/EmptyState.kt index 3b9fbdbdd..efeac9f0e 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/EmptyState.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/EmptyState.kt @@ -17,17 +17,21 @@ */ package com.infomaniak.swisstransfer.ui.components +import android.content.res.Configuration import androidx.annotation.StringRes -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.* -import androidx.compose.material3.Text +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import com.infomaniak.swisstransfer.ui.theme.Dimens +import androidx.compose.ui.tooling.preview.Preview +import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.images.AppImages.AppIllus +import com.infomaniak.swisstransfer.ui.images.illus.MascotSearching import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme @@ -38,27 +42,30 @@ fun EmptyState( @StringRes description: Int, modifier: Modifier = Modifier, ) { - Column( - modifier = modifier.fillMaxSize(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, ) { - Image(imageVector = icon, contentDescription = null) - - Text( - text = stringResource(title), - style = SwissTransferTheme.typography.specificMedium22, - modifier = Modifier.padding(PaddingValues(top = Margin.XLarge)), + IllustratedMessageBlock( + icon = icon, + title = title, + description = stringResource(description), + modifier = modifier.padding(horizontal = Margin.Medium), ) + } +} - Text( - text = stringResource(description), - textAlign = TextAlign.Center, - style = SwissTransferTheme.typography.bodyRegular, - color = SwissTransferTheme.colors.secondaryTextColor, - modifier = Modifier - .widthIn(max = Dimens.DescriptionWidth) - .padding(PaddingValues(top = Margin.Medium)), - ) +@Preview(name = "Light mode") +@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL) +@Composable +private fun EmptyStatePreview() { + SwissTransferTheme { + Surface { + EmptyState( + icon = AppIllus.MascotSearching, + title = R.string.noTransferReceivedTitle, + description = R.string.noTransferReceivedDescription, + ) + } } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/IllustratedMessageBlock.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/IllustratedMessageBlock.kt new file mode 100644 index 000000000..691888280 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/IllustratedMessageBlock.kt @@ -0,0 +1,89 @@ +/* + * 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 android.content.res.Configuration +import androidx.annotation.StringRes +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.widthIn +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.images.AppImages.AppIllus +import com.infomaniak.swisstransfer.ui.images.illus.MascotSearching +import com.infomaniak.swisstransfer.ui.theme.Dimens +import com.infomaniak.swisstransfer.ui.theme.Margin +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme + +@Composable +fun IllustratedMessageBlock( + icon: ImageVector, + @StringRes title: Int, + description: String, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Image(imageVector = icon, contentDescription = null) + + Spacer(Modifier.height(Margin.XLarge)) + + Text( + text = stringResource(title), + textAlign = TextAlign.Center, + style = SwissTransferTheme.typography.h1, + ) + + Spacer(Modifier.height(Margin.Medium)) + + Text( + text = description, + textAlign = TextAlign.Center, + style = SwissTransferTheme.typography.bodyRegular, + color = SwissTransferTheme.colors.secondaryTextColor, + modifier = Modifier.widthIn(max = Dimens.DescriptionWidth), + ) + } +} + +@Preview(name = "Light mode") +@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL) +@Composable +private fun IllustratedMessageBlockPreview() { + SwissTransferTheme { + Surface { + IllustratedMessageBlock( + icon = AppIllus.MascotSearching, + title = R.string.noTransferReceivedTitle, + description = stringResource(R.string.noTransferReceivedDescription), + ) + } + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/NewTransferFab.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/NewTransferFab.kt index d40dbbaf4..04fe3246a 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/NewTransferFab.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/NewTransferFab.kt @@ -17,14 +17,22 @@ */ package com.infomaniak.swisstransfer.ui.components +import android.content.res.Configuration +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.width import androidx.compose.material3.FloatingActionButtonDefaults import androidx.compose.material3.FloatingActionButtonElevation +import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.infomaniak.swisstransfer.ui.NewTransferActivity +import com.infomaniak.swisstransfer.ui.theme.Margin +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.launchActivity @Composable @@ -57,3 +65,20 @@ enum class NewTransferFabType(val fabType: FabType, private val defaultElevation } } } + +@Preview(name = "Light mode") +@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL) +@Composable +private fun NewTransferFabPreview() { + SwissTransferTheme { + Surface { + Row { + NewTransferFab(newTransferFabType = NewTransferFabType.BOTTOM_BAR) + Spacer(modifier = Modifier.width(Margin.Large)) + NewTransferFab(newTransferFabType = NewTransferFabType.EMPTY_STATE) + Spacer(modifier = Modifier.width(Margin.Large)) + NewTransferFab(newTransferFabType = NewTransferFabType.NAVIGATION_RAIL) + } + } + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/QrCode.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/QrCode.kt new file mode 100644 index 000000000..37acad089 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/QrCode.kt @@ -0,0 +1,60 @@ +/* + * 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 android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.swisstransfer.ui.theme.CustomShapes +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme + +@Composable +fun QrCode() { // TODO: Add parameter containing the QR code value, and use it. + Box( + modifier = Modifier + .size(180.dp) + .clip(CustomShapes.SMALL) + .background(SwissTransferTheme.colors.qrCodeBackground), + contentAlignment = Alignment.Center, + ) { + Box( + modifier = Modifier + .size(160.dp) + .background(SwissTransferTheme.colors.qrCodeColor), // TODO: Use this color to tint the QR code. + ) + } +} + +@Preview(name = "Light mode") +@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL) +@Composable +private fun QrCodePreview() { + SwissTransferTheme { + Surface { + QrCode() + } + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/DocumentOnDocument.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/DocumentOnDocument.kt new file mode 100644 index 000000000..4191150c1 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/DocumentOnDocument.kt @@ -0,0 +1,95 @@ +package com.infomaniak.swisstransfer.ui.images.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType.Companion.NonZero +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.swisstransfer.ui.images.AppImages +import com.infomaniak.swisstransfer.ui.images.AppImages.AppIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +val AppIcons.DocumentOnDocument: ImageVector + get() { + + if (_documentOnDocument != null) return _documentOnDocument!! + + _documentOnDocument = Builder( + name = "DocumentOnDocument", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f, + ).apply { + path( + stroke = SolidColor(Color(0xFF9f9f9f)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero, + ) { + moveTo(7.5f, 6.75f) + lineTo(7.5f, 2.25f) + curveTo(7.5f, 1.852f, 7.658f, 1.471f, 7.939f, 1.189f) + curveTo(8.221f, 0.908f, 8.602f, 0.75f, 9.0f, 0.75f) + lineTo(16.629f, 0.75f) + curveTo(17.027f, 0.75f, 17.408f, 0.908f, 17.689f, 1.189f) + lineTo(20.561f, 4.061f) + curveTo(20.842f, 4.342f, 21.0f, 4.723f, 21.0f, 5.121f) + lineTo(21.0f, 15.75f) + curveTo(21.0f, 16.148f, 20.842f, 16.529f, 20.561f, 16.811f) + curveTo(20.279f, 17.092f, 19.898f, 17.25f, 19.5f, 17.25f) + lineTo(16.5f, 17.25f) + } + path( + stroke = SolidColor(Color(0xFF9f9f9f)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero, + ) { + moveTo(16.5f, 21.75f) + curveTo(16.5f, 22.148f, 16.342f, 22.529f, 16.061f, 22.811f) + curveTo(15.779f, 23.092f, 15.398f, 23.25f, 15.0f, 23.25f) + lineTo(4.5f, 23.25f) + curveTo(4.102f, 23.25f, 3.721f, 23.092f, 3.439f, 22.811f) + curveTo(3.158f, 22.529f, 3.0f, 22.148f, 3.0f, 21.75f) + lineTo(3.0f, 8.25f) + curveTo(3.0f, 7.852f, 3.158f, 7.471f, 3.439f, 7.189f) + curveTo(3.721f, 6.908f, 4.102f, 6.75f, 4.5f, 6.75f) + lineTo(12.129f, 6.75f) + curveTo(12.526f, 6.75f, 12.908f, 6.908f, 13.189f, 7.189f) + lineTo(16.061f, 10.061f) + curveTo(16.342f, 10.342f, 16.5f, 10.724f, 16.5f, 11.121f) + lineTo(16.5f, 21.75f) + close() + } + }.build() + + return _documentOnDocument!! + } + +private var _documentOnDocument: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box { + Image( + imageVector = AppIcons.DocumentOnDocument, + contentDescription = null, + modifier = Modifier.size(AppImages.previewSize), + ) + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/PersonBadgeShare.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/PersonBadgeShare.kt new file mode 100644 index 000000000..13b1b14f0 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/PersonBadgeShare.kt @@ -0,0 +1,118 @@ +package com.infomaniak.swisstransfer.ui.images.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType.Companion.EvenOdd +import androidx.compose.ui.graphics.PathFillType.Companion.NonZero +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.StrokeCap.Companion.Butt +import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.swisstransfer.ui.images.AppImages +import com.infomaniak.swisstransfer.ui.images.AppImages.AppIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +val AppIcons.PersonBadgeShare: ImageVector + get() { + + if (_personBadgeShare != null) return _personBadgeShare!! + + _personBadgeShare = Builder( + name = "PersonBadgeShare", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f, + ).apply { + path( + fill = SolidColor(Color(0xFF9f9f9f)), + strokeLineWidth = 0.0f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = EvenOdd, + ) { + moveTo(19.644f, 16.175f) + curveTo(19.673f, 16.206f, 19.702f, 16.237f, 19.732f, 16.268f) + curveTo(20.201f, 16.737f, 20.837f, 17.0f, 21.5f, 17.0f) + curveTo(22.163f, 17.0f, 22.799f, 16.737f, 23.268f, 16.268f) + curveTo(23.737f, 15.799f, 24.0f, 15.163f, 24.0f, 14.5f) + curveTo(24.0f, 13.837f, 23.737f, 13.201f, 23.268f, 12.732f) + curveTo(22.799f, 12.263f, 22.163f, 12.0f, 21.5f, 12.0f) + curveTo(20.837f, 12.0f, 20.201f, 12.263f, 19.732f, 12.732f) + curveTo(19.263f, 13.201f, 19.0f, 13.837f, 19.0f, 14.5f) + curveTo(19.0f, 14.604f, 19.007f, 14.708f, 19.019f, 14.81f) + lineTo(16.236f, 16.202f) + curveTo(15.771f, 15.752f, 15.148f, 15.5f, 14.5f, 15.5f) + curveTo(13.837f, 15.5f, 13.201f, 15.763f, 12.732f, 16.232f) + curveTo(12.263f, 16.701f, 12.0f, 17.337f, 12.0f, 18.0f) + curveTo(12.0f, 18.663f, 12.263f, 19.299f, 12.732f, 19.768f) + curveTo(13.201f, 20.237f, 13.837f, 20.5f, 14.5f, 20.5f) + curveTo(15.148f, 20.5f, 15.771f, 20.248f, 16.236f, 19.799f) + lineTo(19.019f, 21.19f) + curveTo(19.007f, 21.292f, 19.0f, 21.396f, 19.0f, 21.5f) + curveTo(19.0f, 22.163f, 19.263f, 22.799f, 19.732f, 23.268f) + curveTo(20.201f, 23.737f, 20.837f, 24.0f, 21.5f, 24.0f) + curveTo(22.163f, 24.0f, 22.799f, 23.737f, 23.268f, 23.268f) + curveTo(23.737f, 22.799f, 24.0f, 22.163f, 24.0f, 21.5f) + curveTo(24.0f, 20.837f, 23.737f, 20.201f, 23.268f, 19.732f) + curveTo(22.799f, 19.263f, 22.163f, 19.0f, 21.5f, 19.0f) + curveTo(20.837f, 19.0f, 20.201f, 19.263f, 19.732f, 19.732f) + curveTo(19.702f, 19.763f, 19.673f, 19.794f, 19.644f, 19.825f) + lineTo(16.954f, 18.48f) + curveTo(16.984f, 18.323f, 17.0f, 18.162f, 17.0f, 18.0f) + curveTo(17.0f, 17.838f, 16.984f, 17.677f, 16.954f, 17.52f) + lineTo(19.644f, 16.175f) + close() + } + path( + stroke = SolidColor(Color(0xFF9f9f9f)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero, + ) { + moveTo(9.983f, 19.75f) + lineTo(0.75f, 19.75f) + curveTo(0.75f, 17.622f, 1.617f, 15.581f, 3.161f, 14.076f) + curveTo(4.706f, 12.571f, 6.8f, 11.725f, 8.983f, 11.725f) + curveTo(10.829f, 11.725f, 12.61f, 12.329f, 14.05f, 13.425f) + moveTo(3.917f, 5.817f) + curveTo(3.917f, 7.16f, 4.45f, 8.449f, 5.401f, 9.399f) + curveTo(6.351f, 10.349f, 7.64f, 10.883f, 8.983f, 10.883f) + curveTo(10.327f, 10.883f, 11.616f, 10.349f, 12.566f, 9.399f) + curveTo(13.516f, 8.449f, 14.05f, 7.16f, 14.05f, 5.817f) + curveTo(14.05f, 4.473f, 13.516f, 3.184f, 12.566f, 2.234f) + curveTo(11.616f, 1.284f, 10.327f, 0.75f, 8.983f, 0.75f) + curveTo(7.64f, 0.75f, 6.351f, 1.284f, 5.401f, 2.234f) + curveTo(4.45f, 3.184f, 3.917f, 4.473f, 3.917f, 5.817f) + close() + } + }.build() + + return _personBadgeShare!! + } + +private var _personBadgeShare: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box { + Image( + imageVector = AppIcons.PersonBadgeShare, + contentDescription = null, + modifier = Modifier.size(AppImages.previewSize), + ) + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/received/components/ReceivedEmptyFab.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/received/components/ReceivedEmptyFab.kt index 28c378387..990ee1e33 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/received/components/ReceivedEmptyFab.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/received/components/ReceivedEmptyFab.kt @@ -18,7 +18,10 @@ package com.infomaniak.swisstransfer.ui.screen.main.received.components import android.content.res.Configuration -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.material3.Icon import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -47,7 +50,7 @@ fun ReceivedEmptyFab(isMessageVisible: () -> Boolean) { style = SwissTransferTheme.typography.bodyRegular, color = SwissTransferTheme.colors.secondaryTextColor, modifier = Modifier - .padding(PaddingValues(top = Margin.XLarge)) + .padding(top = Margin.XLarge) .constrainAs(text) { bottom.linkTo(icon.top, Margin.Small) end.linkTo(icon.end, Margin.Small) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/sent/SentListScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/sent/SentListScreen.kt index c1ff2b6b4..89ea230fd 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/sent/SentListScreen.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/sent/SentListScreen.kt @@ -29,29 +29,32 @@ import com.infomaniak.swisstransfer.ui.utils.PreviewAllWindows @Composable fun SentListScreen(transfers: List) { + + // TODO: Remove this when `transfers` contains the real data. val transfers = listOf( FileUi( fileName = "The 5-Step Guide to Not Breaking Your Code.txt", uid = "The 5-Step Guide to Not Breaking Your Code.txt", - fileSizeInBytes = 57689032, + fileSizeInBytes = 57_689_032L, mimeType = null, uri = "", ), FileUi( fileName = "Introduction to Turning It Off and On Again.pptx", uid = "Introduction to Turning It Off and On Again.pptx", - fileSizeInBytes = 89723143, + fileSizeInBytes = 89_723_143L, mimeType = null, uri = "", ), FileUi( fileName = "Learning to Copy and Paste: A Complete Guide.docx", uid = "Learning to Copy and Paste: A Complete Guide.docx", - fileSizeInBytes = 237866728, + fileSizeInBytes = 237_866_728L, mimeType = null, uri = "", ), ) + FileItemList( modifier = Modifier.padding(Margin.Medium), files = transfers, diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/NewTransferNavHost.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/NewTransferNavHost.kt index 767b06aba..ad79c163c 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/NewTransferNavHost.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/NewTransferNavHost.kt @@ -26,6 +26,7 @@ import com.infomaniak.swisstransfer.ui.navigation.NewTransferNavigation.* import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.ImportFilesScreen import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.TransferOptionsScreen import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.ValidateUserEmailScreen +import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.components.TransferType import com.infomaniak.swisstransfer.ui.screen.newtransfer.upload.UploadProgressScreen import com.infomaniak.swisstransfer.ui.screen.newtransfer.upload.UploadSuccessScreen @@ -48,7 +49,8 @@ fun NewTransferNavHost(navController: NavHostController, closeActivity: () -> Un UploadProgressScreen() } composable { - UploadSuccessScreen() + // TODO: Use correct TransferType instead of hard-coded value + UploadSuccessScreen(transferType = TransferType.MAIL) } } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/ImportedFilesCard.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/ImportedFilesCard.kt index d2d5a5645..091ccbd83 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/ImportedFilesCard.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/components/ImportedFilesCard.kt @@ -58,19 +58,19 @@ fun ImportedFilesCard( SwissTransferCard(modifier) { SharpRippleButton(onClick = { /*TODO*/ }) { Text( - pluralStringResource(R.plurals.filesCount, fileCount, fileCount), + text = pluralStringResource(R.plurals.filesCount, fileCount, fileCount), modifier = Modifier.padding(start = Margin.Medium), color = SwissTransferTheme.colors.secondaryTextColor, style = SwissTransferTheme.typography.bodySmallRegular, ) Text( - "•", + text = "•", modifier = Modifier.padding(horizontal = Margin.Small), color = SwissTransferTheme.colors.secondaryTextColor, style = SwissTransferTheme.typography.bodySmallRegular, ) Text( - formatSpaceLeft(humanReadableSize), + text = formatSpaceLeft(humanReadableSize), color = SwissTransferTheme.colors.secondaryTextColor, style = SwissTransferTheme.typography.bodySmallRegular, ) @@ -84,7 +84,7 @@ fun ImportedFilesCard( } LazyRow( - Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), contentPadding = PaddingValues(start = Margin.Medium, end = Margin.Medium, bottom = Margin.Medium), horizontalArrangement = Arrangement.spacedBy(Margin.Medium), ) { @@ -147,7 +147,7 @@ private fun ImportedFilesCardPreview(@PreviewParameter(FileUiListPreviewParamete files = { files }, humanReadableSize = { "20 GB" }, showUploadSourceChoiceBottomSheet = {}, - removeFileByUid = {} + removeFileByUid = {}, ) } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/UploadSuccessEmailScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/UploadSuccessEmailScreen.kt new file mode 100644 index 000000000..e20dd080d --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/UploadSuccessEmailScreen.kt @@ -0,0 +1,112 @@ +/* + * 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.upload + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.pluralStringResource +import androidx.compose.ui.unit.dp +import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.* +import com.infomaniak.swisstransfer.ui.images.AppImages.AppIllus +import com.infomaniak.swisstransfer.ui.images.illus.uploadSuccessEmail.UploadSuccessEmail +import com.infomaniak.swisstransfer.ui.theme.Margin +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme +import com.infomaniak.swisstransfer.ui.utils.PreviewAllWindows + +// TODO: Use correct emails instead of hard-coded values +@Composable +fun UploadSuccessEmailScreen( + emails: List = listOf( + "email@example.com", + "firstname.lastname@example.com", + "email@subdomain.example.com", + "firstname+lastname@example.com", + "email@123.123.123.123", + "email@[123.123.123.123]", + "\"email\"@example.com", + "1234567890@example.com", + "email@example-one.com", + "_______@example.com", + "email@example.name", + "email@example.museum", + "email@example.co.jp", + "firstname-lastname@example.com", + ), +) { + BottomStickyButtonScaffold( + topBar = { BrandTopAppBar() }, + bottomButton = { + LargeButton( + modifier = it, + titleRes = R.string.buttonFinished, + onClick = { /* TODO */ }, + ) + }, + content = { Content(emails) }, + ) +} + +@OptIn(ExperimentalLayoutApi::class) +@Composable +private fun Content(emails: List) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(Margin.Medium), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + + IllustratedMessageBlock( + icon = AppIllus.UploadSuccessEmail.image(), + title = R.string.uploadSuccessEmailTitle, + description = pluralStringResource(R.plurals.uploadSuccessEmailDescription, emails.count()), + ) + + Spacer(modifier = Modifier.height(Margin.Medium)) + + FlowRow( + modifier = Modifier.widthIn(max = 800.dp), + horizontalArrangement = Arrangement.Center, + ) { + emails.forEach { + EmailAddressChip( + text = it, + modifier = Modifier.padding(horizontal = Margin.XSmall), + ) + } + } + } +} + +@PreviewAllWindows +@Composable +private fun UploadSuccessEmailScreenPreview() { + SwissTransferTheme { + Surface { + UploadSuccessEmailScreen() + } + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/UploadSuccessQrScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/UploadSuccessQrScreen.kt new file mode 100644 index 000000000..5ee32a116 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/UploadSuccessQrScreen.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.screen.newtransfer.upload + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +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.text.style.TextAlign +import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.* +import com.infomaniak.swisstransfer.ui.images.AppImages.AppIcons +import com.infomaniak.swisstransfer.ui.images.AppImages.AppIllus +import com.infomaniak.swisstransfer.ui.images.icons.DocumentOnDocument +import com.infomaniak.swisstransfer.ui.images.icons.PersonBadgeShare +import com.infomaniak.swisstransfer.ui.images.illus.uploadSuccessQr.UploadSuccessQr +import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.components.TransferType +import com.infomaniak.swisstransfer.ui.theme.Dimens +import com.infomaniak.swisstransfer.ui.theme.Margin +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme +import com.infomaniak.swisstransfer.ui.utils.PreviewAllWindows + +@Composable +fun UploadSuccessQrScreen(transferType: TransferType) { + BottomStickyButtonScaffold( + topBar = { BrandTopAppBar() }, + topButton = { + LargeButton( + modifier = it, + style = ButtonType.PRIMARY, + titleRes = R.string.buttonShare, + imageVector = AppIcons.PersonBadgeShare, + onClick = { /* TODO */ }, + ) + }, + bottomButton = { + LargeButton( + modifier = it, + style = ButtonType.SECONDARY, + titleRes = R.string.buttonFinished, + onClick = { /* TODO */ }, + ) + }, + content = { Content(transferType) }, + ) +} + +@Composable +private fun Content(transferType: TransferType) { + + val uploadSuccessTitle = if (transferType == TransferType.QR_CODE) { + R.string.uploadSuccessQrTitle + } else { + R.string.uploadSuccessLinkTitle + } + + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(Margin.Medium), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + + Image( + imageVector = AppIllus.UploadSuccessQr.image(), + contentDescription = null, + ) + + Spacer(Modifier.height(Margin.XLarge)) + + Text( + text = stringResource(uploadSuccessTitle), + style = SwissTransferTheme.typography.h1, + color = SwissTransferTheme.colors.primaryTextColor, + ) + + Spacer(Modifier.height(Margin.XLarge)) + + QrCode() + + if (transferType != TransferType.QR_CODE) { + Spacer(Modifier.height(Margin.XLarge)) + Text( + text = stringResource(R.string.uploadSuccessLinkDescription), + style = SwissTransferTheme.typography.bodyRegular, + textAlign = TextAlign.Center, + color = SwissTransferTheme.colors.secondaryTextColor, + modifier = Modifier.widthIn(max = Dimens.DescriptionWidth), + ) + } + } + + // TODO: What do we want to do with this button placement? + LargeButton( + modifier = Modifier.padding(Margin.Medium), + style = ButtonType.SECONDARY, + titleRes = R.string.buttonCopyLink, + imageVector = AppIcons.DocumentOnDocument, + onClick = { /* TODO */ }, + ) +} + +@PreviewAllWindows +@Composable +private fun UploadSuccessQrScreenPreview() { + SwissTransferTheme { + Surface { + UploadSuccessQrScreen(transferType = TransferType.LINK) + } + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/UploadSuccessScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/UploadSuccessScreen.kt index a8446ccc0..e5e68de77 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/UploadSuccessScreen.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/upload/UploadSuccessScreen.kt @@ -17,10 +17,27 @@ */ package com.infomaniak.swisstransfer.ui.screen.newtransfer.upload -import androidx.compose.material3.Text +import androidx.compose.material3.Surface import androidx.compose.runtime.Composable +import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.components.TransferType +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme +import com.infomaniak.swisstransfer.ui.utils.PreviewAllWindows @Composable -fun UploadSuccessScreen() { - Text("UploadSuccessScreen") +fun UploadSuccessScreen(transferType: TransferType) { + if (transferType == TransferType.MAIL) { + UploadSuccessEmailScreen() + } else { + UploadSuccessQrScreen(transferType) + } +} + +@PreviewAllWindows +@Composable +private fun UploadSuccessScreenPreview() { + SwissTransferTheme { + Surface { + UploadSuccessScreen(TransferType.QR_CODE) + } + } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorDark.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorDark.kt index 915997981..828ecdd05 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorDark.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorDark.kt @@ -29,6 +29,7 @@ private const val dark1 = 0xFF152123 private const val dark2 = 0xFF2B383B private const val dark3 = 0xFF3C4F52 private const val shark = 0xFF9F9F9F +private const val polar_bear = 0xFFF5F5F5 private const val rabbit = 0xFFF1F1F1 private const val specific1 = 0xFF124426 @@ -84,4 +85,8 @@ val CustomDarkColorScheme = CustomColorScheme( transferTypeQrOnContainer = Color(green_main), transferTypeProximityContainer = Color(specific3), transferTypeProximityOnContainer = Color(specific4), + emailAddressChipColor = Color(green_dark), + onEmailAddressChipColor = Color(green_main), + qrCodeBackground = Color(polar_bear), + qrCodeColor = Color(green_dark), ) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorLight.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorLight.kt index 0834bb1cd..7bcefbb40 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorLight.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorLight.kt @@ -85,4 +85,8 @@ val CustomLightColorScheme = CustomColorScheme( transferTypeQrOnContainer = Color(green_main), transferTypeProximityContainer = Color(specific3), transferTypeProximityOnContainer = Color(specific4), + emailAddressChipColor = Color(green_contrast), + onEmailAddressChipColor = Color(green_dark), + qrCodeBackground = Color(polar_bear), + qrCodeColor = Color(green_dark), ) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/Theme.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/Theme.kt index 812a05d62..245b2d9a6 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/Theme.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/Theme.kt @@ -81,6 +81,10 @@ data class CustomColorScheme( val transferTypeQrOnContainer: Color = Color.Unspecified, val transferTypeProximityContainer: Color = Color.Unspecified, val transferTypeProximityOnContainer: Color = Color.Unspecified, + val emailAddressChipColor: Color = Color.Unspecified, + val onEmailAddressChipColor: Color = Color.Unspecified, + val qrCodeBackground: Color = Color.Unspecified, + val qrCodeColor: Color = Color.Unspecified, ) private val Shapes = Shapes( diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b938282ce..8189a7159 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -89,7 +89,10 @@ Dateien durchsuchen Foto- und Videogalerie Herunterladen von - Der Download-Link wurde erfolgreich an den folgenden Empfänger gesendet: + + Der Download-Link wurde erfolgreich an den folgenden Empfänger gesendet: + Der Download-Link wurde an die folgenden Empfänger gesendet: + Hoppla, das ist gesendet! Lass diesen QR-Code in deiner Umgebung scannen, um deine Dateien weiterzugeben, oder kopiere den untenstehenden Link. Deine Überweisung ist fertig! diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 584b8f995..c1cc14864 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -89,7 +89,10 @@ Examinar archivos Galería de fotos y vídeos Descargar desde - El enlace de descarga se ha enviado al siguiente destinatario: + + El enlace de descarga se ha enviado al siguiente destinatario: + El enlace de descarga se ha enviado a los siguientes destinatarios: + ¡Y ya está! Escanea este código QR a tu alrededor para compartir tus archivos o copia el enlace que aparece a continuación. Su transferencia está lista diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index afed8fadf..5fadb05b9 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -91,7 +91,10 @@ Parcourir les fichiers Galerie photos et vidéos Télécharger à partir de - Le lien de téléchargement a bien été envoyé au destinataire suivant : + + Le lien de téléchargement a bien été envoyé au destinataire suivant : + Le lien de téléchargement a été envoyé aux destinataires suivants : + Hop c’est envoyé ! Fais scanner ce QR code autour de toi pour partager tes fichiers ou copie le lien ci-dessous. Ton transfert est prêt ! diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index fd272521a..c975172d2 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -89,7 +89,10 @@ Sfoglia i file Galleria di foto e video Scarica da - Il link per il download è stato inviato al seguente destinatario: + + Il link per il download è stato inviato al seguente destinatario: + Il link per il download è stato inviato ai seguenti destinatari: + E si parte! Scansiona questo codice QR intorno a voi per condividere i vostri file o copiate il link qui sotto. Il trasferimento è pronto! diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2c2773c89..c1a587179 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -94,7 +94,10 @@ Browse files Photo and video gallery Upload from - The download link has been sent to the following recipient: + + The download link has been sent to the following recipient: + The download link has been sent to the following recipients: + It’s sent! Scan this QR code around you to share your files, or copy the link below. Your transfer is ready!