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..826a2df5d --- /dev/null +++ b/FileTypes/build.gradle.kts @@ -0,0 +1,48 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.compose.compiler) +} + +android { + namespace = "com.infomaniak.library.filetypes" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + + 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" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.14" + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + 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(filetype.androidx.ui.tooling) +} diff --git a/FileTypes/consumer-rules.pro b/FileTypes/consumer-rules.pro new file mode 100644 index 000000000..e69de29bb 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/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/java/com/infomaniak/library/filetypes/FileType.kt b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt new file mode 100644 index 000000000..489340d3b --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileType.kt @@ -0,0 +1,67 @@ +/* + * 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 + } + + companion object { + fun guessFromFileName(fileName: String): FileType { + val extension = fileName.extractExtension() ?: return UNKNOWN + val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: return UNKNOWN + return guessFromMimeType(mimeType) + } + + fun guessFromMimeType(mimeType: String): FileType { + 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..1b3416f84 --- /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 + +internal object FileTypeGuesser { + private val pdfMatches = mimeTypeSetOf( + "application/pdf", + "application/acrobat", + "application/nappdf", + "application/x-pdf", + ) + + private 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()) + + 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/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..ebf7f20fe --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/FileTypeIcons.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.library.filetypes + +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 new file mode 100644 index 000000000..2f87455d6 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Archive.kt @@ -0,0 +1,131 @@ +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 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 + +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(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 new file mode 100644 index 000000000..cbbcdbf59 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Audio.kt @@ -0,0 +1,116 @@ +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 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 + +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(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 new file mode 100644 index 000000000..844b58a83 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Calendar.kt @@ -0,0 +1,73 @@ +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 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 + +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(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 new file mode 100644 index 000000000..89eccb4a4 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Code.kt @@ -0,0 +1,85 @@ +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 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 + +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(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 new file mode 100644 index 000000000..0f64d92d1 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Font.kt @@ -0,0 +1,87 @@ +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 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 + +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(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 new file mode 100644 index 000000000..0b9a41cd7 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Image.kt @@ -0,0 +1,83 @@ +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 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 + +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(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 new file mode 100644 index 000000000..a034d0b1d --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Pdf.kt @@ -0,0 +1,103 @@ +/* + * 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 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 + +internal 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(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 new file mode 100644 index 000000000..9678be13b --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Points.kt @@ -0,0 +1,96 @@ +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 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 + +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(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 new file mode 100644 index 000000000..1dd5d72da --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Sheet.kt @@ -0,0 +1,94 @@ +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 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 + +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(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 new file mode 100644 index 000000000..0978b5b26 --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Text.kt @@ -0,0 +1,75 @@ +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 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 + +internal 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(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 new file mode 100644 index 000000000..3b426ed4d --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Unknown.kt @@ -0,0 +1,69 @@ +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 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 + +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(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 new file mode 100644 index 000000000..a0550c2ba --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Vcard.kt @@ -0,0 +1,83 @@ +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 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 + +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(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 new file mode 100644 index 000000000..ba5a8ef5e --- /dev/null +++ b/FileTypes/src/main/java/com/infomaniak/library/filetypes/icons/Video.kt @@ -0,0 +1,85 @@ +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 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 + +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(previewSize)) { + Image(imageVector = FileTypeIcons.Video, contentDescription = null) + } +} diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 19b93c19e..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) @@ -86,6 +87,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/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dc91f9387..9173a6796 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,6 +19,8 @@ + + . + */ +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 +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 +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 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 +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 FileItem( + file: FileUiItem, + isRemoveButtonVisible: Boolean, + isCheckboxVisible: Boolean, + isChecked: () -> Boolean = { false }, + onClick: () -> Unit, + onRemove: (() -> Unit)? = null, +) { + FileItemContent( + content = { + var displayPreview by rememberSaveable { mutableStateOf(file.hasPreview) } + + if (displayPreview) { + FileThumbnail(file.uri.toUri(), onError = { displayPreview = false }) + } else { + FileIcon(file.fileType) + } + }, + onClick = onClick, + isCheckboxVisible = isCheckboxVisible, + isChecked = isChecked, + isRemoveButtonVisible = isRemoveButtonVisible, + onRemove = onRemove, + title = file.fileName, + description = Formatter.formatShortFileSize(LocalContext.current, file.fileSizeInBytes), + ) +} + +@Composable +private fun FileItemContent( + content: @Composable () -> Unit, + onClick: () -> Unit, + isCheckboxVisible: Boolean, + isChecked: () -> Boolean, + isRemoveButtonVisible: Boolean, + onRemove: (() -> Unit)?, + title: String, + description: String +) { + Card( + onClick = onClick, + modifier = Modifier.aspectRatio(164 / 152f), + colors = CardDefaults.cardColors(containerColor = SwissTransferTheme.materialColors.background), + shape = Shapes.small, + border = BorderStroke(width = 1.dp, SwissTransferTheme.materialColors.outlineVariant) + ) { + Box( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .background(SwissTransferTheme.materialColors.surfaceContainerHighest) + ) { + content() + + if (isCheckboxVisible) { + Checkbox( + checked = isChecked(), + onCheckedChange = null, + 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.fileTileRemoveButtonBackground), + 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, + ) + } + } +} + +@Composable +private fun FileThumbnail(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()) { + 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 +private fun FileItemPreview() { + SwissTransferTheme { + Surface { + Column( + modifier = Modifier + .padding(24.dp) + .width(164.dp) + ) + { + 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 = "" + } + FileItem( + iconFile, + isRemoveButtonVisible = true, + isCheckboxVisible = true, + isChecked = { isChecked }, + onClick = { isChecked = !isChecked }, + onRemove = {}, + ) + + 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" + } + FileItem( + file = imageFile, + 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/screen/main/sent/SentListScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/sent/SentListScreen.kt index 36a0977e8..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 @@ -17,24 +17,49 @@ */ package com.infomaniak.swisstransfer.ui.screen.main.sent -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.material3.Surface -import androidx.compose.material3.Text 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.FileItem +import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewLargeWindow import com.infomaniak.swisstransfer.ui.utils.PreviewSmallWindow -import java.util.UUID @Composable fun SentListScreen(transfers: List) { - 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), + ) { + 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" + } + + items(3) { + FileItem( + file = imageFile, + isRemoveButtonVisible = true, + isCheckboxVisible = true, + isChecked = { true }, + onClick = {}, + onRemove = {}) } } } + @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) } 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..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 @@ -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), + 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 0a092c132..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 @@ -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), + 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 4e4a316e1..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,6 +75,7 @@ data class CustomColorScheme( val navigationItemBackground: Color = Color.Unspecified, val tertiaryButtonBackground: Color = Color.Unspecified, val selectedSettingItem: Color = Color.Unspecified, + val fileTileRemoveButtonBackground: Color = Color.Unspecified, val transferTypeLinkContainer: Color = Color.Unspecified, val transferTypeLinkOnContainer: Color = Color.Unspecified, val transferTypeEmailContainer: Color = Color.Unspecified, 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..e78f6ccb3 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/utils/FileUiItemExt.kt @@ -0,0 +1,25 @@ +/* + * 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 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/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 5c95d1969..9be8b5e2e 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" } @@ -48,3 +50,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" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 1a80ad33d..674765690 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,7 +21,13 @@ dependencyResolutionManagement { mavenCentral() maven { url = uri("https://jitpack.io") } } + versionCatalogs { + create("filetype") { + from(files("FileTypes/gradle/filetype.versions.toml")) + } + } } rootProject.name = "android-SwissTransfer" include(":app") +include(":FileTypes")