From 201d6a03f29a1f7cee14cb367c25ce7d6281806e Mon Sep 17 00:00:00 2001 From: m Date: Sun, 13 Sep 2026 09:25:18 +0200 Subject: [PATCH] add sync status --- .../ui/components/FileSyncStatusIcon.kt | 60 +++++++++++++++++++ .../ui/folderdetail/FolderDetailScreen.kt | 3 + .../mobile/ui/folderlist/FolderListScreen.kt | 5 +- .../mobile/ui/search/SearchScreen.kt | 17 ++++-- 4 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/components/FileSyncStatusIcon.kt diff --git a/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/components/FileSyncStatusIcon.kt b/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/components/FileSyncStatusIcon.kt new file mode 100644 index 0000000..6cdf394 --- /dev/null +++ b/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/components/FileSyncStatusIcon.kt @@ -0,0 +1,60 @@ +package com.vaultdrop.mobile.ui.components + +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Cloud +import androidx.compose.material.icons.filled.CloudDone +import androidx.compose.material.icons.filled.CloudOff +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.data.local.entity.FileStatus + +/** Placement d'un fichier entre le device et le serveur distant. */ +private enum class FileSyncPlacement { + LOCAL, + CLOUD, + LOCAL_CLOUD, +} + +private fun FileEntity.syncPlacement(): FileSyncPlacement = when (syncStatus) { + FileStatus.CLOUD -> FileSyncPlacement.CLOUD + FileStatus.LOCAL_CLOUD -> FileSyncPlacement.LOCAL_CLOUD + else -> FileSyncPlacement.LOCAL +} + +/** Icône dédiée à chaque placement. */ +private val FileSyncPlacement.icon: ImageVector + get() = when (this) { + FileSyncPlacement.LOCAL -> Icons.Filled.CloudOff + FileSyncPlacement.CLOUD -> Icons.Filled.Cloud + FileSyncPlacement.LOCAL_CLOUD -> Icons.Filled.CloudDone + } + +/** Teinte dédiée à chaque placement. */ +private val FileSyncPlacement.color: Color + get() = when (this) { + FileSyncPlacement.LOCAL -> Color(0xFFF57F17) + FileSyncPlacement.CLOUD -> Color(0xFF1565C0) + FileSyncPlacement.LOCAL_CLOUD -> Color(0xFF2E7D32) + } + +/** Statut de sync d'un fichier — présence device / serveur distant. */ +@Composable +fun FileSyncStatusIcon( + file: FileEntity, + size: Dp, + modifier: Modifier = Modifier, +) { + val placement = file.syncPlacement() + Icon( + imageVector = placement.icon, + contentDescription = null, + tint = placement.color, + modifier = modifier.size(size), + ) +} \ No newline at end of file diff --git a/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/folderdetail/FolderDetailScreen.kt b/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/folderdetail/FolderDetailScreen.kt index b5cca61..9f9ebe5 100644 --- a/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/folderdetail/FolderDetailScreen.kt +++ b/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/folderdetail/FolderDetailScreen.kt @@ -52,6 +52,7 @@ import com.vaultdrop.mobile.data.local.entity.FolderEntity import com.vaultdrop.mobile.features.connection.ConnectionStatusViewModel import com.vaultdrop.mobile.features.sync.SyncViewModel import com.vaultdrop.mobile.ui.components.FileCategoryIcon +import com.vaultdrop.mobile.ui.components.FileSyncStatusIcon import com.vaultdrop.mobile.ui.components.FolderNameDialog import com.vaultdrop.mobile.ui.components.MoveFolderPickerDialog import com.vaultdrop.mobile.ui.components.SelectionState @@ -359,6 +360,8 @@ private fun FileRow( } if (selection.active) { SelectionStatusIcon(selected = selected) + } else { + FileSyncStatusIcon(file = file, size = 20.dp) } } } diff --git a/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/folderlist/FolderListScreen.kt b/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/folderlist/FolderListScreen.kt index ee9c942..3b8c93d 100644 --- a/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/folderlist/FolderListScreen.kt +++ b/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/folderlist/FolderListScreen.kt @@ -73,6 +73,7 @@ import com.vaultdrop.mobile.features.connection.ConnectionStatusViewModel import com.vaultdrop.mobile.features.saf.safDisplayName import com.vaultdrop.mobile.features.sync.SyncViewModel import com.vaultdrop.mobile.ui.components.FileCategoryIcon +import com.vaultdrop.mobile.ui.components.FileSyncStatusIcon import com.vaultdrop.mobile.ui.components.FolderNameDialog import com.vaultdrop.mobile.ui.components.SelectionState import com.vaultdrop.mobile.ui.components.SelectionStatusIcon @@ -749,9 +750,11 @@ private fun FileCard( Column(modifier = Modifier.padding(12.dp)) { Row(verticalAlignment = androidx.compose.ui.Alignment.CenterVertically) { FileCategoryIcon(file = file, size = 36.dp) + Spacer(Modifier.weight(1f)) if (selection.active) { - Spacer(Modifier.weight(1f)) SelectionStatusIcon(selected = selected) + } else { + FileSyncStatusIcon(file = file, size = 20.dp) } } Spacer(Modifier.height(8.dp)) diff --git a/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/search/SearchScreen.kt b/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/search/SearchScreen.kt index 781f3bf..e5fc1d6 100644 --- a/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/search/SearchScreen.kt +++ b/mobile-kotlin/app/src/main/java/com/vaultdrop/mobile/ui/search/SearchScreen.kt @@ -58,6 +58,7 @@ import com.vaultdrop.mobile.domain.FileCategory import com.vaultdrop.mobile.features.connection.ConnectionStatusViewModel import com.vaultdrop.mobile.features.sync.SyncViewModel import com.vaultdrop.mobile.ui.components.FileCategoryIcon +import com.vaultdrop.mobile.ui.components.FileSyncStatusIcon import com.vaultdrop.mobile.ui.components.MoveFolderPickerDialog import com.vaultdrop.mobile.ui.components.SelectionState import com.vaultdrop.mobile.ui.components.SelectionStatusIcon @@ -385,11 +386,17 @@ private fun SearchResultCard( if (selection.active) { SelectionStatusIcon(selected = selected) } else { - Text( - text = formatSize(file.size), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + Text( + text = formatSize(file.size), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + FileSyncStatusIcon(file = file, size = 18.dp) + } } } }