diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferTopAppBar.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferTopAppBar.kt index f8106f1e9..4eb48ebb8 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferTopAppBar.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferTopAppBar.kt @@ -31,6 +31,40 @@ import com.infomaniak.swisstransfer.ui.images.icons.Cross import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewAllWindows +@Composable +fun SwissTransferTopAppBar( + title: String? = null, + @StringRes titleRes: Int, + navigationMenu: TopAppBarButton? = null, + vararg actionMenus: TopAppBarButton, +) { + if (title != null) { + SwissTransferTopAppBar(title = title, navigationMenu = navigationMenu, actionMenus = actionMenus) + } else { + SwissTransferTopAppBar(titleRes = titleRes, navigationMenu = navigationMenu, actionMenus = actionMenus) + } +} + +@Composable +@OptIn(ExperimentalMaterial3Api::class) +fun SwissTransferTopAppBar( + title: String, + navigationMenu: TopAppBarButton? = null, + vararg actionMenus: TopAppBarButton, +) { + TopAppBar( + colors = TopAppBarDefaults.topAppBarColors( + containerColor = SwissTransferTheme.materialColors.tertiary, + titleContentColor = SwissTransferTheme.colors.toolbarTextColor, + actionIconContentColor = SwissTransferTheme.colors.toolbarIconColor, + navigationIconContentColor = SwissTransferTheme.colors.toolbarIconColor, + ), + title = { Text(text = title, style = SwissTransferTheme.typography.h2) }, + navigationIcon = { navigationMenu?.let { MenuButton(navigationMenu) } }, + actions = { actionMenus.forEach { actionMenu -> MenuButton(actionMenu) } }, + ) +} + @Composable @OptIn(ExperimentalMaterial3Api::class) fun SwissTransferTopAppBar( @@ -45,7 +79,7 @@ fun SwissTransferTopAppBar( actionIconContentColor = SwissTransferTheme.colors.toolbarIconColor, navigationIconContentColor = SwissTransferTheme.colors.toolbarIconColor, ), - title = { Text(stringResource(id = titleRes), style = SwissTransferTheme.typography.h2) }, + title = { Text(text = stringResource(id = titleRes), style = SwissTransferTheme.typography.h2) }, navigationIcon = { navigationMenu?.let { MenuButton(navigationMenu) } }, actions = { actionMenus.forEach { actionMenu -> MenuButton(actionMenu) } }, ) @@ -81,8 +115,7 @@ private fun SwissTransferTopAppBarPreview() { SwissTransferTopAppBar( titleRes = R.string.appName, navigationMenu = TopAppBarButton.backButton {}, - TopAppBarButton(AppIcons.Add, R.string.appName) {}, - TopAppBarButton.closeButton {}, + actionMenus = arrayOf(TopAppBarButton(AppIcons.Add, R.string.appName) {}, TopAppBarButton.closeButton {}), ) } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/FilesSize.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/FilesSize.kt new file mode 100644 index 000000000..9d593e829 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/FilesSize.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.screen.newtransfer + +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.pluralStringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.FileUi +import com.infomaniak.swisstransfer.ui.previewparameter.FileUiListPreviewParameter +import com.infomaniak.swisstransfer.ui.theme.Margin +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme +import com.infomaniak.swisstransfer.ui.utils.HumanReadableSizeUtils.formatSpaceLeft +import com.infomaniak.swisstransfer.ui.utils.HumanReadableSizeUtils.getFilesSize +import com.infomaniak.swisstransfer.ui.utils.HumanReadableSizeUtils.getSpaceLeft + +@Composable +fun FilesSize(files: List, withSpaceLeft: Boolean) { + Row( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + .padding(vertical = Margin.Medium) + ) { + val filesCount = files.count() + val filesSize = LocalContext.current.getFilesSize(files) + Text( + pluralStringResource(R.plurals.filesCount, filesCount, filesCount), + modifier = Modifier + .padding(start = Margin.Medium) + .wrapContentWidth(), + color = SwissTransferTheme.colors.secondaryTextColor, + style = SwissTransferTheme.typography.bodySmallRegular, + ) + Text( + "•", + modifier = Modifier.padding(horizontal = Margin.Small), + color = SwissTransferTheme.colors.secondaryTextColor, + style = SwissTransferTheme.typography.bodySmallRegular, + ) + Text( + filesSize, + color = SwissTransferTheme.colors.secondaryTextColor, + style = SwissTransferTheme.typography.bodySmallRegular, + ) + if (withSpaceLeft) { + val context = LocalContext.current + val spaceLeft = formatSpaceLeft { context.getSpaceLeft(files) } + Spacer(modifier = Modifier.weight(1f)) + Text( + modifier = Modifier.padding(horizontal = Margin.Medium), + text = spaceLeft, + color = SwissTransferTheme.colors.secondaryTextColor, + style = SwissTransferTheme.typography.bodySmallRegular, + ) + } + } +} + +@Preview +@Composable +fun FileSizePreview(@PreviewParameter(FileUiListPreviewParameter::class) files: List) { + SwissTransferTheme { + Surface { + FilesSize(files, withSpaceLeft = true) + } + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/FilesDetailsScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/FilesDetailsScreen.kt new file mode 100644 index 000000000..a46e64e87 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/importfiles/FilesDetailsScreen.kt @@ -0,0 +1,101 @@ +/* + * 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 + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.PreviewParameter +import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.FileItemList +import com.infomaniak.swisstransfer.ui.components.FileUi +import com.infomaniak.swisstransfer.ui.components.SwissTransferTopAppBar +import com.infomaniak.swisstransfer.ui.components.TopAppBarButton +import com.infomaniak.swisstransfer.ui.previewparameter.FileUiListPreviewParameter +import com.infomaniak.swisstransfer.ui.screen.newtransfer.FilesSize +import com.infomaniak.swisstransfer.ui.theme.Margin +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme +import com.infomaniak.swisstransfer.ui.utils.PreviewAllWindows + +@Composable +fun FilesDetailsScreen( + withSpaceLeft: Boolean, + title: String? = null, + files: List? = null, + onFileRemoved: (uuid: String) -> Unit, +) { + val files = 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, + 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, + 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, + mimeType = null, + uri = "", + ), + ) + Column { + SwissTransferTopAppBar( + title = title, + titleRes = R.string.importFilesScreenTitle, + navigationMenu = TopAppBarButton.backButton {}, + TopAppBarButton.closeButton {}, + ) + FilesSize(files, withSpaceLeft) + + FileItemList( + modifier = Modifier.padding(horizontal = Margin.Medium), + files = files, + isRemoveButtonVisible = true, + isCheckboxVisible = false, + isUidChecked = { false }, + setUidCheckStatus = { _, _ -> }, + onRemoveUid = { onFileRemoved(it) }, + ) + } +} + +@PreviewAllWindows +@Composable +private fun FilesDetailsScreenPreview(@PreviewParameter(FileUiListPreviewParameter::class) files: List) { + SwissTransferTheme { + Surface { + FilesDetailsScreen( + withSpaceLeft = true, + title = "My album", + files = files, + onFileRemoved = {}, + ) + } + } +} 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 5a19a816c..f20578cfc 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 @@ -35,11 +35,9 @@ import com.infomaniak.swisstransfer.ui.screen.newtransfer.NewTransferViewModel import com.infomaniak.swisstransfer.ui.screen.newtransfer.importfiles.components.ImportedFilesCard import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme -import com.infomaniak.swisstransfer.ui.utils.HumanReadableSizeUtils.getHumanReadableSize +import com.infomaniak.swisstransfer.ui.utils.HumanReadableSizeUtils.getFilesSize import com.infomaniak.swisstransfer.ui.utils.PreviewAllWindows -private const val TOTAL_FILE_SIZE: Long = 50_000_000_000L - @Composable fun ImportFilesScreen( newTransferViewModel: NewTransferViewModel = hiltViewModel(), @@ -68,9 +66,7 @@ private fun ImportFilesScreen( val importedFiles = files() val humanReadableSize = remember(importedFiles) { - val usedSpace = importedFiles.sumOf { it.fileSizeInBytes } - val spaceLeft = (TOTAL_FILE_SIZE - usedSpace).coerceAtLeast(0) - getHumanReadableSize(context, spaceLeft) + context.getFilesSize(importedFiles) } val isSendButtonEnabled by remember { derivedStateOf { importedFiles.isNotEmpty() } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/HumanReadableSizeUtils.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/HumanReadableSizeUtils.kt index 1ea0e0e32..b7feedad5 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/HumanReadableSizeUtils.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/HumanReadableSizeUtils.kt @@ -24,10 +24,20 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.pluralStringResource import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.FileUi object HumanReadableSizeUtils { - fun getHumanReadableSize(context: Context, sizeInBytes: Long): String { - return Formatter.formatShortFileSize(context, sizeInBytes) + private const val TOTAL_FILE_SIZE: Long = 50_000_000_000L + + private fun getHumanReadableSize(context: Context, sizeInBytes: Long) = Formatter.formatFileSize(context, sizeInBytes) + + private fun getFilesSizeInBytes(files: List) = files.sumOf { it.fileSizeInBytes } + + fun Context.getFilesSize(files: List): String = getHumanReadableSize(this, getFilesSizeInBytes(files)) + + fun Context.getSpaceLeft(files: List): String { + val spaceLeft = (TOTAL_FILE_SIZE - getFilesSizeInBytes(files)).coerceAtLeast(0) + return getHumanReadableSize(this, spaceLeft) } @Composable @@ -42,7 +52,7 @@ object HumanReadableSizeUtils { val sizeParts = humanReadableSize.split(' ', Typography.nbsp) return if (sizeParts.size == 2) { - val local = resources.configuration.getLocales().get(0) + val local = resources.configuration.getLocales()[0] val parsedNumber = NumberFormat.getInstance(local).parse(sizeParts.first()) parsedNumber?.toDouble()?.toInt() ?: 0 } else {