From 5fc8bceddf4c08942d5ce184f15284f8b609d001 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Thu, 19 Sep 2024 17:00:11 +0200 Subject: [PATCH 01/15] Create an ImageTile component --- app/build.gradle.kts | 2 + .../swisstransfer/ui/components/ImageTile.kt | 156 ++++++++++++++++++ .../ui/images/icons/CrossThick.kt | 65 ++++++++ .../swisstransfer/ui/theme/ColorDark.kt | 2 + .../swisstransfer/ui/theme/ColorLight.kt | 2 + .../swisstransfer/ui/theme/Theme.kt | 1 + app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-it/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + gradle/libs.versions.toml | 2 + 12 files changed, 235 insertions(+) create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/CrossThick.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 19b93c19e..4d5530c5a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -86,6 +86,8 @@ dependencies { implementation(libs.swisstransfer.core) + implementation(libs.coil.compose) + // Compose preview tools implementation(libs.compose.ui.tooling.preview) debugImplementation(libs.compose.ui.tooling) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt new file mode 100644 index 000000000..595adb587 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt @@ -0,0 +1,156 @@ +/* + * 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.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.painter.ColorPainter +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage +import coil.request.ImageRequest +import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.images.AppImages +import com.infomaniak.swisstransfer.ui.images.icons.CrossThick +import com.infomaniak.swisstransfer.ui.theme.Margin +import com.infomaniak.swisstransfer.ui.theme.Shapes +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme +import com.infomaniak.swisstransfer.ui.utils.PreviewMobile +import com.infomaniak.swisstransfer.ui.utils.PreviewTablet + + +@Composable +fun ImageTile( + title: String, + description: String, + isRemoveButtonVisible: Boolean, + isCheckboxVisible: Boolean, + isChecked: () -> Boolean = { false }, + onClick: () -> Unit, + onRemove: (() -> Unit)? = null, + onCheckedChange: ((Boolean) -> Unit)? = null, +) { + Card( + onClick = onClick, + modifier = Modifier + .fillMaxSize() + .aspectRatio(164 / 152f), + shape = Shapes.small, + border = BorderStroke(width = 1.dp, SwissTransferTheme.materialColors.outlineVariant) + ) { + Box( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + ) { + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data("https://fastly.picsum.photos/id/1/200/300.jpg?hmac=jH5bDkLr6Tgy3oAg5khKCHeunZMHq0ehBZr6vGifPLY") + .crossfade(true) + .build(), + placeholder = ColorPainter(Color.Gray), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize(), + ) + + if (isCheckboxVisible) { + Checkbox( + checked = isChecked(), + onCheckedChange = onCheckedChange, + Modifier + .align(Alignment.TopStart) + .padding(12.dp), + ) + } + + if (isRemoveButtonVisible) { + Button( + modifier = Modifier + .size(Margin.XXLarge) + .padding(12.dp) + .align(Alignment.TopEnd), + contentPadding = PaddingValues(0.dp), + shape = CircleShape, + colors = ButtonDefaults.buttonColors(containerColor = SwissTransferTheme.colors.imageTileRemoveButtonBackground), + onClick = onRemove ?: {}, + ) { + Icon( + modifier = Modifier.size(Margin.Small), + imageVector = AppImages.AppIcons.CrossThick, + contentDescription = stringResource(R.string.contentDescriptionButtonRemove), + tint = Color.White + ) + } + } + } + + Column(Modifier.padding(Margin.Small)) { + Text( + text = title, + style = SwissTransferTheme.typography.bodySmallRegular, + color = SwissTransferTheme.colors.primaryTextColor, + maxLines = 1, + overflow = TextOverflow.MiddleEllipsis, + ) + Text( + text = description, + style = SwissTransferTheme.typography.bodySmallRegular, + color = SwissTransferTheme.colors.secondaryTextColor, + maxLines = 1, + overflow = TextOverflow.MiddleEllipsis, + ) + } + } +} + +@PreviewMobile +@PreviewTablet +@Composable +private fun ImageTilePreview() { + SwissTransferTheme { + Surface { + Column( + modifier = Modifier + .padding(24.dp) + .size(164.dp) + ) + { + var isChecked by remember { mutableStateOf(true) } + ImageTile( + title = "Time-Clock-Circle--Streamline-Ultimate.svg (1).svg", + description = "1.4 Mo", + isRemoveButtonVisible = true, + isCheckboxVisible = true, + isChecked = { isChecked }, + onClick = { isChecked = !isChecked }, + onRemove = {}, + ) + } + } + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/CrossThick.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/CrossThick.kt new file mode 100644 index 000000000..845f8c729 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/CrossThick.kt @@ -0,0 +1,65 @@ +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.group +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 androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +val AppImages.AppIcons.CrossThick: ImageVector + get() { + if (_crossThick != null) { + return _crossThick!! + } + _crossThick = Builder( + name = "CrossThick", + defaultWidth = 16.0.dp, + defaultHeight = 16.0.dp, + viewportWidth = 16.0f, + viewportHeight = 16.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 2.0f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(1.0f, 15.0f) + lineTo(15.0f, 1.0f) + moveToRelative(0.0f, 14.0f) + lineTo(1.0f, 1.0f) + } + } + }.build() + return _crossThick!! + } + +private var _crossThick: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box { + Image( + imageVector = AppImages.AppIcons.CrossThick, + contentDescription = null, + modifier = Modifier.size(AppImages.previewSize) + ) + } +} 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 63f1d4fee..7981da945 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 @@ -40,6 +40,7 @@ private const val specific5 = 0xFF49DEFD // Extra palette private const val elephant = 0xFF666666 private const val white = 0xFFFFFFFF +private const val black_translucent = 0x80000000 private const val error = 0xFFFC8878 @@ -74,6 +75,7 @@ val CustomDarkColorScheme = CustomColorScheme( navigationItemBackground = Color(dark2), tertiaryButtonBackground = Color(dark2), selectedSettingItem = Color(dark2), + imageTileRemoveButtonBackground = Color(black_translucent), transferTypeLinkContainer = Color(specific1), transferTypeLinkOnContainer = Color(green_main), transferTypeEmailContainer = 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 0a092c132..295239837 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 @@ -41,6 +41,7 @@ private const val specific4 = 0xFFCF9E1B // Extra palette private const val on_primary = 0xFFF7FCFA private const val white = 0xFFFFFFFF +private const val black_translucent = 0x80000000 private const val error = 0xFFF44336 @@ -75,6 +76,7 @@ val CustomLightColorScheme = CustomColorScheme( navigationItemBackground = LightColorScheme.background, tertiaryButtonBackground = Color(rabbit), selectedSettingItem = Color(rabbit), + imageTileRemoveButtonBackground = Color(black_translucent), transferTypeLinkContainer = Color(specific1), transferTypeLinkOnContainer = Color(green_main), transferTypeEmailContainer = Color(specific2), 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 4e4a316e1..5f78ef9d7 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 @@ -75,6 +75,7 @@ data class CustomColorScheme( val navigationItemBackground: Color = Color.Unspecified, val tertiaryButtonBackground: Color = Color.Unspecified, val selectedSettingItem: Color = Color.Unspecified, + val imageTileRemoveButtonBackground: Color = Color.Unspecified, val transferTypeLinkContainer: Color = Color.Unspecified, val transferTypeLinkOnContainer: Color = Color.Unspecified, val transferTypeEmailContainer: Color = Color.Unspecified, diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 6bf2c9cb3..2aa1eb992 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -20,6 +20,7 @@ Weiter zu Zurück Schliessen + Datei entfernen Neuer Transfer Mache deine erste Überweisung! Zu übertragende Dateien diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 65a1e4c87..5cf57976d 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -20,6 +20,7 @@ Siguiente Volver Cerrar + Eliminar archivo Nueva transferencia Realice su primera transferencia Archivos para transferir diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f4777f365..6d2cc0d60 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -20,6 +20,7 @@ Suivant Retour Fermer + Supprimer le fichier Nouveau transfert Fais ton premier transfert ! Fichiers à transférer diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 70eb953fe..9bc9fdc39 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -20,6 +20,7 @@ Avanti Indietro Chiudi + Rimuovi il file Nuovo trasferimento Effettua il tuo primo trasferimento! File da trasferire diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0e93fab58..c2be9758a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,6 +23,7 @@ Next Back Close + Remove file New transfer Make your first transfer! Files to transfer diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5c95d1969..1d46bbf2e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,6 +2,7 @@ activityCompose = "1.9.2" adaptiveLayout = "1.0.0" agp = "8.6.1" +coilCompose = "2.7.0" composeAlpha = "1.8.0-alpha02" composeBom = "2024.09.02" constraintlayoutCompose = "1.0.1" @@ -22,6 +23,7 @@ androidx-adaptive = { module = "androidx.compose.material3.adaptive:adaptive", v androidx-adaptive-layout = { module = "androidx.compose.material3.adaptive:adaptive-layout", version.ref = "adaptiveLayout" } androidx-adaptive-navigation = { module = "androidx.compose.material3.adaptive:adaptive-navigation", version.ref = "adaptiveLayout" } androidx-constraintlayout-compose = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "constraintlayoutCompose" } +coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coilCompose" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } From a1546cb6056c295220752ef6bac219bc949927f5 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Fri, 20 Sep 2024 11:03:39 +0200 Subject: [PATCH 02/15] Dummy usage of ImageTileComponent --- app/src/main/AndroidManifest.xml | 3 +++ .../swisstransfer/ui/components/ImageTile.kt | 8 +++---- .../ui/screen/main/sent/SentListScreen.kt | 24 +++++++++++++------ .../ui/screen/main/sent/SentViewModel.kt | 2 +- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dc91f9387..986f30184 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,6 +19,9 @@ + + + ) { - LazyColumn { - items(items = transfers, key = { UUID.randomUUID() }) { - Text(text = "Sent screen") + LazyVerticalGrid( + modifier = Modifier.padding(Margin.Medium), + columns = GridCells.Adaptive(150.dp), + verticalArrangement = Arrangement.spacedBy(Margin.Medium), + horizontalArrangement = Arrangement.spacedBy(Margin.Medium), + ) { + items(3) { + ImageTile("Time-Clock-Circle--Streamline-Ultimate.svg (1).svg", "1.4 MB", true, true, { true }, {}, {}) } } } + @PreviewSmallWindow @PreviewLargeWindow @Composable diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/sent/SentViewModel.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/sent/SentViewModel.kt index b622fc490..10f39925e 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/sent/SentViewModel.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/sent/SentViewModel.kt @@ -27,5 +27,5 @@ import javax.inject.Inject @HiltViewModel class SentViewModel @Inject constructor() : ViewModel() { - val transfers = flow> { emit(emptyList()) }.stateIn(viewModelScope, SharingStarted.Eagerly, null) + val transfers = flow> { emit(listOf(1)) }.stateIn(viewModelScope, SharingStarted.Eagerly, null) } From ee3585b4a528f68a286a10fa3ed5b7f3e6d768f6 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Fri, 20 Sep 2024 14:28:53 +0200 Subject: [PATCH 03/15] Basic module to share file type data --- FileTypes/.gitignore | 1 + FileTypes/build.gradle.kts | 43 ++++++++ FileTypes/consumer-rules.pro | 0 FileTypes/proguard-rules.pro | 21 ++++ FileTypes/src/main/AndroidManifest.xml | 4 + .../library/filetypes/FileTypeIcons.kt | 20 ++++ .../infomaniak/library/filetypes/FileTypes.kt | 46 ++++++++ .../infomaniak/library/filetypes/icons/Pdf.kt | 102 ++++++++++++++++++ .../library/filetypes/icons/Text.kt | 74 +++++++++++++ .../swisstransfer/ui/components/ImageTile.kt | 5 +- build.gradle.kts | 1 + gradle/libs.versions.toml | 7 ++ settings.gradle.kts | 1 + 13 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 FileTypes/.gitignore create mode 100644 FileTypes/build.gradle.kts create mode 100644 FileTypes/consumer-rules.pro create mode 100644 FileTypes/proguard-rules.pro create mode 100644 FileTypes/src/main/AndroidManifest.xml create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypes.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt diff --git a/FileTypes/.gitignore b/FileTypes/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/FileTypes/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/FileTypes/build.gradle.kts b/FileTypes/build.gradle.kts new file mode 100644 index 000000000..16b450462 --- /dev/null +++ b/FileTypes/build.gradle.kts @@ -0,0 +1,43 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) +} + +android { + namespace = "com.infomaniak.library.filetypes" + compileSdk = 34 + + defaultConfig { + minSdk = 25 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.ui.android) + implementation(libs.androidx.foundation.android) + implementation(libs.androidx.ui.tooling.preview.android) + // implementation(libs.androidx.appcompat) + // implementation(libs.material) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + // androidTestImplementation(libs.androidx.espresso.core) +} diff --git a/FileTypes/consumer-rules.pro b/FileTypes/consumer-rules.pro new file mode 100644 index 000000000..e69de29bb diff --git a/FileTypes/proguard-rules.pro b/FileTypes/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /dev/null +++ b/FileTypes/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/FileTypes/src/main/AndroidManifest.xml b/FileTypes/src/main/AndroidManifest.xml new file mode 100644 index 000000000..8bdb7e14b --- /dev/null +++ b/FileTypes/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt new file mode 100644 index 000000000..283653eca --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt @@ -0,0 +1,20 @@ +/* + * 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.library.filetypes + +object FileTypeIcons diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypes.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypes.kt new file mode 100644 index 000000000..fbb2f9d9f --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypes.kt @@ -0,0 +1,46 @@ +/* + * 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.library.filetypes + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import com.infomaniak.library.filetypes.icons.Pdf +import com.infomaniak.library.filetypes.icons.Text + +enum class FileTypes(val icon: ImageVector? = null, val color: @Composable (FileTypeColors) -> Color) { + PDF(icon = FileTypeIcons.Pdf, color = { it.pdf }), + TEXT(icon = FileTypeIcons.Text, color = { it.text }), +} + +@Immutable +data class FileTypeColors( + val pdf: Color, + val text: Color, +) + +val LightFileTypeColors = FileTypeColors( + pdf = Color(0xFFEF5803), + text = Color(0xFF2196F3), +) + +val DarkFileTypeColors = FileTypeColors( + pdf = Color(0xFFFD9459), + text = Color(0xFF81C4F8), +) diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt new file mode 100644 index 000000000..3d39172b0 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt @@ -0,0 +1,102 @@ +/* + * 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.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +val FileTypeIcons.Pdf: ImageVector + get() { + if (_pdf != null) { + return _pdf!! + } + _pdf = Builder( + name = "Pdf", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.5f, 21.757f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, 1.5f) + horizontalLineTo(3.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, -1.5f) + verticalLineToRelative(-19.5f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.5f, -1.5f) + horizontalLineToRelative(15.0f) + arcToRelative(1.48f, 1.48f, 0.0f, false, true, 1.05f, 0.43f) + lineToRelative(3.0f, 2.88f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 0.45f, 1.07f) + close() + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(5.62f, 4.259f) + curveToRelative(-2.339f, 1.487f, 0.756f, 5.313f, 4.878f, 7.908f) + curveToRelative(1.3f, 0.83f, 7.637f, 4.933f, 8.56f, 2.113f) + curveToRelative(0.776f, -2.38f, -2.004f, -2.934f, -7.647f, -1.21f) + curveToRelative(-7.06f, 2.153f, -7.343f, 6.43f, -5.245f, 6.892f) + curveToRelative(2.79f, 0.625f, 3.325f, -5.498f, 3.472f, -6.687f) + curveTo(10.1f, 8.946f, 8.169f, 2.669f, 5.62f, 4.259f) + } + } + }.build() + return _pdf!! + } + +private var _pdf: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Pdf, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt new file mode 100644 index 000000000..8bb13f189 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt @@ -0,0 +1,74 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +val FileTypeIcons.Text: ImageVector + get() { + if (_text != null) { + return _text!! + } + _text = Builder( + name = "Text", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.5f, 21.757f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, 1.5f) + horizontalLineTo(3.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, -1.5f) + verticalLineToRelative(-19.5f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.5f, -1.5f) + horizontalLineToRelative(15.045f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.048f, 0.426f) + lineToRelative(2.954f, 2.883f) + arcTo(1.5f, 1.5f, 0.0f, false, true, 22.5f, 5.14f) + close() + moveTo(6.0f, 7.507f) + horizontalLineToRelative(12.0f) + moveToRelative(-12.0f, 4.5f) + horizontalLineToRelative(12.0f) + moveToRelative(-12.0f, 4.5f) + horizontalLineToRelative(6.0f) + } + } + }.build() + return _text!! + } + +private var _text: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Text, contentDescription = null) + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt index e2b0e7f67..15df85886 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt @@ -18,6 +18,7 @@ package com.infomaniak.swisstransfer.ui.components import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.* @@ -25,7 +26,6 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.painter.ColorPainter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource @@ -59,6 +59,7 @@ fun ImageTile( modifier = Modifier .fillMaxSize() .aspectRatio(164 / 152f), + colors = CardDefaults.cardColors(containerColor = SwissTransferTheme.materialColors.background), shape = Shapes.small, border = BorderStroke(width = 1.dp, SwissTransferTheme.materialColors.outlineVariant) ) { @@ -66,13 +67,13 @@ fun ImageTile( modifier = Modifier .weight(1f) .fillMaxWidth() + .background(SwissTransferTheme.materialColors.surfaceContainerHighest) ) { AsyncImage( model = ImageRequest.Builder(LocalContext.current) .data("https://fastly.picsum.photos/id/1/200/300.jpg?hmac=jH5bDkLr6Tgy3oAg5khKCHeunZMHq0ehBZr6vGifPLY") .crossfade(true) .build(), - placeholder = ColorPainter(Color.Gray), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier.fillMaxSize(), diff --git a/build.gradle.kts b/build.gradle.kts index 88ab05926..dcad8f2e1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,4 +12,5 @@ plugins { alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.kapt) apply false alias(libs.plugins.hilt) apply false + alias(libs.plugins.android.library) apply false } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1d46bbf2e..3d7cfde5e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,6 +16,9 @@ lifecycleRuntimeKtx = "2.8.6" navigation = "2.8.1" serialization = "1.7.1" swisstransfer = "0.1.1" +uiAndroid = "1.7.2" +foundationAndroid = "1.7.3" +uiToolingPreviewAndroid = "1.7.3" [libraries] androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } @@ -43,6 +46,9 @@ swisstransfer-core = { module = "com.github.Infomaniak.multiplatform-SwissTransf # Tests androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-ui-android = { group = "androidx.compose.ui", name = "ui-android", version.ref = "uiAndroid" } +androidx-foundation-android = { group = "androidx.compose.foundation", name = "foundation-android", version.ref = "foundationAndroid" } +androidx-ui-tooling-preview-android = { group = "androidx.compose.ui", name = "ui-tooling-preview-android", version.ref = "uiToolingPreviewAndroid" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } @@ -50,3 +56,4 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = " hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +android-library = { id = "com.android.library", version.ref = "agp" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 1a80ad33d..55b9a40b6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -25,3 +25,4 @@ dependencyResolutionManagement { rootProject.name = "android-SwissTransfer" include(":app") +include(":FileTypes") From 42d6b8ee3968bbce760bd50209d3f537f50aba9f Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Fri, 4 Oct 2024 15:55:27 +0200 Subject: [PATCH 04/15] Add icons and use them in ImageTile --- FileTypes/build.gradle.kts | 10 +- .../infomaniak/library/filetypes/FileType.kt | 61 ++++++++ .../library/filetypes/FileTypeGuesser.kt | 139 ++++++++++++++++++ .../library/filetypes/FileTypeIcons.kt | 2 +- .../infomaniak/library/filetypes/FileTypes.kt | 46 ------ .../library/filetypes/icons/Archive.kt | 130 ++++++++++++++++ .../library/filetypes/icons/Audio.kt | 115 +++++++++++++++ .../library/filetypes/icons/Calendar.kt | 72 +++++++++ .../library/filetypes/icons/Code.kt | 84 +++++++++++ .../library/filetypes/icons/Font.kt | 86 +++++++++++ .../library/filetypes/icons/Image.kt | 82 +++++++++++ .../infomaniak/library/filetypes/icons/Pdf.kt | 2 +- .../library/filetypes/icons/Points.kt | 95 ++++++++++++ .../library/filetypes/icons/Sheet.kt | 93 ++++++++++++ .../library/filetypes/icons/Text.kt | 2 +- .../library/filetypes/icons/Unknown.kt | 68 +++++++++ .../library/filetypes/icons/Vcard.kt | 82 +++++++++++ .../library/filetypes/icons/Video.kt | 84 +++++++++++ app/build.gradle.kts | 1 + .../swisstransfer/ui/components/ImageTile.kt | 112 ++++++++++++-- .../ui/screen/main/sent/SentListScreen.kt | 11 +- gradle/libs.versions.toml | 2 + 22 files changed, 1315 insertions(+), 64 deletions(-) create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt delete mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypes.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Archive.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Audio.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Calendar.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Code.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Font.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Image.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Points.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Sheet.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Unknown.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Vcard.kt create mode 100644 FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Video.kt diff --git a/FileTypes/build.gradle.kts b/FileTypes/build.gradle.kts index 16b450462..04f540227 100644 --- a/FileTypes/build.gradle.kts +++ b/FileTypes/build.gradle.kts @@ -1,6 +1,7 @@ plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) + alias(libs.plugins.compose.compiler) } android { @@ -8,7 +9,7 @@ android { compileSdk = 34 defaultConfig { - minSdk = 25 + minSdk = 24 testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") @@ -27,6 +28,12 @@ android { kotlinOptions { jvmTarget = "1.8" } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.14" + } } dependencies { @@ -39,5 +46,6 @@ dependencies { // implementation(libs.material) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) + debugImplementation(libs.androidx.ui.tooling) // androidTestImplementation(libs.androidx.espresso.core) } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt new file mode 100644 index 000000000..5b32f608f --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt @@ -0,0 +1,61 @@ +/* + * 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.library.filetypes + +import android.webkit.MimeTypeMap +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import com.infomaniak.library.filetypes.icons.* + +private val MEDIA_COLOR_LIGHT = Color(0xFF00BCD4) +private val MEDIA_COLOR_DARK = Color(0xFF86DEEA) + +enum class FileType(val icon: ImageVector, private val colorLight: Color, private val colorDark: Color) { + ARCHIVE(icon = FileTypeIcons.Archive, colorLight = Color(0xFF607D8B), colorDark = Color(0xFFA5B7C0)), + AUDIO(icon = FileTypeIcons.Audio, colorLight = MEDIA_COLOR_LIGHT, colorDark = MEDIA_COLOR_DARK), + CALENDAR(icon = FileTypeIcons.Calendar, colorLight = Color(0xFF36D0EB), colorDark = Color(0xFFA2E9F6)), + CODE(icon = FileTypeIcons.Code, colorLight = Color(0xFF673AB7), colorDark = Color(0xFF956DDD)), + FONT(icon = FileTypeIcons.Font, colorLight = Color(0xFF9C26B0), colorDark = Color(0xFFCD68DE)), + IMAGE(icon = FileTypeIcons.Image, colorLight = MEDIA_COLOR_LIGHT, colorDark = MEDIA_COLOR_DARK), + PDF(icon = FileTypeIcons.Pdf, colorLight = Color(0xFFEF5803), colorDark = Color(0xFFFD9459)), + POINTS(icon = FileTypeIcons.Points, colorLight = Color(0xFFFF9802), colorDark = Color(0xFFFFC166)), + SPREADSHEET(icon = FileTypeIcons.Sheet, colorLight = Color(0xFF3EBF4D), colorDark = Color(0xFF78D383)), + TEXT(icon = FileTypeIcons.Text, colorLight = Color(0xFF2196F3), colorDark = Color(0xFF81C4F8)), + VCARD(icon = FileTypeIcons.Vcard, colorLight = Color(0xFF9D66E1), colorDark = Color(0xFFC8AAEE)), + VIDEO(icon = FileTypeIcons.Video, colorLight = MEDIA_COLOR_LIGHT, colorDark = MEDIA_COLOR_DARK), + + UNKNOWN(icon = FileTypeIcons.Unknown, colorLight = Color(0xFF85A2B6), colorDark = Color(0xFFAFC2CF)); + + fun color(isDark: Boolean): Color { + return if (isDark) colorDark else colorLight + } + + fun guessFromFileName(fileName: String): FileType { + val extension = fileName.extractExtension() + val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: return FileType.UNKNOWN + return FileTypeGuesser.getFileTypeFromMimeType(mimeType) + } + + private fun String.extractExtension(): String? { + val fileName = lastIndexOf('/').takeIf { it != -1 }?.let { fileNameStart -> + substring(fileNameStart + 1) + } ?: this + + return fileName.substringAfterLast(".").takeIf { it.isNotEmpty() } + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt new file mode 100644 index 000000000..897fbbd55 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt @@ -0,0 +1,139 @@ +/* + * 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.library.filetypes + +object FileTypeGuesser { + private val pdfMatches = mimeTypeSetOf( + "application/pdf", + "application/acrobat", + "application/nappdf", + "application/x-pdf", + ) + + val calendarMatches = mimeTypeSetOf( + "application/ics", + "text/calendar", + ) + + private val vcardMatches = mimeTypeSetOf( + "text/vcard", + "text/directory", + "text/x-vcard", + ) + + private val imageMatches = mimeTypeSetOf( + "image/", + "application/postscript", + "application/x-font-type1", + ) + + private val audioMatches = mimeTypeSetOf("audio/") + + private val videoMatches = mimeTypeSetOf( + "video/", + "model/vnd.mts", + "application/mxf", + "application/vnd.rn-realmedia", + "application/x-shockwave-flash", + ) + + private val sheetMatches = mimeTypeSetOf( + "text/csv", + "application/vnd.ms-excel", + "application/msexcel", + "application/x-msexcel", + "application/vnd.openxmlformats-officedocument.spreadsheetml", + "application/vnd.oasis.opendocument.spreadsheet", + ) + + private val pointMatches = mimeTypeSetOf( + "application/powerpoint", + "application/mspowerpoint", + "application/vnd.ms-powerpoint", + "application/x-mspowerpoint", + "application/vnd.openxmlformats-officedocument.presentationml", + "application/vnd.oasis.opendocument.presentation", + ) + + private val textMatches = mimeTypeSetOf( + "text/markdown", + "text/plain", + "application/msword", + "application/vnd.ms-word", + "application/vnd.oasis.opendocument.text", + "application/vnd.openxmlformats-officedocument.wordprocessingml", + ) + + private val archiveMatches = mimeTypeSetOf( + "application/x-7z-compressed", + "application/x-ace-compressed", + "application/x-cfs-compressed", + "application/x-compressed-tar", + "application/x-cpio-compressed", + "application/x-dgc-compressed", + "application/x-gca-compressed", + "application/x-lrzip-compressed-tar", + "application/x-lz4-compressed-tar", + "application/x-compress", + "application/gzip", + "application/x-zip-compressed", + "application/x-zip", + "application/zip", + "application/x-bzip", + "application/x-bzip2", + "application/java-archive", + "application/x-rar-compressed", + "application/application/x-tar", + ) + + private val codeMatches = mimeTypeSetOf( + "text/", // Beware of the order, this must come after every other "text/" + "application/json", + "application/xml", + ) + + private val fontMatches = mimeTypeSetOf( + "font/", + "application/vnd.afpc.foca-codedfont", + "application/vnd.font-fontforge-sfd", + "application/vnd.ms-fontobject", + "application/font-tdpfr", + ) + + fun getFileTypeFromMimeType(mimeType: String): FileType = when (mimeType) { + in pdfMatches -> FileType.PDF + in calendarMatches -> FileType.CALENDAR + in vcardMatches -> FileType.VCARD + in imageMatches -> FileType.IMAGE + in audioMatches -> FileType.AUDIO + in videoMatches -> FileType.VIDEO + in sheetMatches -> FileType.SPREADSHEET + in pointMatches -> FileType.POINTS + in textMatches -> FileType.TEXT + in archiveMatches -> FileType.ARCHIVE + in codeMatches -> FileType.CODE // Beware of the order, this must come after every other "text/" + in fontMatches -> FileType.FONT + else -> FileType.UNKNOWN + } + + private fun mimeTypeSetOf(vararg mimeTypes: String) = MimeTypeSet(mimeTypes.toSet()) + + class MimeTypeSet(private val mimeTypes: Set) : Set by mimeTypes { + override fun contains(element: String): Boolean = mimeTypes.any { mimeType -> element.startsWith(mimeType) } + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt index 283653eca..6ae6b66ee 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt @@ -17,4 +17,4 @@ */ package com.infomaniak.library.filetypes -object FileTypeIcons +internal object FileTypeIcons diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypes.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypes.kt deleted file mode 100644 index fbb2f9d9f..000000000 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypes.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.library.filetypes - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Immutable -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import com.infomaniak.library.filetypes.icons.Pdf -import com.infomaniak.library.filetypes.icons.Text - -enum class FileTypes(val icon: ImageVector? = null, val color: @Composable (FileTypeColors) -> Color) { - PDF(icon = FileTypeIcons.Pdf, color = { it.pdf }), - TEXT(icon = FileTypeIcons.Text, color = { it.text }), -} - -@Immutable -data class FileTypeColors( - val pdf: Color, - val text: Color, -) - -val LightFileTypeColors = FileTypeColors( - pdf = Color(0xFFEF5803), - text = Color(0xFF2196F3), -) - -val DarkFileTypeColors = FileTypeColors( - pdf = Color(0xFFFD9459), - text = Color(0xFF81C4F8), -) diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Archive.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Archive.kt new file mode 100644 index 000000000..245c91c72 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Archive.kt @@ -0,0 +1,130 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.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.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Archive: ImageVector + get() { + if (_archive != null) { + return _archive!! + } + _archive = Builder( + name = "Archive", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + path( + fill = SolidColor(Color(0xFF9F9F9F)), + stroke = null, + strokeLineWidth = 0.0f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(9.75f, 15.25f) + arcToRelative(0.375f, 0.375f, 0.0f, false, true, 0.0f, -0.75f) + moveToRelative(0.0f, 0.75f) + arcToRelative(0.375f, 0.375f, 0.0f, false, false, 0.0f, -0.75f) + moveToRelative(0.0f, 5.25f) + arcToRelative(0.375f, 0.375f, 0.0f, false, true, 0.0f, -0.75f) + moveToRelative(0.0f, 0.75f) + arcToRelative(0.375f, 0.375f, 0.0f, false, false, 0.0f, -0.75f) + moveToRelative(0.0f, -8.25f) + arcToRelative(0.375f, 0.375f, 0.0f, true, true, 0.0f, -0.75f) + arcToRelative(0.375f, 0.375f, 0.0f, false, true, 0.0f, 0.75f) + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(9.75f, 15.25f) + arcToRelative(0.375f, 0.375f, 0.0f, true, true, 0.0f, -0.75f) + arcToRelative(0.375f, 0.375f, 0.0f, false, true, 0.0f, 0.75f) + close() + moveToRelative(0.0f, 4.5f) + arcToRelative(0.375f, 0.375f, 0.0f, true, true, 0.0f, -0.75f) + arcToRelative(0.375f, 0.375f, 0.0f, false, true, 0.0f, 0.75f) + close() + moveToRelative(0.0f, -9.0f) + arcToRelative(0.375f, 0.375f, 0.0f, true, true, 0.0f, -0.75f) + arcToRelative(0.375f, 0.375f, 0.0f, false, true, 0.0f, 0.75f) + close() + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(20.885f, 23.257f) + horizontalLineTo(3.115f) + arcToRelative(1.68f, 1.68f, 0.0f, false, true, -1.142f, -0.44f) + arcToRelative(1.45f, 1.45f, 0.0f, false, true, -0.473f, -1.06f) + verticalLineToRelative(-19.5f) + curveToRelative(0.0f, -0.398f, 0.17f, -0.78f, 0.473f, -1.061f) + arcToRelative(1.68f, 1.68f, 0.0f, false, true, 1.142f, -0.44f) + horizontalLineToRelative(14.678f) + curveToRelative(0.428f, 0.0f, 0.838f, 0.159f, 1.141f, 0.44f) + lineToRelative(3.093f, 2.872f) + curveTo(22.33f, 4.348f, 22.5f, 4.73f, 22.5f, 5.128f) + verticalLineToRelative(16.629f) + curveToRelative(0.0f, 0.397f, -0.17f, 0.779f, -0.473f, 1.06f) + arcToRelative(1.68f, 1.68f, 0.0f, false, true, -1.142f, 0.44f) + } + path( + fill = SolidColor(Color(0xFF9F9F9F)), + stroke = null, + strokeLineWidth = 0.0f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(11.726f, 4.807f) + arcToRelative(1.95f, 1.95f, 0.0f, false, true, -0.474f, 1.533f) + arcToRelative(2.04f, 2.04f, 0.0f, false, true, -3.0f, 0.0f) + arcToRelative(1.95f, 1.95f, 0.0f, false, true, -0.474f, -1.533f) + lineTo(8.25f, 1.0f) + horizontalLineToRelative(3.0f) + close() + } + }.build() + return _archive!! + } + +private var _archive: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Archive, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Audio.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Audio.kt new file mode 100644 index 000000000..f0dca06ed --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Audio.kt @@ -0,0 +1,115 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Audio: ImageVector + get() { + if (_audio != null) { + return _audio!! + } + _audio = Builder( + name = "Audio", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.5f, 21.757f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, 1.5f) + horizontalLineTo(3.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, -1.5f) + verticalLineToRelative(-19.5f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.5f, -1.5f) + horizontalLineToRelative(15.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.047f, 0.426f) + lineToRelative(3.0f, 2.883f) + arcTo(1.5f, 1.5f, 0.0f, false, true, 22.5f, 5.14f) + close() + } + path( + fill = SolidColor(Color(0xFF9F9F9F)), + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(5.0f, 16.708f) + curveToRelative(0.0f, 0.61f, 0.246f, 1.194f, 0.683f, 1.625f) + arcToRelative(2.35f, 2.35f, 0.0f, false, false, 1.65f, 0.674f) + curveToRelative(0.62f, 0.0f, 1.213f, -0.243f, 1.65f, -0.674f) + arcToRelative(2.28f, 2.28f, 0.0f, false, false, 0.684f, -1.625f) + curveToRelative(0.0f, -0.61f, -0.246f, -1.195f, -0.684f, -1.626f) + arcToRelative(2.35f, 2.35f, 0.0f, false, false, -1.65f, -0.673f) + curveToRelative(-0.619f, 0.0f, -1.212f, 0.242f, -1.65f, 0.673f) + arcTo(2.28f, 2.28f, 0.0f, false, false, 5.0f, 16.708f) + moveToRelative(9.333f, -2.758f) + curveToRelative(0.0f, 0.609f, 0.246f, 1.194f, 0.684f, 1.625f) + arcToRelative(2.35f, 2.35f, 0.0f, false, false, 1.65f, 0.673f) + curveToRelative(0.618f, 0.0f, 1.212f, -0.242f, 1.65f, -0.673f) + arcTo(2.28f, 2.28f, 0.0f, false, false, 19.0f, 13.949f) + curveToRelative(0.0f, -0.61f, -0.246f, -1.194f, -0.683f, -1.625f) + arcToRelative(2.35f, 2.35f, 0.0f, false, false, -1.65f, -0.674f) + curveToRelative(-0.62f, 0.0f, -1.213f, 0.242f, -1.65f, 0.674f) + arcToRelative(2.28f, 2.28f, 0.0f, false, false, -0.684f, 1.625f) + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(9.667f, 16.708f) + verticalLineToRelative(-8.33f) + curveToRelative(0.0f, -0.386f, 0.123f, -0.762f, 0.352f, -1.075f) + curveToRelative(0.23f, -0.313f, 0.553f, -0.548f, 0.925f, -0.67f) + lineToRelative(5.6f, -1.532f) + arcToRelative(1.9f, 1.9f, 0.0f, false, true, 1.68f, 0.253f) + curveToRelative(0.24f, 0.17f, 0.436f, 0.394f, 0.57f, 0.654f) + curveTo(18.93f, 6.267f, 19.0f, 6.554f, 19.0f, 6.845f) + verticalLineToRelative(7.104f) + } + } + }.build() + return _audio!! + } + +private var _audio: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Audio, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Calendar.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Calendar.kt new file mode 100644 index 000000000..3a9f25f97 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Calendar.kt @@ -0,0 +1,72 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Calendar: ImageVector + get() { + if (_calendar != null) { + return _calendar!! + } + _calendar = Builder( + name = "Calendar", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.044f, 2.913f) + horizontalLineTo(1.957f) + arcTo(0.957f, 0.957f, 0.0f, false, false, 1.0f, 3.87f) + verticalLineToRelative(18.174f) + curveTo(1.0f, 22.572f, 1.428f, 23.0f, 1.957f, 23.0f) + horizontalLineToRelative(20.087f) + arcTo(0.957f, 0.957f, 0.0f, false, false, 23.0f, 22.044f) + verticalLineTo(3.87f) + arcToRelative(0.956f, 0.956f, 0.0f, false, false, -0.956f, -0.957f) + moveTo(5.783f, 1.0f) + verticalLineToRelative(4.783f) + moveTo(18.217f, 1.0f) + verticalLineToRelative(4.783f) + moveTo(1.0f, 7.696f) + horizontalLineToRelative(22.0f) + } + } + }.build() + return _calendar!! + } + +private var _calendar: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Calendar, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Code.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Code.kt new file mode 100644 index 000000000..a55783d19 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Code.kt @@ -0,0 +1,84 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Code: ImageVector + get() { + if (_code != null) { + return _code!! + } + _code = Builder( + name = "Code", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.5f, 21.76f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, 1.5f) + horizontalLineTo(3.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, -1.5f) + verticalLineTo(2.26f) + arcTo(1.5f, 1.5f, 0.0f, false, true, 3.0f, 0.76f) + horizontalLineToRelative(15.045f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.048f, 0.427f) + lineToRelative(2.955f, 2.882f) + arcTo(1.5f, 1.5f, 0.0f, false, true, 22.5f, 5.143f) + close() + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(14.25f, 8.257f) + lineToRelative(3.75f, 3.75f) + lineToRelative(-3.75f, 3.75f) + moveToRelative(-4.5f, -7.5f) + lineTo(6.0f, 12.007f) + lineToRelative(3.75f, 3.75f) + } + } + }.build() + return _code!! + } + +private var _code: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Code, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Font.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Font.kt new file mode 100644 index 000000000..ac99ec535 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Font.kt @@ -0,0 +1,86 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Font: ImageVector + get() { + if (_font != null) { + return _font!! + } + _font = Builder( + name = "Font", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.5f, 21.757f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, 1.5f) + horizontalLineTo(3.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, -1.5f) + verticalLineToRelative(-19.5f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.5f, -1.5f) + horizontalLineToRelative(15.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.047f, 0.426f) + lineToRelative(3.0f, 2.883f) + arcTo(1.5f, 1.5f, 0.0f, false, true, 22.5f, 5.14f) + close() + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(8.0f, 9.007f) + verticalLineToRelative(-2.0f) + horizontalLineToRelative(8.0f) + verticalLineToRelative(2.0f) + moveToRelative(-4.0f, -2.0f) + verticalLineToRelative(10.0f) + moveToRelative(-2.0f, 0.0f) + horizontalLineToRelative(4.0f) + } + } + }.build() + return _font!! + } + +private var _font: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Font, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Image.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Image.kt new file mode 100644 index 000000000..c998f8fa5 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Image.kt @@ -0,0 +1,82 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Image: ImageVector + get() { + if (_image != null) { + return _image!! + } + _image = Builder( + name = "Image", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.5f, 21.757f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.503f, 1.5f) + horizontalLineTo(3.003f) + arcToRelative(1.505f, 1.505f, 0.0f, false, true, -1.503f, -1.5f) + verticalLineToRelative(-19.5f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.503f, -1.5f) + horizontalLineToRelative(15.033f) + curveToRelative(0.392f, 0.0f, 0.769f, 0.152f, 1.05f, 0.426f) + lineToRelative(2.961f, 2.883f) + arcTo(1.5f, 1.5f, 0.0f, false, true, 22.5f, 5.14f) + close() + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(18.77f, 18.482f) + lineToRelative(-3.925f, -5.888f) + arcToRelative(1.01f, 1.01f, 0.0f, false, false, -1.671f, -0.02f) + lineToRelative(-2.691f, 3.846f) + lineToRelative(-1.668f, -1.338f) + arcToRelative(1.01f, 1.01f, 0.0f, false, false, -1.474f, 0.229f) + lineTo(5.23f, 18.48f) + } + }.build() + return _image!! + } + +private var _image: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Image, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt index 3d39172b0..652617ea9 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt @@ -35,7 +35,7 @@ import com.infomaniak.library.filetypes.FileTypeIcons import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound -val FileTypeIcons.Pdf: ImageVector +internal val FileTypeIcons.Pdf: ImageVector get() { if (_pdf != null) { return _pdf!! diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Points.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Points.kt new file mode 100644 index 000000000..97ea1def0 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Points.kt @@ -0,0 +1,95 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.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.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Points: ImageVector + get() { + if (_points != null) { + return _points!! + } + _points = Builder( + name = "Points", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.5f, 21.757f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.503f, 1.5f) + horizontalLineTo(3.003f) + arcToRelative(1.505f, 1.505f, 0.0f, false, true, -1.503f, -1.5f) + verticalLineToRelative(-19.5f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.503f, -1.5f) + horizontalLineToRelative(15.033f) + curveToRelative(0.392f, 0.0f, 0.769f, 0.152f, 1.05f, 0.426f) + lineToRelative(2.961f, 2.883f) + arcTo(1.5f, 1.5f, 0.0f, false, true, 22.5f, 5.14f) + close() + } + path( + fill = SolidColor(Color(0xFF9F9F9F)), + stroke = null, + strokeLineWidth = 0.0f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(13.0f, 5.007f) + verticalLineToRelative(6.0f) + horizontalLineToRelative(6.0f) + arcToRelative(6.0f, 6.0f, 0.0f, false, false, -6.0f, -6.0f) + } + path( + fill = SolidColor(Color(0xFF9F9F9F)), + stroke = null, + strokeLineWidth = 0.0f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(11.0f, 7.007f) + arcToRelative(6.0f, 6.0f, 0.0f, true, false, 6.0f, 6.0f) + horizontalLineToRelative(-6.0f) + close() + } + }.build() + return _points!! + } + +private var _points: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Points, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Sheet.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Sheet.kt new file mode 100644 index 000000000..7f8e4b189 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Sheet.kt @@ -0,0 +1,93 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Sheet: ImageVector + get() { + if (_sheet != null) { + return _sheet!! + } + _sheet = Builder( + name = "Sheet", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.5f, 22.007f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.503f, 1.5f) + horizontalLineTo(3.003f) + arcToRelative(1.505f, 1.505f, 0.0f, false, true, -1.503f, -1.5f) + verticalLineToRelative(-19.5f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.503f, -1.5f) + horizontalLineToRelative(15.033f) + curveToRelative(0.392f, 0.0f, 0.769f, 0.153f, 1.05f, 0.426f) + lineToRelative(2.961f, 2.883f) + arcTo(1.5f, 1.5f, 0.0f, false, true, 22.5f, 5.39f) + close() + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(9.667f, 9.725f) + verticalLineToRelative(8.62f) + moveTo(5.0f, 14.034f) + horizontalLineToRelative(14.0f) + moveTo(5.0f, 9.725f) + horizontalLineToRelative(14.0f) + moveTo(5.519f, 5.67f) + horizontalLineToRelative(12.963f) + reflectiveCurveTo(19.0f, 5.67f, 19.0f, 6.177f) + verticalLineToRelative(11.661f) + reflectiveCurveToRelative(0.0f, 0.507f, -0.518f, 0.507f) + horizontalLineTo(5.519f) + reflectiveCurveTo(5.0f, 18.345f, 5.0f, 17.838f) + verticalLineTo(6.177f) + reflectiveCurveToRelative(0.0f, -0.508f, 0.519f, -0.508f) + } + } + }.build() + return _sheet!! + } + +private var _sheet: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Sheet, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt index 8bb13f189..7e4cfeea1 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt @@ -18,7 +18,7 @@ import com.infomaniak.library.filetypes.FileTypeIcons import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound -val FileTypeIcons.Text: ImageVector +internal val FileTypeIcons.Text: ImageVector get() { if (_text != null) { return _text!! diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Unknown.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Unknown.kt new file mode 100644 index 000000000..727f9b4c4 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Unknown.kt @@ -0,0 +1,68 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Unknown: ImageVector + get() { + if (_unknown != null) { + return _unknown!! + } + _unknown = Builder( + name = "Unknown", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.5f, 21.757f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.503f, 1.5f) + horizontalLineTo(3.003f) + arcToRelative(1.505f, 1.505f, 0.0f, false, true, -1.503f, -1.5f) + verticalLineToRelative(-19.5f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.503f, -1.5f) + horizontalLineToRelative(15.033f) + curveToRelative(0.392f, 0.0f, 0.769f, 0.152f, 1.05f, 0.426f) + lineToRelative(2.961f, 2.883f) + arcTo(1.5f, 1.5f, 0.0f, false, true, 22.5f, 5.14f) + close() + } + } + }.build() + return _unknown!! + } + +private var _unknown: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Unknown, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Vcard.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Vcard.kt new file mode 100644 index 000000000..2e866b56e --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Vcard.kt @@ -0,0 +1,82 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Vcard: ImageVector + get() { + if (_vcard != null) { + return _vcard!! + } + _vcard = Builder( + name = "Vcard", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.0f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(20.0f, 0.5f) + horizontalLineTo(4.5f) + arcTo(1.5f, 1.5f, 0.0f, false, false, 3.0f, 2.0f) + moveToRelative(0.0f, 0.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, false, 1.5f, 1.5f) + horizontalLineToRelative(16.0f) + arcTo(0.5f, 0.5f, 0.0f, false, true, 21.0f, 4.0f) + verticalLineToRelative(19.0f) + arcToRelative(0.5f, 0.5f, 0.0f, false, true, -0.5f, 0.5f) + horizontalLineTo(5.0f) + arcToRelative(2.0f, 2.0f, 0.0f, false, true, -2.0f, -2.0f) + close() + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.0f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(17.5f, 19.5f) + arcToRelative(5.0f, 5.0f, 0.0f, true, false, -10.0f, 0.0f) + close() + moveToRelative(-5.0f, -6.5f) + arcToRelative(3.0f, 3.0f, 0.0f, true, false, 0.0f, -6.0f) + arcToRelative(3.0f, 3.0f, 0.0f, false, false, 0.0f, 6.0f) + } + }.build() + return _vcard!! + } + +private var _vcard: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Vcard, contentDescription = null) + } +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Video.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Video.kt new file mode 100644 index 000000000..4ede33399 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Video.kt @@ -0,0 +1,84 @@ +package com.infomaniak.library.filetypes.icons + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +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.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.library.filetypes.FileTypeIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +internal val FileTypeIcons.Video: ImageVector + get() { + if (_video != null) { + return _video!! + } + _video = Builder( + name = "Video", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(22.5f, 21.757f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, 1.5f) + horizontalLineTo(3.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, -1.5f) + verticalLineToRelative(-19.5f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.5f, -1.5f) + horizontalLineToRelative(15.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.047f, 0.426f) + lineToRelative(3.0f, 2.883f) + arcTo(1.5f, 1.5f, 0.0f, false, true, 22.5f, 5.14f) + close() + } + path( + fill = SolidColor(Color(0xFF9F9F9F)), + stroke = null, + strokeLineWidth = 0.0f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(9.488f, 15.667f) + arcTo(0.856f, 0.856f, 0.0f, false, true, 8.25f, 14.9f) + verticalLineTo(9.113f) + arcToRelative(0.856f, 0.856f, 0.0f, false, true, 1.238f, -0.766f) + lineToRelative(5.789f, 2.895f) + arcToRelative(0.855f, 0.855f, 0.0f, false, true, 0.0f, 1.53f) + close() + } + }.build() + return _video!! + } + +private var _video: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box(modifier = Modifier.padding(12.dp)) { + Image(imageVector = FileTypeIcons.Video, contentDescription = null) + } +} diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4d5530c5a..ebfdd94d8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -90,6 +90,7 @@ dependencies { // Compose preview tools implementation(libs.compose.ui.tooling.preview) + implementation(project(":FileTypes")) debugImplementation(libs.compose.ui.tooling) // Hilt diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt index 15df85886..353733d75 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt @@ -17,7 +17,9 @@ */ package com.infomaniak.swisstransfer.ui.components +import android.net.Uri import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Canvas import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape @@ -31,11 +33,14 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.core.net.toUri import coil.compose.AsyncImage import coil.request.ImageRequest +import com.infomaniak.library.filetypes.FileType import com.infomaniak.swisstransfer.R import com.infomaniak.swisstransfer.ui.images.AppImages import com.infomaniak.swisstransfer.ui.images.icons.CrossThick +import com.infomaniak.swisstransfer.ui.theme.LocalIsDarkMode import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.Shapes import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme @@ -45,6 +50,7 @@ import com.infomaniak.swisstransfer.ui.utils.PreviewSmallWindow @Composable fun ImageTile( + uri: Uri, title: String, description: String, isRemoveButtonVisible: Boolean, @@ -53,12 +59,85 @@ fun ImageTile( onClick: () -> Unit, onRemove: (() -> Unit)? = null, onCheckedChange: ((Boolean) -> Unit)? = null, +) { + ImageTileContent( + data = { + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(uri) + .crossfade(true) + .build(), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize(), + ) + }, + onClick = onClick, + isCheckboxVisible = isCheckboxVisible, + isChecked = isChecked, + onCheckedChange = onCheckedChange, + isRemoveButtonVisible = isRemoveButtonVisible, + onRemove = onRemove, + title = title, + description = description + ) +} + + +@Composable +fun ImageTile( + fileType: FileType, + title: String, + description: String, + isRemoveButtonVisible: Boolean, + isCheckboxVisible: Boolean, + isChecked: () -> Boolean = { false }, + onClick: () -> Unit, + onRemove: (() -> Unit)? = null, + onCheckedChange: ((Boolean) -> Unit)? = null, +) { + ImageTileContent( + data = { + Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) { + val surfaceColor = SwissTransferTheme.materialColors.surface + Canvas(modifier = Modifier.size(64.dp)) { + drawCircle(color = surfaceColor) + } + + Icon( + modifier = Modifier.size(32.dp), + imageVector = fileType.icon, + contentDescription = null, + tint = fileType.color(LocalIsDarkMode.current) + ) + } + }, + onClick = onClick, + isCheckboxVisible = isCheckboxVisible, + isChecked = isChecked, + onCheckedChange = onCheckedChange, + isRemoveButtonVisible = isRemoveButtonVisible, + onRemove = onRemove, + title = title, + description = description + ) +} + +@Composable +private fun ImageTileContent( + data: @Composable () -> Unit, + onClick: () -> Unit, + isCheckboxVisible: Boolean, + isChecked: () -> Boolean, + onCheckedChange: ((Boolean) -> Unit)?, + isRemoveButtonVisible: Boolean, + onRemove: (() -> Unit)?, + title: String, + description: String ) { Card( onClick = onClick, - modifier = Modifier - .fillMaxSize() - .aspectRatio(164 / 152f), + modifier = Modifier.aspectRatio(164 / 152f), colors = CardDefaults.cardColors(containerColor = SwissTransferTheme.materialColors.background), shape = Shapes.small, border = BorderStroke(width = 1.dp, SwissTransferTheme.materialColors.outlineVariant) @@ -69,15 +148,7 @@ fun ImageTile( .fillMaxWidth() .background(SwissTransferTheme.materialColors.surfaceContainerHighest) ) { - AsyncImage( - model = ImageRequest.Builder(LocalContext.current) - .data("https://fastly.picsum.photos/id/1/200/300.jpg?hmac=jH5bDkLr6Tgy3oAg5khKCHeunZMHq0ehBZr6vGifPLY") - .crossfade(true) - .build(), - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize(), - ) + data() if (isCheckboxVisible) { Checkbox( @@ -138,11 +209,26 @@ private fun ImageTilePreview() { Column( modifier = Modifier .padding(24.dp) - .size(164.dp) + .width(164.dp) ) { var isChecked by remember { mutableStateOf(true) } + + ImageTile( + fileType = FileType.PDF, + title = "How to not get fired.pdf", + description = "1.4 Mo", + isRemoveButtonVisible = true, + isCheckboxVisible = true, + isChecked = { isChecked }, + onClick = { isChecked = !isChecked }, + onRemove = {}, + ) + + Spacer(modifier = Modifier.height(16.dp)) + ImageTile( + uri = "https://fastly.picsum.photos/id/1/200/300.jpg?hmac=jH5bDkLr6Tgy3oAg5khKCHeunZMHq0ehBZr6vGifPLY".toUri(), title = "Time-Clock-Circle--Streamline-Ultimate.svg (1).svg", description = "1.4 Mo", isRemoveButtonVisible = true, 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 dd5a2ac08..cfb74a1bb 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 @@ -25,6 +25,7 @@ import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import androidx.core.net.toUri import com.infomaniak.swisstransfer.ui.components.ImageTile import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme @@ -40,7 +41,15 @@ fun SentListScreen(transfers: List) { horizontalArrangement = Arrangement.spacedBy(Margin.Medium), ) { items(3) { - ImageTile("Time-Clock-Circle--Streamline-Ultimate.svg (1).svg", "1.4 MB", true, true, { true }, {}, {}) + ImageTile( + uri = "https://fastly.picsum.photos/id/1/200/300.jpg?hmac=jH5bDkLr6Tgy3oAg5khKCHeunZMHq0ehBZr6vGifPLY".toUri(), + title = "Time-Clock-Circle--Streamline-Ultimate.svg (1).svg", + description = "1.4 MB", + isRemoveButtonVisible = true, + isCheckboxVisible = true, + isChecked = { true }, + onClick = {}, + onRemove = {}) } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3d7cfde5e..9c3eef4da 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,6 +19,7 @@ swisstransfer = "0.1.1" uiAndroid = "1.7.2" foundationAndroid = "1.7.3" uiToolingPreviewAndroid = "1.7.3" +uiTooling = "1.7.3" [libraries] androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } @@ -49,6 +50,7 @@ junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-ui-android = { group = "androidx.compose.ui", name = "ui-android", version.ref = "uiAndroid" } androidx-foundation-android = { group = "androidx.compose.foundation", name = "foundation-android", version.ref = "foundationAndroid" } androidx-ui-tooling-preview-android = { group = "androidx.compose.ui", name = "ui-tooling-preview-android", version.ref = "uiToolingPreviewAndroid" } +androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "uiTooling" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } From c7a55eae16df6e9fa3c568ddab338eccc42a8712 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Mon, 7 Oct 2024 14:45:06 +0200 Subject: [PATCH 05/15] Rearrange ImageTile to adapt better to its usage --- .../infomaniak/library/filetypes/FileType.kt | 26 ++++++------ .../swisstransfer/ui/components/ImageTile.kt | 42 +++++++++++-------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt index 5b32f608f..e6c5a5eff 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt @@ -45,17 +45,19 @@ enum class FileType(val icon: ImageVector, private val colorLight: Color, privat return if (isDark) colorDark else colorLight } - fun guessFromFileName(fileName: String): FileType { - val extension = fileName.extractExtension() - val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: return FileType.UNKNOWN - return FileTypeGuesser.getFileTypeFromMimeType(mimeType) - } - - private fun String.extractExtension(): String? { - val fileName = lastIndexOf('/').takeIf { it != -1 }?.let { fileNameStart -> - substring(fileNameStart + 1) - } ?: this - - return fileName.substringAfterLast(".").takeIf { it.isNotEmpty() } + companion object { + fun guessFromFileName(fileName: String): FileType { + val extension = fileName.extractExtension() + val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: return FileType.UNKNOWN + return FileTypeGuesser.getFileTypeFromMimeType(mimeType) + } + + private fun String.extractExtension(): String? { + val fileName = lastIndexOf('/').takeIf { it != -1 }?.let { fileNameStart -> + substring(fileNameStart + 1) + } ?: this + + return fileName.substringAfterLast(".").takeIf { it.isNotEmpty() } + } } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt index 353733d75..278638ac5 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt @@ -61,7 +61,7 @@ fun ImageTile( onCheckedChange: ((Boolean) -> Unit)? = null, ) { ImageTileContent( - data = { + content = { AsyncImage( model = ImageRequest.Builder(LocalContext.current) .data(uri) @@ -69,6 +69,9 @@ fun ImageTile( .build(), contentDescription = null, contentScale = ContentScale.Crop, + onError = { + FileIcon(FileType.IMAGE) + }, modifier = Modifier.fillMaxSize(), ) }, @@ -97,21 +100,7 @@ fun ImageTile( onCheckedChange: ((Boolean) -> Unit)? = null, ) { ImageTileContent( - data = { - Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) { - val surfaceColor = SwissTransferTheme.materialColors.surface - Canvas(modifier = Modifier.size(64.dp)) { - drawCircle(color = surfaceColor) - } - - Icon( - modifier = Modifier.size(32.dp), - imageVector = fileType.icon, - contentDescription = null, - tint = fileType.color(LocalIsDarkMode.current) - ) - } - }, + content = { FileIcon(fileType) }, onClick = onClick, isCheckboxVisible = isCheckboxVisible, isChecked = isChecked, @@ -125,7 +114,7 @@ fun ImageTile( @Composable private fun ImageTileContent( - data: @Composable () -> Unit, + content: @Composable () -> Unit, onClick: () -> Unit, isCheckboxVisible: Boolean, isChecked: () -> Boolean, @@ -148,7 +137,7 @@ private fun ImageTileContent( .fillMaxWidth() .background(SwissTransferTheme.materialColors.surfaceContainerHighest) ) { - data() + content() if (isCheckboxVisible) { Checkbox( @@ -200,6 +189,23 @@ private fun ImageTileContent( } } +@Composable +private fun FileIcon(fileType: FileType) { + Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) { + val surfaceColor = SwissTransferTheme.materialColors.surface + Canvas(modifier = Modifier.size(64.dp)) { + drawCircle(color = surfaceColor) + } + + Icon( + modifier = Modifier.size(32.dp), + imageVector = fileType.icon, + contentDescription = null, + tint = fileType.color(LocalIsDarkMode.current) + ) + } +} + @PreviewSmallWindow @PreviewLargeWindow @Composable From 3d79b4daff750a5444d73fd551e73c190abc9e6f Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Tue, 8 Oct 2024 11:35:51 +0200 Subject: [PATCH 06/15] Make ImageTile take in a FileUiItem directly for separation of concerns --- .../infomaniak/library/filetypes/FileType.kt | 8 +- .../library/filetypes/FileTypeGuesser.kt | 2 +- .../swisstransfer/ui/components/ImageTile.kt | 102 +++++++++--------- .../ui/screen/main/sent/SentListScreen.kt | 14 ++- .../swisstransfer/ui/utils/FileUiItemExt.kt | 24 +++++ 5 files changed, 95 insertions(+), 55 deletions(-) create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/utils/FileUiItemExt.kt diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt index e6c5a5eff..295d70cd0 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt @@ -17,10 +17,12 @@ */ package com.infomaniak.library.filetypes +import android.util.Log import android.webkit.MimeTypeMap import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import com.infomaniak.library.filetypes.icons.* +import org.jetbrains.annotations.TestOnly private val MEDIA_COLOR_LIGHT = Color(0xFF00BCD4) private val MEDIA_COLOR_DARK = Color(0xFF86DEEA) @@ -48,7 +50,11 @@ enum class FileType(val icon: ImageVector, private val colorLight: Color, privat companion object { fun guessFromFileName(fileName: String): FileType { val extension = fileName.extractExtension() - val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: return FileType.UNKNOWN + val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: return UNKNOWN + return guessFromMimeType(mimeType) + } + + fun guessFromMimeType(mimeType: String): FileType { return FileTypeGuesser.getFileTypeFromMimeType(mimeType) } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt index 897fbbd55..1d188c3cd 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt @@ -17,7 +17,7 @@ */ package com.infomaniak.library.filetypes -object FileTypeGuesser { +internal object FileTypeGuesser { private val pdfMatches = mimeTypeSetOf( "application/pdf", "application/acrobat", diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt index 278638ac5..90e1100b1 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt @@ -18,6 +18,7 @@ package com.infomaniak.swisstransfer.ui.components import android.net.Uri +import android.text.format.Formatter import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Canvas import androidx.compose.foundation.background @@ -25,6 +26,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -46,13 +48,21 @@ import com.infomaniak.swisstransfer.ui.theme.Shapes import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewLargeWindow import com.infomaniak.swisstransfer.ui.utils.PreviewSmallWindow +import com.infomaniak.swisstransfer.ui.utils.fileType +import com.infomaniak.swisstransfer.ui.utils.hasPreview +// TODO: Get the interface from the shared kmp code +interface FileUiItem { + val uid: String + val fileName: String + val fileSizeInBytes: Long + val mimeType: String? + val uri: String +} @Composable fun ImageTile( - uri: Uri, - title: String, - description: String, + file: FileUiItem, isRemoveButtonVisible: Boolean, isCheckboxVisible: Boolean, isChecked: () -> Boolean = { false }, @@ -62,53 +72,22 @@ fun ImageTile( ) { ImageTileContent( content = { - AsyncImage( - model = ImageRequest.Builder(LocalContext.current) - .data(uri) - .crossfade(true) - .build(), - contentDescription = null, - contentScale = ContentScale.Crop, - onError = { - FileIcon(FileType.IMAGE) - }, - modifier = Modifier.fillMaxSize(), - ) - }, - onClick = onClick, - isCheckboxVisible = isCheckboxVisible, - isChecked = isChecked, - onCheckedChange = onCheckedChange, - isRemoveButtonVisible = isRemoveButtonVisible, - onRemove = onRemove, - title = title, - description = description - ) -} - + var displayPreview by rememberSaveable { mutableStateOf(file.hasPreview) } -@Composable -fun ImageTile( - fileType: FileType, - title: String, - description: String, - isRemoveButtonVisible: Boolean, - isCheckboxVisible: Boolean, - isChecked: () -> Boolean = { false }, - onClick: () -> Unit, - onRemove: (() -> Unit)? = null, - onCheckedChange: ((Boolean) -> Unit)? = null, -) { - ImageTileContent( - content = { FileIcon(fileType) }, + if (displayPreview) { + FileImage(file.uri.toUri()) { displayPreview = false } + } else { + FileIcon(file.fileType) + } + }, onClick = onClick, isCheckboxVisible = isCheckboxVisible, isChecked = isChecked, onCheckedChange = onCheckedChange, isRemoveButtonVisible = isRemoveButtonVisible, onRemove = onRemove, - title = title, - description = description + title = file.fileName, + description = Formatter.formatShortFileSize(LocalContext.current, file.fileSizeInBytes), ) } @@ -189,6 +168,20 @@ private fun ImageTileContent( } } +@Composable +private fun FileImage(uri: Uri, onError: () -> Unit) { + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(uri) + .crossfade(true) + .build(), + contentDescription = null, + contentScale = ContentScale.Crop, + onError = { onError() }, + modifier = Modifier.fillMaxSize(), + ) +} + @Composable private fun FileIcon(fileType: FileType) { Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) { @@ -220,10 +213,16 @@ private fun ImageTilePreview() { { var isChecked by remember { mutableStateOf(true) } + + val iconFile = object : FileUiItem { + override val fileName: String = "How to not get fired.pdf" + override val uid: String = fileName + override val fileSizeInBytes: Long = 10302130 + override val mimeType: String? = null + override val uri: String = "" + } ImageTile( - fileType = FileType.PDF, - title = "How to not get fired.pdf", - description = "1.4 Mo", + iconFile, isRemoveButtonVisible = true, isCheckboxVisible = true, isChecked = { isChecked }, @@ -233,10 +232,15 @@ private fun ImageTilePreview() { Spacer(modifier = Modifier.height(16.dp)) + val imageFile = object : FileUiItem { + override val fileName: String = "Time-Clock-Circle--Streamline-Ultimate.svg (1).png" + override val uid: String = fileName + override val fileSizeInBytes: Long = 456782 + override val mimeType: String? = null + override val uri: String = "https://picsum.photos/200/300" + } ImageTile( - uri = "https://fastly.picsum.photos/id/1/200/300.jpg?hmac=jH5bDkLr6Tgy3oAg5khKCHeunZMHq0ehBZr6vGifPLY".toUri(), - title = "Time-Clock-Circle--Streamline-Ultimate.svg (1).svg", - description = "1.4 Mo", + file = imageFile, isRemoveButtonVisible = true, isCheckboxVisible = true, isChecked = { isChecked }, 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 cfb74a1bb..df7ca5f53 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 @@ -25,7 +25,7 @@ import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import androidx.core.net.toUri +import com.infomaniak.swisstransfer.ui.components.FileUiItem import com.infomaniak.swisstransfer.ui.components.ImageTile import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme @@ -40,11 +40,17 @@ fun SentListScreen(transfers: List) { verticalArrangement = Arrangement.spacedBy(Margin.Medium), horizontalArrangement = Arrangement.spacedBy(Margin.Medium), ) { + val imageFile = object : FileUiItem { + override val fileName: String = "Time-Clock-Circle--Streamline-Ultimate.svg (1).png" + override val uid: String = fileName + override val fileSizeInBytes: Long = 456782 + override val mimeType: String? = null + override val uri: String = "httttttps://picsum.photos/200/300" + } + items(3) { ImageTile( - uri = "https://fastly.picsum.photos/id/1/200/300.jpg?hmac=jH5bDkLr6Tgy3oAg5khKCHeunZMHq0ehBZr6vGifPLY".toUri(), - title = "Time-Clock-Circle--Streamline-Ultimate.svg (1).svg", - description = "1.4 MB", + file = imageFile, isRemoveButtonVisible = true, isCheckboxVisible = true, isChecked = { true }, diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/FileUiItemExt.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/FileUiItemExt.kt new file mode 100644 index 000000000..82c06ff86 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/FileUiItemExt.kt @@ -0,0 +1,24 @@ +/* + * 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.utils + +import com.infomaniak.library.filetypes.FileType +import com.infomaniak.swisstransfer.ui.components.FileUiItem + +val FileUiItem.fileType: FileType get() = mimeType?.let { FileType.guessFromMimeType(it) } ?: FileType.guessFromFileName(fileName) +val FileUiItem.hasPreview: Boolean get() = fileType == FileType.IMAGE From 79075aedfbd1f27512ab60ee38deccc5a82c199e Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 9 Oct 2024 14:26:47 +0200 Subject: [PATCH 07/15] Rename ImageTile into FileTile --- .../ui/components/{ImageTile.kt => FileTile.kt} | 14 +++++++------- .../ui/screen/main/sent/SentListScreen.kt | 4 ++-- .../infomaniak/swisstransfer/ui/theme/ColorDark.kt | 2 +- .../swisstransfer/ui/theme/ColorLight.kt | 2 +- .../com/infomaniak/swisstransfer/ui/theme/Theme.kt | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) rename app/src/main/java/com/infomaniak/swisstransfer/ui/components/{ImageTile.kt => FileTile.kt} (97%) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt similarity index 97% rename from app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt rename to app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt index 90e1100b1..76b93833c 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/ImageTile.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt @@ -61,7 +61,7 @@ interface FileUiItem { } @Composable -fun ImageTile( +fun FileTile( file: FileUiItem, isRemoveButtonVisible: Boolean, isCheckboxVisible: Boolean, @@ -70,7 +70,7 @@ fun ImageTile( onRemove: (() -> Unit)? = null, onCheckedChange: ((Boolean) -> Unit)? = null, ) { - ImageTileContent( + FileTileContent( content = { var displayPreview by rememberSaveable { mutableStateOf(file.hasPreview) } @@ -92,7 +92,7 @@ fun ImageTile( } @Composable -private fun ImageTileContent( +private fun FileTileContent( content: @Composable () -> Unit, onClick: () -> Unit, isCheckboxVisible: Boolean, @@ -136,7 +136,7 @@ private fun ImageTileContent( .align(Alignment.TopEnd), contentPadding = PaddingValues(0.dp), shape = CircleShape, - colors = ButtonDefaults.buttonColors(containerColor = SwissTransferTheme.colors.imageTileRemoveButtonBackground), + colors = ButtonDefaults.buttonColors(containerColor = SwissTransferTheme.colors.fileTileRemoveButtonBackground), onClick = onRemove ?: {}, ) { Icon( @@ -202,7 +202,7 @@ private fun FileIcon(fileType: FileType) { @PreviewSmallWindow @PreviewLargeWindow @Composable -private fun ImageTilePreview() { +private fun FileTilePreview() { SwissTransferTheme { Surface { Column( @@ -221,7 +221,7 @@ private fun ImageTilePreview() { override val mimeType: String? = null override val uri: String = "" } - ImageTile( + FileTile( iconFile, isRemoveButtonVisible = true, isCheckboxVisible = true, @@ -239,7 +239,7 @@ private fun ImageTilePreview() { override val mimeType: String? = null override val uri: String = "https://picsum.photos/200/300" } - ImageTile( + FileTile( file = imageFile, isRemoveButtonVisible = true, isCheckboxVisible = true, 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 df7ca5f53..33a7c7c1c 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 @@ -26,7 +26,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.infomaniak.swisstransfer.ui.components.FileUiItem -import com.infomaniak.swisstransfer.ui.components.ImageTile +import com.infomaniak.swisstransfer.ui.components.FileTile import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewLargeWindow @@ -49,7 +49,7 @@ fun SentListScreen(transfers: List) { } items(3) { - ImageTile( + FileTile( file = imageFile, isRemoveButtonVisible = true, isCheckboxVisible = true, 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 7981da945..67a87f4c9 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 @@ -75,7 +75,7 @@ val CustomDarkColorScheme = CustomColorScheme( navigationItemBackground = Color(dark2), tertiaryButtonBackground = Color(dark2), selectedSettingItem = Color(dark2), - imageTileRemoveButtonBackground = Color(black_translucent), + fileTileRemoveButtonBackground = Color(black_translucent), transferTypeLinkContainer = Color(specific1), transferTypeLinkOnContainer = Color(green_main), transferTypeEmailContainer = 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 295239837..1a888a5a3 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 @@ -76,7 +76,7 @@ val CustomLightColorScheme = CustomColorScheme( navigationItemBackground = LightColorScheme.background, tertiaryButtonBackground = Color(rabbit), selectedSettingItem = Color(rabbit), - imageTileRemoveButtonBackground = Color(black_translucent), + fileTileRemoveButtonBackground = Color(black_translucent), transferTypeLinkContainer = Color(specific1), transferTypeLinkOnContainer = Color(green_main), transferTypeEmailContainer = Color(specific2), 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 5f78ef9d7..27fce6db1 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 @@ -75,7 +75,7 @@ data class CustomColorScheme( val navigationItemBackground: Color = Color.Unspecified, val tertiaryButtonBackground: Color = Color.Unspecified, val selectedSettingItem: Color = Color.Unspecified, - val imageTileRemoveButtonBackground: Color = Color.Unspecified, + val fileTileRemoveButtonBackground: Color = Color.Unspecified, val transferTypeLinkContainer: Color = Color.Unspecified, val transferTypeLinkOnContainer: Color = Color.Unspecified, val transferTypeEmailContainer: Color = Color.Unspecified, From 943948423302f436d82bdd2aacdca0986ec5d231 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 9 Oct 2024 14:54:10 +0200 Subject: [PATCH 08/15] Rename FileImage into FileThumbnail --- .../com/infomaniak/swisstransfer/ui/components/FileTile.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt index 76b93833c..46a9845cd 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt @@ -75,7 +75,7 @@ fun FileTile( var displayPreview by rememberSaveable { mutableStateOf(file.hasPreview) } if (displayPreview) { - FileImage(file.uri.toUri()) { displayPreview = false } + FileThumbnail(file.uri.toUri()) { displayPreview = false } } else { FileIcon(file.fileType) } @@ -169,7 +169,7 @@ private fun FileTileContent( } @Composable -private fun FileImage(uri: Uri, onError: () -> Unit) { +private fun FileThumbnail(uri: Uri, onError: () -> Unit) { AsyncImage( model = ImageRequest.Builder(LocalContext.current) .data(uri) From eb331a4dc34c0d6b7ad8b92b9f7c2f33431307d6 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 9 Oct 2024 15:32:26 +0200 Subject: [PATCH 09/15] Clean code --- FileTypes/build.gradle.kts | 3 --- FileTypes/src/main/AndroidManifest.xml | 4 ---- app/src/main/AndroidManifest.xml | 1 - .../swisstransfer/ui/screen/main/sent/SentListScreen.kt | 2 +- .../infomaniak/swisstransfer/ui/utils/FileUiItemExt.kt | 1 + gradle/libs.versions.toml | 8 +++++++- 6 files changed, 9 insertions(+), 10 deletions(-) delete mode 100644 FileTypes/src/main/AndroidManifest.xml diff --git a/FileTypes/build.gradle.kts b/FileTypes/build.gradle.kts index 04f540227..a5e855d04 100644 --- a/FileTypes/build.gradle.kts +++ b/FileTypes/build.gradle.kts @@ -42,10 +42,7 @@ dependencies { implementation(libs.androidx.ui.android) implementation(libs.androidx.foundation.android) implementation(libs.androidx.ui.tooling.preview.android) - // implementation(libs.androidx.appcompat) - // implementation(libs.material) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) debugImplementation(libs.androidx.ui.tooling) - // androidTestImplementation(libs.androidx.espresso.core) } diff --git a/FileTypes/src/main/AndroidManifest.xml b/FileTypes/src/main/AndroidManifest.xml deleted file mode 100644 index 8bdb7e14b..000000000 --- a/FileTypes/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 986f30184..9173a6796 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,7 +20,6 @@ xmlns:tools="http://schemas.android.com/tools"> - ) { override val uid: String = fileName override val fileSizeInBytes: Long = 456782 override val mimeType: String? = null - override val uri: String = "httttttps://picsum.photos/200/300" + override val uri: String = "https://picsum.photos/200/300" } items(3) { diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/FileUiItemExt.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/FileUiItemExt.kt index 82c06ff86..e78f6ccb3 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/FileUiItemExt.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/FileUiItemExt.kt @@ -21,4 +21,5 @@ import com.infomaniak.library.filetypes.FileType import com.infomaniak.swisstransfer.ui.components.FileUiItem val FileUiItem.fileType: FileType get() = mimeType?.let { FileType.guessFromMimeType(it) } ?: FileType.guessFromFileName(fileName) + val FileUiItem.hasPreview: Boolean get() = fileType == FileType.IMAGE diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9c3eef4da..dde5b1b30 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,9 @@ lifecycleRuntimeKtx = "2.8.6" navigation = "2.8.1" serialization = "1.7.1" swisstransfer = "0.1.1" -uiAndroid = "1.7.2" + +# FileType module +uiAndroid = "1.7.3" foundationAndroid = "1.7.3" uiToolingPreviewAndroid = "1.7.3" uiTooling = "1.7.3" @@ -47,6 +49,8 @@ swisstransfer-core = { module = "com.github.Infomaniak.multiplatform-SwissTransf # Tests androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } junit = { group = "junit", name = "junit", version.ref = "junit" } + +# FileType module androidx-ui-android = { group = "androidx.compose.ui", name = "ui-android", version.ref = "uiAndroid" } androidx-foundation-android = { group = "androidx.compose.foundation", name = "foundation-android", version.ref = "foundationAndroid" } androidx-ui-tooling-preview-android = { group = "androidx.compose.ui", name = "ui-tooling-preview-android", version.ref = "uiToolingPreviewAndroid" } @@ -58,4 +62,6 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = " hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } + +# FileType module android-library = { id = "com.android.library", version.ref = "agp" } From 5a3b305e5971872447db02673f6cb364a1091172 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 9 Oct 2024 15:40:58 +0200 Subject: [PATCH 10/15] Remove onCheckedChange --- .../com/infomaniak/swisstransfer/ui/components/FileTile.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt index 46a9845cd..8d2917194 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt @@ -68,7 +68,6 @@ fun FileTile( isChecked: () -> Boolean = { false }, onClick: () -> Unit, onRemove: (() -> Unit)? = null, - onCheckedChange: ((Boolean) -> Unit)? = null, ) { FileTileContent( content = { @@ -83,7 +82,6 @@ fun FileTile( onClick = onClick, isCheckboxVisible = isCheckboxVisible, isChecked = isChecked, - onCheckedChange = onCheckedChange, isRemoveButtonVisible = isRemoveButtonVisible, onRemove = onRemove, title = file.fileName, @@ -97,7 +95,6 @@ private fun FileTileContent( onClick: () -> Unit, isCheckboxVisible: Boolean, isChecked: () -> Boolean, - onCheckedChange: ((Boolean) -> Unit)?, isRemoveButtonVisible: Boolean, onRemove: (() -> Unit)?, title: String, @@ -121,7 +118,7 @@ private fun FileTileContent( if (isCheckboxVisible) { Checkbox( checked = isChecked(), - onCheckedChange = onCheckedChange, + onCheckedChange = null, Modifier .align(Alignment.TopStart) .padding(12.dp), From b990ddc8e4b1fe095f0c4416dd2e7497d1f5f2a5 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Thu, 10 Oct 2024 13:27:09 +0200 Subject: [PATCH 11/15] Add name to onError lambda --- .../java/com/infomaniak/swisstransfer/ui/components/FileTile.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt index 8d2917194..45a8c053f 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt @@ -74,7 +74,7 @@ fun FileTile( var displayPreview by rememberSaveable { mutableStateOf(file.hasPreview) } if (displayPreview) { - FileThumbnail(file.uri.toUri()) { displayPreview = false } + FileThumbnail(file.uri.toUri(), onError = { displayPreview = false }) } else { FileIcon(file.fileType) } From 0634c6ef18a33addf0f8e2599151268e677e141d Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 16 Oct 2024 09:14:34 +0200 Subject: [PATCH 12/15] Add filetype icon preview const --- .../java/com/infomaniak/library/filetypes/FileTypeIcons.kt | 6 +++++- .../java/com/infomaniak/library/filetypes/icons/Archive.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Audio.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Calendar.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Code.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Font.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Image.kt | 3 ++- .../main/java/com/infomaniak/library/filetypes/icons/Pdf.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Points.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Sheet.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Text.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Unknown.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Vcard.kt | 3 ++- .../java/com/infomaniak/library/filetypes/icons/Video.kt | 3 ++- 14 files changed, 31 insertions(+), 14 deletions(-) diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt index 6ae6b66ee..ebf7f20fe 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.kt @@ -17,4 +17,8 @@ */ package com.infomaniak.library.filetypes -internal object FileTypeIcons +import androidx.compose.ui.unit.dp + +internal object FileTypeIcons { + val previewSize = 250.dp +} diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Archive.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Archive.kt index 245c91c72..2f87455d6 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Archive.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Archive.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -124,7 +125,7 @@ private var _archive: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Archive, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Audio.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Audio.kt index f0dca06ed..cbbcdbf59 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Audio.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Audio.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -109,7 +110,7 @@ private var _audio: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Audio, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Calendar.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Calendar.kt index 3a9f25f97..844b58a83 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Calendar.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Calendar.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -66,7 +67,7 @@ private var _calendar: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Calendar, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Code.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Code.kt index a55783d19..89eccb4a4 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Code.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Code.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -78,7 +79,7 @@ private var _code: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Code, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Font.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Font.kt index ac99ec535..0f64d92d1 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Font.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Font.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -80,7 +81,7 @@ private var _font: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Font, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Image.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Image.kt index c998f8fa5..0b9a41cd7 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Image.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Image.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -76,7 +77,7 @@ private var _image: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Image, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt index 652617ea9..a034d0b1d 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -96,7 +97,7 @@ private var _pdf: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Pdf, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Points.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Points.kt index 97ea1def0..9678be13b 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Points.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Points.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -89,7 +90,7 @@ private var _points: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Points, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Sheet.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Sheet.kt index 7f8e4b189..1dd5d72da 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Sheet.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Sheet.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -87,7 +88,7 @@ private var _sheet: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Sheet, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt index 7e4cfeea1..0978b5b26 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -68,7 +69,7 @@ private var _text: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Text, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Unknown.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Unknown.kt index 727f9b4c4..3b426ed4d 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Unknown.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Unknown.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -62,7 +63,7 @@ private var _unknown: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Unknown, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Vcard.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Vcard.kt index 2e866b56e..a0550c2ba 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Vcard.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Vcard.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -76,7 +77,7 @@ private var _vcard: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Vcard, contentDescription = null) } } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Video.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Video.kt index 4ede33399..ba5a8ef5e 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Video.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Video.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.infomaniak.library.filetypes.FileTypeIcons +import com.infomaniak.library.filetypes.FileTypeIcons.previewSize import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound @@ -78,7 +79,7 @@ private var _video: ImageVector? = null @Preview @Composable private fun Preview() { - Box(modifier = Modifier.padding(12.dp)) { + Box(modifier = Modifier.padding(previewSize)) { Image(imageVector = FileTypeIcons.Video, contentDescription = null) } } From 7e012e1d775692d7da6725d887e42a1ed24a3652 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 16 Oct 2024 09:17:53 +0200 Subject: [PATCH 13/15] Apply suggestions from code review --- .../main/java/com/infomaniak/library/filetypes/FileType.kt | 4 +--- .../java/com/infomaniak/library/filetypes/FileTypeGuesser.kt | 4 ++-- app/build.gradle.kts | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt index 295d70cd0..489340d3b 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt @@ -17,12 +17,10 @@ */ package com.infomaniak.library.filetypes -import android.util.Log import android.webkit.MimeTypeMap import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import com.infomaniak.library.filetypes.icons.* -import org.jetbrains.annotations.TestOnly private val MEDIA_COLOR_LIGHT = Color(0xFF00BCD4) private val MEDIA_COLOR_DARK = Color(0xFF86DEEA) @@ -49,7 +47,7 @@ enum class FileType(val icon: ImageVector, private val colorLight: Color, privat companion object { fun guessFromFileName(fileName: String): FileType { - val extension = fileName.extractExtension() + val extension = fileName.extractExtension() ?: return UNKNOWN val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: return UNKNOWN return guessFromMimeType(mimeType) } diff --git a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt index 1d188c3cd..1b3416f84 100644 --- a/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeGuesser.kt @@ -25,7 +25,7 @@ internal object FileTypeGuesser { "application/x-pdf", ) - val calendarMatches = mimeTypeSetOf( + private val calendarMatches = mimeTypeSetOf( "application/ics", "text/calendar", ) @@ -133,7 +133,7 @@ internal object FileTypeGuesser { private fun mimeTypeSetOf(vararg mimeTypes: String) = MimeTypeSet(mimeTypes.toSet()) - class MimeTypeSet(private val mimeTypes: Set) : Set by mimeTypes { + private class MimeTypeSet(private val mimeTypes: Set) : Set by mimeTypes { override fun contains(element: String): Boolean = mimeTypes.any { mimeType -> element.startsWith(mimeType) } } } diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ebfdd94d8..bb697e9e7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -64,6 +64,7 @@ kapt { } dependencies { + implementation(project(":FileTypes")) implementation(kotlin("reflect")) implementation(libs.androidx.core.ktx) @@ -90,7 +91,6 @@ dependencies { // Compose preview tools implementation(libs.compose.ui.tooling.preview) - implementation(project(":FileTypes")) debugImplementation(libs.compose.ui.tooling) // Hilt From 6b7f52078aa3ea6f6be51aa1b64531121af636e7 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 16 Oct 2024 09:22:38 +0200 Subject: [PATCH 14/15] Split FileType's dependencies into its own version catalog file --- FileTypes/build.gradle.kts | 8 ++++---- FileTypes/gradle/filetype.versions.toml | 11 +++++++++++ gradle/libs.versions.toml | 12 ------------ settings.gradle.kts | 5 +++++ 4 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 FileTypes/gradle/filetype.versions.toml diff --git a/FileTypes/build.gradle.kts b/FileTypes/build.gradle.kts index a5e855d04..826a2df5d 100644 --- a/FileTypes/build.gradle.kts +++ b/FileTypes/build.gradle.kts @@ -39,10 +39,10 @@ android { dependencies { implementation(libs.androidx.core.ktx) - implementation(libs.androidx.ui.android) - implementation(libs.androidx.foundation.android) - implementation(libs.androidx.ui.tooling.preview.android) + implementation(filetype.androidx.ui.android) + implementation(filetype.androidx.foundation.android) + implementation(filetype.androidx.ui.tooling.preview.android) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) - debugImplementation(libs.androidx.ui.tooling) + debugImplementation(filetype.androidx.ui.tooling) } diff --git a/FileTypes/gradle/filetype.versions.toml b/FileTypes/gradle/filetype.versions.toml new file mode 100644 index 000000000..6374ce328 --- /dev/null +++ b/FileTypes/gradle/filetype.versions.toml @@ -0,0 +1,11 @@ +[versions] +uiAndroid = "1.7.3" +foundationAndroid = "1.7.3" +uiToolingPreviewAndroid = "1.7.3" +uiTooling = "1.7.3" + +[libraries] +androidx-ui-android = { group = "androidx.compose.ui", name = "ui-android", version.ref = "uiAndroid" } +androidx-foundation-android = { group = "androidx.compose.foundation", name = "foundation-android", version.ref = "foundationAndroid" } +androidx-ui-tooling-preview-android = { group = "androidx.compose.ui", name = "ui-tooling-preview-android", version.ref = "uiToolingPreviewAndroid" } +androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "uiTooling" } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dde5b1b30..9be8b5e2e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,12 +17,6 @@ navigation = "2.8.1" serialization = "1.7.1" swisstransfer = "0.1.1" -# FileType module -uiAndroid = "1.7.3" -foundationAndroid = "1.7.3" -uiToolingPreviewAndroid = "1.7.3" -uiTooling = "1.7.3" - [libraries] androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } androidx-adaptive = { module = "androidx.compose.material3.adaptive:adaptive", version.ref = "adaptiveLayout" } @@ -50,12 +44,6 @@ swisstransfer-core = { module = "com.github.Infomaniak.multiplatform-SwissTransf androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } junit = { group = "junit", name = "junit", version.ref = "junit" } -# FileType module -androidx-ui-android = { group = "androidx.compose.ui", name = "ui-android", version.ref = "uiAndroid" } -androidx-foundation-android = { group = "androidx.compose.foundation", name = "foundation-android", version.ref = "foundationAndroid" } -androidx-ui-tooling-preview-android = { group = "androidx.compose.ui", name = "ui-tooling-preview-android", version.ref = "uiToolingPreviewAndroid" } -androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "uiTooling" } - [plugins] android-application = { id = "com.android.application", version.ref = "agp" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 55b9a40b6..674765690 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,6 +21,11 @@ dependencyResolutionManagement { mavenCentral() maven { url = uri("https://jitpack.io") } } + versionCatalogs { + create("filetype") { + from(files("FileTypes/gradle/filetype.versions.toml")) + } + } } rootProject.name = "android-SwissTransfer" From 10ccbef8c8f584db1c50827ec1362c476abca1e1 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 16 Oct 2024 09:25:33 +0200 Subject: [PATCH 15/15] Rename FileTile into FileItem --- .../ui/components/{FileTile.kt => FileItem.kt} | 12 ++++++------ .../ui/screen/main/sent/SentListScreen.kt | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) rename app/src/main/java/com/infomaniak/swisstransfer/ui/components/{FileTile.kt => FileItem.kt} (98%) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileItem.kt similarity index 98% rename from app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt rename to app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileItem.kt index 45a8c053f..017a20452 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileTile.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/FileItem.kt @@ -61,7 +61,7 @@ interface FileUiItem { } @Composable -fun FileTile( +fun FileItem( file: FileUiItem, isRemoveButtonVisible: Boolean, isCheckboxVisible: Boolean, @@ -69,7 +69,7 @@ fun FileTile( onClick: () -> Unit, onRemove: (() -> Unit)? = null, ) { - FileTileContent( + FileItemContent( content = { var displayPreview by rememberSaveable { mutableStateOf(file.hasPreview) } @@ -90,7 +90,7 @@ fun FileTile( } @Composable -private fun FileTileContent( +private fun FileItemContent( content: @Composable () -> Unit, onClick: () -> Unit, isCheckboxVisible: Boolean, @@ -199,7 +199,7 @@ private fun FileIcon(fileType: FileType) { @PreviewSmallWindow @PreviewLargeWindow @Composable -private fun FileTilePreview() { +private fun FileItemPreview() { SwissTransferTheme { Surface { Column( @@ -218,7 +218,7 @@ private fun FileTilePreview() { override val mimeType: String? = null override val uri: String = "" } - FileTile( + FileItem( iconFile, isRemoveButtonVisible = true, isCheckboxVisible = true, @@ -236,7 +236,7 @@ private fun FileTilePreview() { override val mimeType: String? = null override val uri: String = "https://picsum.photos/200/300" } - FileTile( + FileItem( file = imageFile, isRemoveButtonVisible = true, isCheckboxVisible = true, 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 e6f153566..4fca7eb5f 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 @@ -26,7 +26,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.infomaniak.swisstransfer.ui.components.FileUiItem -import com.infomaniak.swisstransfer.ui.components.FileTile +import com.infomaniak.swisstransfer.ui.components.FileItem import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewLargeWindow @@ -49,7 +49,7 @@ fun SentListScreen(transfers: List) { } items(3) { - FileTile( + FileItem( file = imageFile, isRemoveButtonVisible = true, isCheckboxVisible = true,