Skip to content

Commit

Permalink
Merge pull request #84 from Infomaniak/image-tile-component
Browse files Browse the repository at this point in the history
Create a file tile component
  • Loading branch information
LunarX authored Oct 16, 2024
2 parents 7ae82f7 + 10ccbef commit b035fd2
Show file tree
Hide file tree
Showing 39 changed files with 1,891 additions and 8 deletions.
1 change: 1 addition & 0 deletions FileTypes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
48 changes: 48 additions & 0 deletions FileTypes/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -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)
}
Empty file added FileTypes/consumer-rules.pro
Empty file.
11 changes: 11 additions & 0 deletions FileTypes/gradle/filetype.versions.toml
Original file line number Diff line number Diff line change
@@ -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" }
21 changes: 21 additions & 0 deletions FileTypes/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
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() }
}
}
}
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
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<String>) : Set<String> by mimeTypes {
override fun contains(element: String): Boolean = mimeTypes.any { mimeType -> element.startsWith(mimeType) }
}
}
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
package com.infomaniak.library.filetypes

import androidx.compose.ui.unit.dp

internal object FileTypeIcons {
val previewSize = 250.dp
}
Loading

0 comments on commit b035fd2

Please sign in to comment.