icones distinctes par categorie de document

This commit is contained in:
m
2026-09-11 23:55:19 +02:00
parent 13deb5e893
commit ea11f28420
5 changed files with 91 additions and 31 deletions
@@ -0,0 +1,70 @@
package com.vaultdrop.mobile.ui.components
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Description
import androidx.compose.material.icons.filled.Image
import androidx.compose.material.icons.filled.InsertDriveFile
import androidx.compose.material.icons.filled.Movie
import androidx.compose.material.icons.filled.MusicNote
import androidx.compose.material.icons.filled.PictureAsPdf
import androidx.compose.material.icons.filled.TextSnippet
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.Dp
import com.vaultdrop.mobile.data.local.entity.FileEntity
import com.vaultdrop.mobile.domain.FileCategory
import com.vaultdrop.mobile.domain.computeCategory
/** Pictogramme dédié à chaque catégorie de document. */
val FileCategory.icon: ImageVector
get() = when (this) {
FileCategory.PDF -> Icons.Filled.PictureAsPdf
FileCategory.OFFICE -> Icons.Filled.Description
FileCategory.IMAGE -> Icons.Filled.Image
FileCategory.TEXT -> Icons.Filled.TextSnippet
FileCategory.VIDEO -> Icons.Filled.Movie
FileCategory.AUDIO -> Icons.Filled.MusicNote
FileCategory.OTHER -> Icons.Filled.InsertDriveFile
}
/** Teinte dédiée à chaque catégorie de document. */
val FileCategory.color: Color
get() = when (this) {
FileCategory.PDF -> Color(0xFFD32F2F)
FileCategory.OFFICE -> Color(0xFF1565C0)
FileCategory.IMAGE -> Color(0xFF2E7D32)
FileCategory.TEXT -> Color(0xFF546E7A)
FileCategory.VIDEO -> Color(0xFF6A1B9A)
FileCategory.AUDIO -> Color(0xFFAD1457)
FileCategory.OTHER -> Color(0xFF757575)
}
/**
* Catégorie d'un fichier : valeur stockée (`category`, colonne ajoutée en v4)
* sinon recalculée depuis le MIME / l'extension — couvre les enregistrements
* antérieurs où la colonne est NULL.
*/
fun FileEntity.categoryValue(): FileCategory {
val stored = category?.let { runCatching { FileCategory.valueOf(it) }.getOrNull() }
return stored ?: computeCategory(mimeType, extension)
}
/** Icône de catégorie d'un fichier — pictogramme + teinte dédiée. */
@Composable
fun FileCategoryIcon(
file: FileEntity,
size: Dp,
modifier: Modifier = Modifier,
) {
val category = file.categoryValue()
Icon(
imageVector = category.icon,
contentDescription = null,
tint = category.color,
modifier = modifier.size(size),
)
}
@@ -11,13 +11,11 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.InsertDriveFile
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@@ -43,6 +41,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vaultdrop.mobile.R import com.vaultdrop.mobile.R
import com.vaultdrop.mobile.data.local.entity.FileEntity import com.vaultdrop.mobile.data.local.entity.FileEntity
import com.vaultdrop.mobile.ui.components.FileCategoryIcon
import java.time.Instant import java.time.Instant
import java.time.ZoneId import java.time.ZoneId
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
@@ -127,12 +126,7 @@ private fun DocumentViewerPage(file: FileEntity, modifier: Modifier = Modifier)
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {
Column(horizontalAlignment = Alignment.CenterHorizontally) { Column(horizontalAlignment = Alignment.CenterHorizontally) {
Icon( FileCategoryIcon(file = file, size = 64.dp)
imageVector = Icons.Filled.InsertDriveFile,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.size(64.dp),
)
Spacer(Modifier.height(8.dp)) Spacer(Modifier.height(8.dp))
Text( Text(
text = stringResource(R.string.document_reader_coming), text = stringResource(R.string.document_reader_coming),
@@ -13,7 +13,6 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Folder import androidx.compose.material.icons.filled.Folder
import androidx.compose.material.icons.filled.InsertDriveFile
import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
@@ -38,6 +37,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vaultdrop.mobile.R import com.vaultdrop.mobile.R
import com.vaultdrop.mobile.data.local.entity.FileEntity import com.vaultdrop.mobile.data.local.entity.FileEntity
import com.vaultdrop.mobile.data.local.entity.FolderEntity import com.vaultdrop.mobile.data.local.entity.FolderEntity
import com.vaultdrop.mobile.ui.components.FileCategoryIcon
import java.util.Locale import java.util.Locale
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@@ -192,12 +192,7 @@ private fun FileRow(file: FileEntity, onClick: () -> Unit) {
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp), horizontalArrangement = Arrangement.spacedBy(12.dp),
) { ) {
Icon( FileCategoryIcon(file = file, size = 24.dp)
imageVector = Icons.Filled.InsertDriveFile,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.size(24.dp),
)
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Text( Text(
text = file.name, text = file.name,
@@ -17,14 +17,12 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.InsertDriveFile
import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Card import androidx.compose.material3.Card
@@ -52,6 +50,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vaultdrop.mobile.R import com.vaultdrop.mobile.R
import com.vaultdrop.mobile.data.local.entity.FileEntity import com.vaultdrop.mobile.data.local.entity.FileEntity
import com.vaultdrop.mobile.features.sync.SyncViewModel import com.vaultdrop.mobile.features.sync.SyncViewModel
import com.vaultdrop.mobile.ui.components.FileCategoryIcon
import com.vaultdrop.mobile.ui.navigation.FloatingNavBar import com.vaultdrop.mobile.ui.navigation.FloatingNavBar
import com.vaultdrop.mobile.ui.navigation.NavTab import com.vaultdrop.mobile.ui.navigation.NavTab
import java.util.Locale import java.util.Locale
@@ -246,12 +245,7 @@ private fun FileCard(file: FileEntity, onClick: () -> Unit, modifier: Modifier =
modifier = modifier, modifier = modifier,
) { ) {
Column(modifier = Modifier.padding(12.dp)) { Column(modifier = Modifier.padding(12.dp)) {
Icon( FileCategoryIcon(file = file, size = 36.dp)
imageVector = Icons.Filled.InsertDriveFile,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(36.dp),
)
Spacer(Modifier.height(8.dp)) Spacer(Modifier.height(8.dp))
Text( Text(
text = file.name, text = file.name,
@@ -11,14 +11,12 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.InsertDriveFile
import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
@@ -46,6 +44,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vaultdrop.mobile.R import com.vaultdrop.mobile.R
import com.vaultdrop.mobile.data.local.entity.FileEntity import com.vaultdrop.mobile.data.local.entity.FileEntity
import com.vaultdrop.mobile.domain.FileCategory import com.vaultdrop.mobile.domain.FileCategory
import com.vaultdrop.mobile.ui.components.FileCategoryIcon
import com.vaultdrop.mobile.ui.components.color
import com.vaultdrop.mobile.ui.components.icon
import com.vaultdrop.mobile.ui.navigation.FloatingNavBar import com.vaultdrop.mobile.ui.navigation.FloatingNavBar
import com.vaultdrop.mobile.ui.navigation.NavTab import com.vaultdrop.mobile.ui.navigation.NavTab
import java.util.Locale import java.util.Locale
@@ -118,6 +119,7 @@ private fun SearchContent(
label = categoryLabel(category), label = categoryLabel(category),
selected = uiState.selectedCategory == category.dbValue, selected = uiState.selectedCategory == category.dbValue,
onClick = { onCategorySelect(category.dbValue) }, onClick = { onCategorySelect(category.dbValue) },
category = category,
) )
} }
} }
@@ -135,11 +137,21 @@ private fun CategoryChip(
label: String, label: String,
selected: Boolean, selected: Boolean,
onClick: () -> Unit, onClick: () -> Unit,
category: FileCategory? = null,
) { ) {
FilterChip( FilterChip(
selected = selected, selected = selected,
onClick = onClick, onClick = onClick,
label = { Text(label) }, label = { Text(label) },
leadingIcon = category?.let { cat ->
{
Icon(
imageVector = cat.icon,
contentDescription = null,
tint = cat.color,
)
}
},
colors = FilterChipDefaults.filterChipColors( colors = FilterChipDefaults.filterChipColors(
containerColor = Color(0xFFF7F8FA), containerColor = Color(0xFFF7F8FA),
), ),
@@ -227,12 +239,7 @@ private fun SearchResultCard(file: FileEntity, onClick: () -> Unit, modifier: Mo
modifier = Modifier.padding(12.dp), modifier = Modifier.padding(12.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Icon( FileCategoryIcon(file = file, size = 28.dp)
imageVector = Icons.Filled.InsertDriveFile,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(28.dp),
)
Spacer(Modifier.width(12.dp)) Spacer(Modifier.width(12.dp))
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Text( Text(