diff --git a/localization/strings.json b/localization/strings.json
index 57fdf8f..d3db23e 100644
--- a/localization/strings.json
+++ b/localization/strings.json
@@ -3700,10 +3700,10 @@
"storage_delete_transfers_caption": {
"context": "Settings > Storage: caption under the destructive delete-all button.",
"translations": {
- "en": "Clears your send and receive history and the app's cached share content. Received files on disk are kept.",
- "fr": "Efface votre historique d'envois et de réceptions ainsi que le contenu de partage mis en cache par l'app. Les fichiers reçus sur le disque sont conservés.",
+ "en": "Clears your send and receive history and the app’s cached share content. Received files on disk are kept.",
+ "fr": "Efface votre historique d’envois et de réceptions ainsi que le contenu de partage mis en cache par l’app. Les fichiers reçus sur le disque sont conservés.",
"es": "Borra tu historial de envíos y recepciones y el contenido compartido en caché de la app. Los archivos recibidos en el disco se conservan.",
- "it": "Cancella la cronologia di invii e ricezioni e i contenuti di condivisione memorizzati dall'app. I file ricevuti sul disco vengono mantenuti.",
+ "it": "Cancella la cronologia di invii e ricezioni e i contenuti di condivisione memorizzati dall’app. I file ricevuti sul disco vengono mantenuti.",
"de": "Löscht deinen Sende- und Empfangsverlauf sowie die zwischengespeicherten Freigabeinhalte der App. Empfangene Dateien auf dem Datenträger bleiben erhalten.",
"pt": "Limpa o teu histórico de envios e receções e o conteúdo de partilha em cache da app. Os ficheiros recebidos no disco são mantidos.",
"pl": "Czyści historię wysyłania i odbierania oraz zapisane w pamięci podręcznej udostępniane treści. Odebrane pliki na dysku zostają zachowane.",
diff --git a/shared/src/commonMain/composeResources/drawable/icon_fluent_more_vertical.xml b/shared/src/commonMain/composeResources/drawable/icon_fluent_more_vertical.xml
new file mode 100644
index 0000000..b61b8b9
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_fluent_more_vertical.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_fluent_share.xml b/shared/src/commonMain/composeResources/drawable/icon_fluent_share.xml
new file mode 100644
index 0000000..06524e7
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_fluent_share.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_fluent_sparkles.xml b/shared/src/commonMain/composeResources/drawable/icon_fluent_sparkles.xml
new file mode 100644
index 0000000..9119ff9
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_fluent_sparkles.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_fluent_stop_circle.xml b/shared/src/commonMain/composeResources/drawable/icon_fluent_stop_circle.xml
new file mode 100644
index 0000000..f49022d
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_fluent_stop_circle.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_lucide_more_vertical.xml b/shared/src/commonMain/composeResources/drawable/icon_lucide_more_vertical.xml
new file mode 100644
index 0000000..8b1de96
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_lucide_more_vertical.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_lucide_share.xml b/shared/src/commonMain/composeResources/drawable/icon_lucide_share.xml
new file mode 100644
index 0000000..d56f3d9
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_lucide_share.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_lucide_sparkles.xml b/shared/src/commonMain/composeResources/drawable/icon_lucide_sparkles.xml
new file mode 100644
index 0000000..f50080a
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_lucide_sparkles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_lucide_stop_circle.xml b/shared/src/commonMain/composeResources/drawable/icon_lucide_stop_circle.xml
new file mode 100644
index 0000000..611df28
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_lucide_stop_circle.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_material_more_vertical.xml b/shared/src/commonMain/composeResources/drawable/icon_material_more_vertical.xml
new file mode 100644
index 0000000..dcd9c8a
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_material_more_vertical.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_material_share.xml b/shared/src/commonMain/composeResources/drawable/icon_material_share.xml
new file mode 100644
index 0000000..913817b
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_material_share.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_material_sparkles.xml b/shared/src/commonMain/composeResources/drawable/icon_material_sparkles.xml
new file mode 100644
index 0000000..00d1712
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_material_sparkles.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/drawable/icon_material_stop_circle.xml b/shared/src/commonMain/composeResources/drawable/icon_material_stop_circle.xml
new file mode 100644
index 0000000..ab13130
--- /dev/null
+++ b/shared/src/commonMain/composeResources/drawable/icon_material_stop_circle.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/shared/src/commonMain/composeResources/values-fr/strings.xml b/shared/src/commonMain/composeResources/values-fr/strings.xml
index ac3dc1a..912d76e 100644
--- a/shared/src/commonMain/composeResources/values-fr/strings.xml
+++ b/shared/src/commonMain/composeResources/values-fr/strings.xml
@@ -249,7 +249,7 @@
Vider le cache des transferts
Supprime le contenu de transfert en cache qui n’est pas utilisé par une réception en cours ou un partage actif. Les fichiers reçus et l’historique ne sont pas supprimés.
Vidage du cache…
- Efface votre historique d\'envois et de réceptions ainsi que le contenu de partage mis en cache par l\'app. Les fichiers reçus sur le disque sont conservés.
+ Efface votre historique d’envois et de réceptions ainsi que le contenu de partage mis en cache par l’app. Les fichiers reçus sur le disque sont conservés.
Supprime les fichiers temporaires et les résidus des transferts précédents. Vos transferts et fichiers reçus sont conservés.
Actualiser
Cache des transferts vidé
diff --git a/shared/src/commonMain/composeResources/values-it/strings.xml b/shared/src/commonMain/composeResources/values-it/strings.xml
index 1ec70da..53a698a 100644
--- a/shared/src/commonMain/composeResources/values-it/strings.xml
+++ b/shared/src/commonMain/composeResources/values-it/strings.xml
@@ -249,7 +249,7 @@
Svuota cache trasferimenti
Rimuove il contenuto dei trasferimenti memorizzato nella cache che non è usato da una ricezione in corso o da una condivisione attiva. I file ricevuti e la cronologia non vengono eliminati.
Svuotamento cache…
- Cancella la cronologia di invii e ricezioni e i contenuti di condivisione memorizzati dall\'app. I file ricevuti sul disco vengono mantenuti.
+ Cancella la cronologia di invii e ricezioni e i contenuti di condivisione memorizzati dall’app. I file ricevuti sul disco vengono mantenuti.
Rimuove i file temporanei e i residui dei trasferimenti precedenti. I tuoi trasferimenti e i file ricevuti vengono mantenuti.
Aggiorna
Cache trasferimenti svuotata
diff --git a/shared/src/commonMain/composeResources/values/strings.xml b/shared/src/commonMain/composeResources/values/strings.xml
index dcf3929..5a68fa7 100644
--- a/shared/src/commonMain/composeResources/values/strings.xml
+++ b/shared/src/commonMain/composeResources/values/strings.xml
@@ -249,7 +249,7 @@
Clear transfer cache
Removes cached transfer content after briefly restarting VniDrop. Finish ongoing transfers and stop active shares first. Received files and transfer history are not deleted.
Clearing cache…
- Clears your send and receive history and the app\'s cached share content. Received files on disk are kept.
+ Clears your send and receive history and the app’s cached share content. Received files on disk are kept.
Removes temporary files and leftover trash from earlier transfers. Your transfers and received files are kept.
Refresh
Transfer cache cleared
diff --git a/shared/src/commonMain/kotlin/com/vnidrop/app/feature/send/SendCatalog.kt b/shared/src/commonMain/kotlin/com/vnidrop/app/feature/send/SendCatalog.kt
index 3b2243a..601f048 100644
--- a/shared/src/commonMain/kotlin/com/vnidrop/app/feature/send/SendCatalog.kt
+++ b/shared/src/commonMain/kotlin/com/vnidrop/app/feature/send/SendCatalog.kt
@@ -269,10 +269,10 @@ private fun TransferActionsMenu(
contentDescription = moreActionsLabel
},
) {
- Text(
- "⋮",
- style = MaterialTheme.typography.headlineSmall,
- color = LocalVniDropColors.current.foregroundLighter,
+ PlatformIcon(
+ AppIcon.MoreVertical,
+ contentDescription = null,
+ tint = LocalVniDropColors.current.foregroundLighter,
)
}
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
@@ -283,7 +283,7 @@ private fun TransferActionsMenu(
expanded = false
onShare()
},
- leadingIcon = { PlatformIcon(AppIcon.Send, contentDescription = null) },
+ leadingIcon = { PlatformIcon(AppIcon.Share, contentDescription = null) },
)
}
if (transfer.status == TransferStatus.Sharing) {
@@ -293,7 +293,7 @@ private fun TransferActionsMenu(
expanded = false
onStopSharing()
},
- leadingIcon = { PlatformIcon(AppIcon.Close, contentDescription = null) },
+ leadingIcon = { PlatformIcon(AppIcon.StopCircle, contentDescription = null) },
)
}
DropdownMenuItem(
diff --git a/shared/src/commonMain/kotlin/com/vnidrop/app/feature/send/TransferDetails.kt b/shared/src/commonMain/kotlin/com/vnidrop/app/feature/send/TransferDetails.kt
index e7334d0..1917c55 100644
--- a/shared/src/commonMain/kotlin/com/vnidrop/app/feature/send/TransferDetails.kt
+++ b/shared/src/commonMain/kotlin/com/vnidrop/app/feature/send/TransferDetails.kt
@@ -104,7 +104,7 @@ internal fun TransferDetails(
if (transfer.status in setOf(TransferStatus.Importing, TransferStatus.Sharing)) {
IconButton(onClick = onShare) {
PlatformIcon(
- AppIcon.Send,
+ AppIcon.Share,
stringResource(Res.string.transfer_share_title),
tint = LocalVniDropColors.current.brandLink,
)
@@ -147,12 +147,18 @@ internal fun TransferDetails(
stringResource(Res.string.send_stop_sharing),
onClick = onStopSharing,
modifier = Modifier.fillMaxWidth(),
+ leadingIcon = {
+ PlatformIcon(AppIcon.StopCircle, null, modifier = Modifier.size(18.dp))
+ },
)
}
DestructiveButton(
stringResource(Res.string.button_delete_transfer),
onClick = onDelete,
modifier = Modifier.fillMaxWidth(),
+ leadingIcon = {
+ PlatformIcon(AppIcon.Delete, null, modifier = Modifier.size(18.dp))
+ },
)
}
}
diff --git a/shared/src/commonMain/kotlin/com/vnidrop/app/feature/settings/StorageSettings.kt b/shared/src/commonMain/kotlin/com/vnidrop/app/feature/settings/StorageSettings.kt
index 682cf13..36442f4 100644
--- a/shared/src/commonMain/kotlin/com/vnidrop/app/feature/settings/StorageSettings.kt
+++ b/shared/src/commonMain/kotlin/com/vnidrop/app/feature/settings/StorageSettings.kt
@@ -7,9 +7,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
-import androidx.compose.material3.Button
-import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -25,6 +24,8 @@ import androidx.compose.ui.unit.dp
import com.vnidrop.app.ui.components.AdaptiveDrawer
import com.vnidrop.app.ui.components.DestructiveButton
import com.vnidrop.app.ui.components.SecondaryButton
+import com.vnidrop.app.ui.icons.AppIcon
+import com.vnidrop.app.ui.icons.PlatformIcon
import com.vnidrop.app.ui.state.formatBytes
import com.vnidrop.app.ui.state.WindowClass
import com.vnidrop.app.ui.theme.LocalVniDropColors
@@ -75,14 +76,18 @@ internal fun StorageSettings(
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
)
- SecondaryButton(
- stringResource(Res.string.storage_refresh),
- onClick = onRefreshStorage,
- enabled = !state.isCalculatingStorage &&
- !state.isCleaningStorage &&
- !state.isDeletingTransfers &&
- !state.isClearingTransferCache,
- )
+ if (state.isCalculatingStorage) {
+ CircularProgressIndicator(Modifier.size(20.dp), strokeWidth = 2.dp)
+ } else {
+ IconButton(
+ onClick = onRefreshStorage,
+ enabled = !state.isCleaningStorage &&
+ !state.isDeletingTransfers &&
+ !state.isClearingTransferCache,
+ ) {
+ PlatformIcon(AppIcon.Sync, stringResource(Res.string.storage_refresh))
+ }
+ }
}
val storage = state.storage
if (storage == null && state.storageLoadFailed && !state.isCalculatingStorage) {
@@ -90,8 +95,11 @@ internal fun StorageSettings(
stringResource(Res.string.storage_unavailable),
onClick = onRefreshStorage,
modifier = Modifier.fillMaxWidth(),
+ leadingIcon = {
+ PlatformIcon(AppIcon.Sync, null, modifier = Modifier.size(18.dp))
+ },
)
- } else if (storage == null || state.isCalculatingStorage) {
+ } else if (storage == null) {
SettingsGroup {
StorageRow(
title = stringResource(Res.string.storage_calculating),
@@ -126,6 +134,13 @@ internal fun StorageSettings(
!state.isClearingTransferCache &&
!state.isCalculatingStorage &&
!state.hasActiveNetworkWork,
+ leadingIcon = {
+ if (state.isCleaningStorage) {
+ CircularProgressIndicator(Modifier.size(18.dp), strokeWidth = 2.dp)
+ } else {
+ PlatformIcon(AppIcon.Sparkles, null, modifier = Modifier.size(18.dp))
+ }
+ },
)
Text(
stringResource(Res.string.storage_free_up_space_caption),
@@ -145,16 +160,22 @@ internal fun StorageSettings(
!state.isClearingTransferCache &&
!state.isCalculatingStorage &&
!state.hasActiveNetworkWork,
+ leadingIcon = {
+ PlatformIcon(AppIcon.Storage, null, modifier = Modifier.size(18.dp))
+ },
)
- Button(
+ DestructiveButton(
+ text = stringResource(
+ if (state.isDeletingTransfers) Res.string.storage_deleting else Res.string.storage_delete_transfers,
+ ),
onClick = { showDeleteConfirmation = true },
enabled = !state.isDeletingTransfers &&
!state.isClearingTransferCache &&
!state.isCalculatingStorage,
- colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.error),
- ) {
- Text(stringResource(if (state.isDeletingTransfers) Res.string.storage_deleting else Res.string.storage_delete_transfers))
- }
+ leadingIcon = {
+ PlatformIcon(AppIcon.Delete, null, modifier = Modifier.size(18.dp))
+ },
+ )
Text(
stringResource(Res.string.storage_delete_transfers_caption),
style = MaterialTheme.typography.bodySmall,
diff --git a/shared/src/commonMain/kotlin/com/vnidrop/app/ui/components/Buttons.kt b/shared/src/commonMain/kotlin/com/vnidrop/app/ui/components/Buttons.kt
index 78e8a79..2f5fc4f 100644
--- a/shared/src/commonMain/kotlin/com/vnidrop/app/ui/components/Buttons.kt
+++ b/shared/src/commonMain/kotlin/com/vnidrop/app/ui/components/Buttons.kt
@@ -1,6 +1,8 @@
package com.vnidrop.app.ui.components
import androidx.compose.foundation.layout.heightIn
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
@@ -17,7 +19,13 @@ import com.vnidrop.app.ui.platform.LocalUiPlatform
import com.vnidrop.app.ui.theme.LocalVniDropColors
@Composable
-fun PrimaryButton(text: String, onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true) {
+fun PrimaryButton(
+ text: String,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ leadingIcon: @Composable (() -> Unit)? = null,
+) {
val desktop = LocalUiPlatform.current.isDesktop
Button(
onClick = onClick,
@@ -26,12 +34,22 @@ fun PrimaryButton(text: String, onClick: () -> Unit, modifier: Modifier = Modifi
shape = RoundedCornerShape(if (desktop) 6.dp else 8.dp),
colors = ButtonDefaults.buttonColors(containerColor = LocalVniDropColors.current.brandButton, contentColor = Color.White),
) {
+ leadingIcon?.let {
+ it()
+ Spacer(Modifier.width(8.dp))
+ }
Text(text, maxLines = 1, overflow = TextOverflow.Ellipsis)
}
}
@Composable
-fun SecondaryButton(text: String, onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true) {
+fun SecondaryButton(
+ text: String,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ leadingIcon: @Composable (() -> Unit)? = null,
+) {
val desktop = LocalUiPlatform.current.isDesktop
OutlinedButton(
onClick = onClick,
@@ -39,6 +57,10 @@ fun SecondaryButton(text: String, onClick: () -> Unit, modifier: Modifier = Modi
modifier = modifier.heightIn(min = if (desktop) 36.dp else 44.dp),
shape = RoundedCornerShape(if (desktop) 6.dp else 8.dp),
) {
+ leadingIcon?.let {
+ it()
+ Spacer(Modifier.width(8.dp))
+ }
Text(text, maxLines = 1, overflow = TextOverflow.Ellipsis)
}
}
@@ -65,7 +87,13 @@ fun DestructiveQuietButton(text: String, onClick: () -> Unit, modifier: Modifier
}
@Composable
-fun DestructiveButton(text: String, onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true) {
+fun DestructiveButton(
+ text: String,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ leadingIcon: @Composable (() -> Unit)? = null,
+) {
val desktop = LocalUiPlatform.current.isDesktop
Button(
onClick = onClick,
@@ -77,6 +105,10 @@ fun DestructiveButton(text: String, onClick: () -> Unit, modifier: Modifier = Mo
contentColor = Color.White,
),
) {
+ leadingIcon?.let {
+ it()
+ Spacer(Modifier.width(8.dp))
+ }
Text(text, maxLines = 1, overflow = TextOverflow.Ellipsis)
}
}
diff --git a/shared/src/commonMain/kotlin/com/vnidrop/app/ui/icons/PlatformIcons.kt b/shared/src/commonMain/kotlin/com/vnidrop/app/ui/icons/PlatformIcons.kt
index bd7e6a0..909041e 100644
--- a/shared/src/commonMain/kotlin/com/vnidrop/app/ui/icons/PlatformIcons.kt
+++ b/shared/src/commonMain/kotlin/com/vnidrop/app/ui/icons/PlatformIcons.kt
@@ -39,12 +39,19 @@ internal enum class AppIcon(
Info(Res.drawable.icon_material_info, Res.drawable.icon_fluent_info, Res.drawable.icon_lucide_info),
Lock(Res.drawable.icon_material_lock, Res.drawable.icon_fluent_lock, Res.drawable.icon_lucide_lock),
Megaphone(Res.drawable.icon_material_megaphone, Res.drawable.icon_fluent_megaphone, Res.drawable.icon_lucide_megaphone),
+ MoreVertical(
+ Res.drawable.icon_material_more_vertical,
+ Res.drawable.icon_fluent_more_vertical,
+ Res.drawable.icon_lucide_more_vertical,
+ ),
Moon(Res.drawable.icon_material_moon, Res.drawable.icon_fluent_moon, Res.drawable.icon_lucide_moon),
Nfc(Res.drawable.icon_material_nfc, Res.drawable.icon_fluent_nfc, Res.drawable.icon_lucide_nfc),
QrCode(Res.drawable.icon_material_qr_code, Res.drawable.icon_fluent_qr_code, Res.drawable.icon_lucide_qr_code),
Radio(Res.drawable.icon_material_radio, Res.drawable.icon_fluent_radio, Res.drawable.icon_lucide_radio),
Scan(Res.drawable.icon_material_scan, Res.drawable.icon_fluent_scan, Res.drawable.icon_lucide_scan),
Send(Res.drawable.icon_material_send, Res.drawable.icon_fluent_send, Res.drawable.icon_lucide_send),
+ Share(Res.drawable.icon_material_share, Res.drawable.icon_fluent_share, Res.drawable.icon_lucide_share),
+ Sparkles(Res.drawable.icon_material_sparkles, Res.drawable.icon_fluent_sparkles, Res.drawable.icon_lucide_sparkles),
Settings(Res.drawable.icon_material_settings, Res.drawable.icon_fluent_settings, Res.drawable.icon_lucide_settings),
Shield(Res.drawable.icon_material_shield, Res.drawable.icon_fluent_shield, Res.drawable.icon_lucide_shield),
ShieldCheck(
@@ -52,6 +59,11 @@ internal enum class AppIcon(
Res.drawable.icon_fluent_shield_check,
Res.drawable.icon_lucide_shield_check,
),
+ StopCircle(
+ Res.drawable.icon_material_stop_circle,
+ Res.drawable.icon_fluent_stop_circle,
+ Res.drawable.icon_lucide_stop_circle,
+ ),
Storage(Res.drawable.icon_material_storage, Res.drawable.icon_fluent_storage, Res.drawable.icon_lucide_storage),
Sun(Res.drawable.icon_material_sun, Res.drawable.icon_fluent_sun, Res.drawable.icon_lucide_sun),
Sync(Res.drawable.icon_material_sync, Res.drawable.icon_fluent_sync, Res.drawable.icon_lucide_sync),
diff --git a/shared/src/jvmTest/kotlin/com/vnidrop/app/ui/FoundationComposeTest.kt b/shared/src/jvmTest/kotlin/com/vnidrop/app/ui/FoundationComposeTest.kt
index 6ab14cf..d0571bd 100644
--- a/shared/src/jvmTest/kotlin/com/vnidrop/app/ui/FoundationComposeTest.kt
+++ b/shared/src/jvmTest/kotlin/com/vnidrop/app/ui/FoundationComposeTest.kt
@@ -40,6 +40,7 @@ import com.vnidrop.app.feature.receive.ReceiveState
import com.vnidrop.app.feature.settings.SettingsScreen
import com.vnidrop.app.feature.settings.SettingsSection
import com.vnidrop.app.feature.settings.SettingsState
+import com.vnidrop.app.feature.settings.StorageBreakdown
import com.vnidrop.app.feature.settings.SettingsOverview
import com.vnidrop.app.feature.send.SendScreen
import com.vnidrop.app.feature.send.SendState
@@ -223,6 +224,48 @@ class FoundationComposeTest {
runOnIdle { assertTrue(deleteRequested) }
}
+ @Test
+ fun storageKeepsCurrentUsageVisibleWhileRefreshing() = runComposeUiTest {
+ setContent {
+ VniDropTheme(isDarkTheme = false) {
+ SettingsScreen(
+ state = SettingsState(
+ selectedSection = SettingsSection.Storage,
+ isCalculatingStorage = true,
+ storage = StorageBreakdown(
+ transferCacheBytes = 1UL,
+ appDataBytes = 2UL,
+ temporaryBytes = 3UL,
+ receivedBytes = 4UL,
+ receivedFileCount = 1,
+ missingReceivedFileCount = 0,
+ inaccessibleReceivedFileCount = 0,
+ ),
+ ),
+ windowClass = WindowClass.Desktop,
+ onSectionSelected = {},
+ onUsernameChanged = {},
+ onThemeModeChanged = {},
+ onChooseFolder = {},
+ onResetFolder = {},
+ onNotificationsChanged = {},
+ onOpenNotificationSettings = {},
+ onDiagnosticsChanged = {},
+ onBugWhatChanged = {},
+ onBugExpectedChanged = {},
+ onBugStepsChanged = {},
+ onBugContactChanged = {},
+ onBugIncludeLogsChanged = {},
+ onSubmitBugReport = {},
+ )
+ }
+ }
+
+ onNodeWithText("Received files").assertIsDisplayed()
+ onNodeWithText("Transfer data").assertIsDisplayed()
+ onAllNodesWithText("Calculating storage usage…").assertCountEquals(0)
+ }
+
@Test
fun aboutSettingsShowsTheSharedProductAndPrivacyContent() = runComposeUiTest {
setContent {
diff --git a/shared/tools/import_platform_icons.py b/shared/tools/import_platform_icons.py
index 4dc0978..3633f87 100644
--- a/shared/tools/import_platform_icons.py
+++ b/shared/tools/import_platform_icons.py
@@ -48,15 +48,19 @@ ICONS = (
IconSource("info", "info", "Info", "info", "info"),
IconSource("lock", "lock", "Lock Closed", "lock_closed", "lock"),
IconSource("megaphone", "campaign", "Megaphone", "megaphone", "megaphone"),
+ IconSource("more_vertical", "more_vert", "More Vertical", "more_vertical", "ellipsis-vertical"),
IconSource("moon", "dark_mode", "Weather Moon", "weather_moon", "moon"),
IconSource("nfc", "nfc", "Tap Double", "tap_double", "nfc"),
IconSource("qr_code", "qr_code_scanner", "QR Code", "qr_code", "qr-code"),
IconSource("radio", "cell_tower", "Cellular Data 1", "cellular_data_1", "radio-tower"),
IconSource("scan", "document_scanner", "Scan Type", "scan_type", "scan-line"),
IconSource("send", "send", "Send", "send", "send"),
+ IconSource("share", "share", "Share", "share", "share-2"),
+ IconSource("sparkles", "auto_awesome", "Sparkle", "sparkle", "sparkles"),
IconSource("settings", "settings", "Settings", "settings", "settings"),
IconSource("shield", "shield", "Shield", "shield", "shield"),
IconSource("shield_check", "verified_user", "Shield Checkmark", "shield_checkmark", "shield-check"),
+ IconSource("stop_circle", "stop_circle", "Stop", "stop", "circle-stop"),
IconSource("storage", "database", "Database", "database", "database"),
IconSource("sun", "light_mode", "Weather Sunny", "weather_sunny", "sun"),
IconSource("sync", "sync", "Arrow Sync", "arrow_sync", "refresh-cw"),