feat(storage): clear inactive transfer cache

This commit is contained in:
2026-07-23 22:22:30 +02:00
parent 7cc0e825f6
commit 4074f4bee8
27 changed files with 457 additions and 47 deletions

View File

@@ -231,16 +231,20 @@
<string name="status_receiving">Wird empfangen</string>
<string name="status_stopped">Beendet</string>
<string name="storage_calculating">Wird berechnet…</string>
<string name="storage_clear_transfer_cache">Übertragungscache leeren</string>
<string name="storage_clear_transfer_cache_description">Entfernt zwischengespeicherte Übertragungsinhalte, die nicht von einem laufenden Empfang oder einer aktiven Freigabe verwendet werden. Empfangene Dateien und der Übertragungsverlauf werden nicht gelöscht.</string>
<string name="storage_clearing_transfer_cache">Cache wird geleert…</string>
<string name="storage_delete_transfers">Alle Übertragungen löschen</string>
<string name="storage_delete_transfers_description">Dadurch werden alle Datensätze gesendeter und empfangener Übertragungen aus Ihrem Verlauf gelöscht. Ihre empfangenen Dateien werden nicht gelöscht. Nicht mehr benötigte zwischengespeicherte freigegebene Inhalte werden automatisch bereinigt; dies kann etwas dauern. Dies kann nicht rückgängig gemacht werden.</string>
<string name="storage_delete_transfers_description">Dadurch werden alle Datensätze gesendeter und empfangener Übertragungen aus Ihrem Verlauf gelöscht und nicht benötigter Übertragungscache sofort freigegeben. Laufende Übertragungen und empfangene Dateien werden nicht gelöscht. Dies kann nicht rückgängig gemacht werden.</string>
<string name="storage_app_data">App-Daten</string>
<string name="storage_deleting">Wird gelöscht…</string>
<string name="storage_footer">Übertragungsdaten umfassen Ihren Verlauf und zwischengespeicherte Inhalte aktiver Freigaben. Nicht mehr benötigter Cache wird nach dem Löschen der Datensätze automatisch bereinigt; dies kann etwas dauern. Empfangene Dateien werden für diese Übersicht erfasst, aber hier niemals gelöscht.</string>
<string name="storage_footer">Der Übertragungscache enthält heruntergeladene oder importierte Inhalte, einschließlich Daten, die durch laufende Empfänge und aktive Freigaben geschützt sind. Beim Leeren wird nur nicht benötigter Cache entfernt. Empfangene Dateien werden hier niemals gelöscht.</string>
<string name="storage_received_files">Empfangene Dateien</string>
<string name="storage_temporary">Temporäre Dateien</string>
<string name="storage_title">Speicher</string>
<string name="storage_total">Gesamt</string>
<string name="storage_transfer_data">Übertragungsdaten</string>
<string name="storage_transfer_data">Übertragungscache</string>
<string name="storage_transfer_cache_cleared">Übertragungscache geleert</string>
<string name="storage_transfers_deleted">Alle Übertragungen gelöscht</string>
<string name="transfer_activity_description">Wichtige Aktualisierungen zu dieser Übertragung ansehen</string>
<string name="transfer_activity_title">Aktivität</string>

View File

@@ -231,16 +231,20 @@
<string name="status_receiving">Recibiendo</string>
<string name="status_stopped">Detenido</string>
<string name="storage_calculating">Calculando…</string>
<string name="storage_clear_transfer_cache">Borrar caché de transferencias</string>
<string name="storage_clear_transfer_cache_description">Elimina el contenido de transferencia en caché que no esté siendo utilizado por una recepción en curso o un recurso compartido activo. Los archivos recibidos y el historial no se eliminan.</string>
<string name="storage_clearing_transfer_cache">Borrando caché…</string>
<string name="storage_delete_transfers">Eliminar todas las transferencias</string>
<string name="storage_delete_transfers_description">Esto borra de su historial todos los registros de transferencias enviadas y recibidas. Sus archivos recibidos no se eliminan. El contenido compartido en caché que ya no se necesita se recupera automáticamente, lo que puede tardar un poco. Esto no se puede deshacer.</string>
<string name="storage_delete_transfers_description">Esto borra del historial todos los registros de transferencias enviadas y recibidas y libera inmediatamente la caché de transferencia no utilizada. Las transferencias en curso y los archivos recibidos no se eliminan. Esto no se puede deshacer.</string>
<string name="storage_app_data">Datos de la aplicación</string>
<string name="storage_deleting">Eliminando…</string>
<string name="storage_footer">Los datos de transferencia incluyen su historial y el contenido en caché de los recursos compartidos activos. La caché innecesaria se recupera automáticamente tras eliminar los registros, lo que puede tardar un poco. Los archivos recibidos se registran para este resumen, pero nunca se eliminan aquí.</string>
<string name="storage_footer">La caché de transferencias incluye contenido descargado o importado, incluidos los datos protegidos por recepciones en curso y recursos compartidos activos. Al borrarla solo se elimina la caché no utilizada. Los archivos recibidos nunca se eliminan aquí.</string>
<string name="storage_received_files">Archivos recibidos</string>
<string name="storage_temporary">Archivos temporales</string>
<string name="storage_title">Almacenamiento</string>
<string name="storage_total">Total</string>
<string name="storage_transfer_data">Datos de transferencia</string>
<string name="storage_transfer_data">Caché de transferencias</string>
<string name="storage_transfer_cache_cleared">Caché de transferencias borrada</string>
<string name="storage_transfers_deleted">Todas las transferencias eliminadas</string>
<string name="transfer_activity_description">Vea las actualizaciones importantes de esta transferencia</string>
<string name="transfer_activity_title">Actividad</string>

View File

@@ -231,16 +231,20 @@
<string name="status_receiving">Réception</string>
<string name="status_stopped">Arrêté</string>
<string name="storage_calculating">Calcul…</string>
<string name="storage_clear_transfer_cache">Vider le cache des transferts</string>
<string name="storage_clear_transfer_cache_description">Supprime le contenu de transfert en cache qui nest pas utilisé par une réception en cours ou un partage actif. Les fichiers reçus et lhistorique ne sont pas supprimés.</string>
<string name="storage_clearing_transfer_cache">Vidage du cache…</string>
<string name="storage_delete_transfers">Supprimer tous les transferts</string>
<string name="storage_delete_transfers_description">Cela efface de votre historique tous les enregistrements de transferts envoyés et reçus. Vos fichiers reçus ne sont pas supprimés. Le contenu partagé mis en cache qui nest plus nécessaire est récupéré automatiquement, ce qui peut prendre un peu de temps. Cette action est irréversible.</string>
<string name="storage_delete_transfers_description">Cela efface tous les transferts envoyés et reçus de lhistorique et libère immédiatement le cache inutilisé. Les transferts en cours et les fichiers reçus ne sont pas supprimés. Cette action est irréversible.</string>
<string name="storage_app_data">Données de lapp</string>
<string name="storage_deleting">Suppression…</string>
<string name="storage_footer">Les données de transfert comprennent votre historique et le contenu mis en cache pour les partages actifs. Le cache inutile est récupéré automatiquement après la suppression des enregistrements, ce qui peut prendre un peu de temps. Les fichiers reçus sont suivis pour ce récapitulatif, mais ne sont jamais supprimés ici.</string>
<string name="storage_footer">Le cache des transferts comprend le contenu téléchargé ou importé, y compris les données protégées par les réceptions en cours et les partages actifs. Le vider ne supprime que le cache inutilisé. Les fichiers reçus ne sont jamais supprimés ici.</string>
<string name="storage_received_files">Fichiers reçus</string>
<string name="storage_temporary">Fichiers temporaires</string>
<string name="storage_title">Stockage</string>
<string name="storage_total">Total</string>
<string name="storage_transfer_data">Données de transfert</string>
<string name="storage_transfer_data">Cache des transferts</string>
<string name="storage_transfer_cache_cleared">Cache des transferts vidé</string>
<string name="storage_transfers_deleted">Tous les transferts supprimés</string>
<string name="transfer_activity_description">Consultez les mises à jour importantes de ce transfert</string>
<string name="transfer_activity_title">Activité</string>

View File

@@ -231,16 +231,20 @@
<string name="status_receiving">Ricezione</string>
<string name="status_stopped">Interrotto</string>
<string name="storage_calculating">Calcolo…</string>
<string name="storage_clear_transfer_cache">Svuota cache trasferimenti</string>
<string name="storage_clear_transfer_cache_description">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.</string>
<string name="storage_clearing_transfer_cache">Svuotamento cache…</string>
<string name="storage_delete_transfers">Elimina tutti i trasferimenti</string>
<string name="storage_delete_transfers_description">Questo cancella dalla cronologia tutti i record dei trasferimenti inviati e ricevuti. I file ricevuti non vengono eliminati. Il contenuto condiviso nella cache che non serve più viene recuperato automaticamente, operazione che può richiedere un po di tempo. Questa azione non può essere annullata.</string>
<string name="storage_delete_transfers_description">Elimina dalla cronologia tutti i trasferimenti inviati e ricevuti e libera immediatamente la cache inutilizzata. I trasferimenti in corso e i file ricevuti non vengono eliminati. Questa azione non può essere annullata.</string>
<string name="storage_app_data">Dati dellapp</string>
<string name="storage_deleting">Eliminazione…</string>
<string name="storage_footer">I dati di trasferimento includono la cronologia e il contenuto nella cache per le condivisioni attive. La cache non necessaria viene recuperata automaticamente dopo la rimozione dei record, operazione che può richiedere un po di tempo. I file ricevuti vengono monitorati per questo riepilogo, ma non sono mai eliminati qui.</string>
<string name="storage_footer">La cache dei trasferimenti include contenuti scaricati o importati, compresi i dati protetti da ricezioni in corso e condivisioni attive. Lo svuotamento rimuove solo la cache inutilizzata. I file ricevuti non vengono mai eliminati qui.</string>
<string name="storage_received_files">File ricevuti</string>
<string name="storage_temporary">File temporanei</string>
<string name="storage_title">Archiviazione</string>
<string name="storage_total">Totale</string>
<string name="storage_transfer_data">Dati di trasferimento</string>
<string name="storage_transfer_data">Cache trasferimenti</string>
<string name="storage_transfer_cache_cleared">Cache trasferimenti svuotata</string>
<string name="storage_transfers_deleted">Tutti i trasferimenti eliminati</string>
<string name="transfer_activity_description">Veda gli aggiornamenti importanti di questo trasferimento</string>
<string name="transfer_activity_title">Attività</string>

View File

@@ -231,16 +231,20 @@
<string name="status_receiving">Ontvangen</string>
<string name="status_stopped">Gestopt</string>
<string name="storage_calculating">Berekenen…</string>
<string name="storage_clear_transfer_cache">Overdrachtscache wissen</string>
<string name="storage_clear_transfer_cache_description">Verwijdert overdrachtsinhoud uit de cache die niet wordt gebruikt door een lopende ontvangst of actieve share. Ontvangen bestanden en de overdrachtsgeschiedenis worden niet verwijderd.</string>
<string name="storage_clearing_transfer_cache">Cache wissen…</string>
<string name="storage_delete_transfers">Alle overdrachten verwijderen</string>
<string name="storage_delete_transfers_description">Hiermee worden alle records van verzonden en ontvangen overdrachten uit uw geschiedenis gewist. Uw ontvangen bestanden worden niet verwijderd. Gedeelde inhoud in de cache die niet meer nodig is, wordt automatisch opgeruimd; dit kan enige tijd duren. Dit kan niet ongedaan worden gemaakt.</string>
<string name="storage_delete_transfers_description">Hiermee worden alle verzonden en ontvangen overdrachten uit de geschiedenis gewist en wordt ongebruikte overdrachtscache direct vrijgemaakt. Lopende overdrachten en ontvangen bestanden worden niet verwijderd. Dit kan niet ongedaan worden gemaakt.</string>
<string name="storage_app_data">Appgegevens</string>
<string name="storage_deleting">Verwijderen…</string>
<string name="storage_footer">Overdrachtsgegevens omvatten uw geschiedenis en inhoud in de cache voor actieve shares. Onnodige cache wordt automatisch opgeruimd nadat overdrachtsrecords zijn verwijderd; dit kan enige tijd duren. Ontvangen bestanden worden voor dit overzicht bijgehouden, maar hier nooit verwijderd.</string>
<string name="storage_footer">De overdrachtscache bevat gedownloade of geïmporteerde inhoud, inclusief gegevens die door lopende ontvangsten en actieve shares worden beschermd. Wissen verwijdert alleen ongebruikte cache. Ontvangen bestanden worden hier nooit verwijderd.</string>
<string name="storage_received_files">Ontvangen bestanden</string>
<string name="storage_temporary">Tijdelijke bestanden</string>
<string name="storage_title">Opslag</string>
<string name="storage_total">Totaal</string>
<string name="storage_transfer_data">Overdrachtsgegevens</string>
<string name="storage_transfer_data">Overdrachtscache</string>
<string name="storage_transfer_cache_cleared">Overdrachtscache gewist</string>
<string name="storage_transfers_deleted">Alle overdrachten verwijderd</string>
<string name="transfer_activity_description">Bekijk belangrijke updates voor deze overdracht</string>
<string name="transfer_activity_title">Activiteit</string>

View File

@@ -231,16 +231,20 @@
<string name="status_receiving">Odbieranie</string>
<string name="status_stopped">Zatrzymany</string>
<string name="storage_calculating">Obliczanie…</string>
<string name="storage_clear_transfer_cache">Wyczyść pamięć podręczną transferów</string>
<string name="storage_clear_transfer_cache_description">Usuwa zawartość transferów z pamięci podręcznej, która nie jest używana przez trwające odbieranie ani aktywne udostępnianie. Odebrane pliki i historia nie są usuwane.</string>
<string name="storage_clearing_transfer_cache">Czyszczenie pamięci podręcznej…</string>
<string name="storage_delete_transfers">Usuń wszystkie transfery</string>
<string name="storage_delete_transfers_description">Spowoduje to usunięcie z historii wszystkich rekordów wysłanych i odebranych transferów. Odebrane pliki nie zostaną usunięte. Niepotrzebna już zawartość udostępniona w pamięci podręcznej jest odzyskiwana automatycznie, co może chwilę potrwać. Tej operacji nie można cofnąć.</string>
<string name="storage_delete_transfers_description">Usuwa z historii wszystkie wysłane i odebrane transfery oraz natychmiast zwalnia nieużywaną pamięć podręczną. Trwające transfery i odebrane pliki nie są usuwane. Tej operacji nie można cofnąć.</string>
<string name="storage_app_data">Dane aplikacji</string>
<string name="storage_deleting">Usuwanie…</string>
<string name="storage_footer">Dane transferu obejmują historię oraz zawartość w pamięci podręcznej dla aktywnych udostępnień. Niepotrzebna pamięć podręczna jest odzyskiwana automatycznie po usunięciu rekordów, co może chwilę potrwać. Odebrane pliki są śledzone na potrzeby tego podsumowania, ale nigdy nie są tu usuwane.</string>
<string name="storage_footer">Pamięć podręczna transferów zawiera pobraną lub zaimportowaną zawartość, w tym dane chronione przez trwające odbieranie i aktywne udostępnianie. Czyszczenie usuwa tylko nieużywaną pamięć podręczną. Odebrane pliki nigdy nie są tutaj usuwane.</string>
<string name="storage_received_files">Odebrane pliki</string>
<string name="storage_temporary">Pliki tymczasowe</string>
<string name="storage_title">Pamięć</string>
<string name="storage_total">Łącznie</string>
<string name="storage_transfer_data">Dane transferu</string>
<string name="storage_transfer_data">Pamięć podręczna transferów</string>
<string name="storage_transfer_cache_cleared">Wyczyszczono pamięć podręczną transferów</string>
<string name="storage_transfers_deleted">Usunięto wszystkie transfery</string>
<string name="transfer_activity_description">Zobacz ważne aktualizacje tego transferu</string>
<string name="transfer_activity_title">Aktywność</string>

View File

@@ -231,16 +231,20 @@
<string name="status_receiving">A receber</string>
<string name="status_stopped">Parada</string>
<string name="storage_calculating">A calcular…</string>
<string name="storage_clear_transfer_cache">Limpar cache de transferências</string>
<string name="storage_clear_transfer_cache_description">Remove conteúdo de transferência em cache que não esteja a ser utilizado por uma receção em curso ou partilha ativa. Os ficheiros recebidos e o histórico não são eliminados.</string>
<string name="storage_clearing_transfer_cache">A limpar cache…</string>
<string name="storage_delete_transfers">Eliminar todas as transferências</string>
<string name="storage_delete_transfers_description">Isto elimina do histórico todos os registos de transferências enviadas e recebidas. Os ficheiros recebidos não são eliminados. O conteúdo partilhado em cache que já não é necessário é recuperado automaticamente, o que pode demorar algum tempo. Esta ação não pode ser anulada.</string>
<string name="storage_delete_transfers_description">Isto elimina do histórico todas as transferências enviadas e recebidas e liberta imediatamente a cache não utilizada. As transferências em curso e os ficheiros recebidos não são eliminados. Esta ação não pode ser anulada.</string>
<string name="storage_app_data">Dados da aplicação</string>
<string name="storage_deleting">A eliminar…</string>
<string name="storage_footer">Os dados de transferência incluem o histórico e o conteúdo em cache das partilhas ativas. A cache desnecessária é recuperada automaticamente após a remoção dos registos, o que pode demorar algum tempo. Os ficheiros recebidos são acompanhados para este resumo, mas nunca são eliminados aqui.</string>
<string name="storage_footer">A cache de transferências inclui conteúdo descarregado ou importado, incluindo dados protegidos por receções em curso e partilhas ativas. A limpeza remove apenas a cache não utilizada. Os ficheiros recebidos nunca são eliminados aqui.</string>
<string name="storage_received_files">Ficheiros recebidos</string>
<string name="storage_temporary">Ficheiros temporários</string>
<string name="storage_title">Armazenamento</string>
<string name="storage_total">Total</string>
<string name="storage_transfer_data">Dados de transferência</string>
<string name="storage_transfer_data">Cache de transferências</string>
<string name="storage_transfer_cache_cleared">Cache de transferências limpa</string>
<string name="storage_transfers_deleted">Todas as transferências eliminadas</string>
<string name="transfer_activity_description">Ver as atualizações importantes desta transferência</string>
<string name="transfer_activity_title">Atividade</string>

View File

@@ -231,16 +231,20 @@
<string name="status_receiving">Получение</string>
<string name="status_stopped">Остановлено</string>
<string name="storage_calculating">Вычисление…</string>
<string name="storage_clear_transfer_cache">Очистить кэш передач</string>
<string name="storage_clear_transfer_cache_description">Удаляет кэшированное содержимое передач, которое не используется текущим приёмом или активной раздачей. Полученные файлы и история передач не удаляются.</string>
<string name="storage_clearing_transfer_cache">Очистка кэша…</string>
<string name="storage_delete_transfers">Удалить все передачи</string>
<string name="storage_delete_transfers_description">Это удалит из истории все записи об отправленных и полученных передачах. Полученные файлы не удаляются. Кэшированное общее содержимое, которое больше не требуется, освобождается автоматически; это может занять некоторое время. Это действие нельзя отменить.</string>
<string name="storage_delete_transfers_description">Это удалит из истории все отправленные и полученные передачи и немедленно освободит неиспользуемый кэш. Текущие передачи и полученные файлы не удаляются. Это действие нельзя отменить.</string>
<string name="storage_app_data">Данные приложения</string>
<string name="storage_deleting">Удаление…</string>
<string name="storage_footer">Данные передачи включают историю и кэшированное содержимое активных раздач. Ненужный кэш освобождается автоматически после удаления записей; это может занять некоторое время. Полученные файлы учитываются в этой сводке, но никогда не удаляются здесь.</string>
<string name="storage_footer">Кэш передач содержит загруженные или импортированные данные, включая содержимое, защищённое текущими приёмами и активными раздачами. Очистка удаляет только неиспользуемый кэш. Полученные файлы здесь никогда не удаляются.</string>
<string name="storage_received_files">Полученные файлы</string>
<string name="storage_temporary">Временные файлы</string>
<string name="storage_title">Хранилище</string>
<string name="storage_total">Всего</string>
<string name="storage_transfer_data">Данные передачи</string>
<string name="storage_transfer_data">Кэш передач</string>
<string name="storage_transfer_cache_cleared">Кэш передач очищен</string>
<string name="storage_transfers_deleted">Все передачи удалены</string>
<string name="transfer_activity_description">Просматривайте важные обновления этой передачи</string>
<string name="transfer_activity_title">Активность</string>

View File

@@ -231,16 +231,20 @@
<string name="status_receiving">Receiving</string>
<string name="status_stopped">Stopped</string>
<string name="storage_calculating">Calculating…</string>
<string name="storage_clear_transfer_cache">Clear transfer cache</string>
<string name="storage_clear_transfer_cache_description">Removes cached transfer content after briefly restarting VniDrop. Finish ongoing transfers and stop active shares first. Received files and transfer history are not deleted.</string>
<string name="storage_clearing_transfer_cache">Clearing cache…</string>
<string name="storage_delete_transfers">Delete all transfers</string>
<string name="storage_delete_transfers_description">This clears all sent and received transfer records from your history. Your received files are not deleted. Cached shared content that is no longer needed is reclaimed automatically, which may take a little time. This cant be undone.</string>
<string name="storage_delete_transfers_description">This clears all sent and received transfer records from your history and immediately reclaims unused transfer cache. Ongoing transfers and received files are not deleted. This cant be undone.</string>
<string name="storage_app_data">App data</string>
<string name="storage_deleting">Deleting…</string>
<string name="storage_footer">Transfer data includes your history and cached content for active shares. Unneeded cache is reclaimed automatically after transfer records are removed, which may take a little time. Received files are tracked for this summary but are never deleted here.</string>
<string name="storage_footer">Transfer cache includes downloaded or imported content used by transfers and shares. It can be cleared when no transfer or share is active. Received files are tracked for this summary but are never deleted here.</string>
<string name="storage_received_files">Received files</string>
<string name="storage_temporary">Temporary files</string>
<string name="storage_title">Storage</string>
<string name="storage_total">Total</string>
<string name="storage_transfer_data">Transfer data</string>
<string name="storage_transfer_data">Transfer cache</string>
<string name="storage_transfer_cache_cleared">Transfer cache cleared</string>
<string name="storage_transfers_deleted">All transfers deleted</string>
<string name="transfer_activity_description">See important updates for this transfer</string>
<string name="transfer_activity_title">Activity</string>

View File

@@ -182,6 +182,7 @@ interface CoreGateway {
suspend fun receiveWithOutputSink(ticket: String, outputSink: ReceiveOutputSink, receiverName: String): Result<Unit>
suspend fun receiveWithOutputSinkV2(ticket: String, outputSink: ReceiveOutputSinkV2, receiverName: String): Result<Unit>
suspend fun storageUsage(): Result<CoreStorageUsageModel>
suspend fun clearTransferCache(): Result<ULong>
suspend fun receivedArtifacts(): Result<List<ReceivedArtifactModel>>
suspend fun cancel(transferId: ULong): Result<Unit>
suspend fun delete(transferId: ULong): Result<Unit>

View File

@@ -30,6 +30,7 @@ import uniffi.vnidrop.TicketInspection
import uniffi.vnidrop.TransferMetadata
import uniffi.vnidrop.TransferAccessMode
import uniffi.vnidrop.VnidropCore
import uniffi.vnidrop.clearInactiveTransferCache
import uniffi.vnidrop.defaultCoreNetworkConfig
class CoreRepository(
@@ -45,6 +46,8 @@ class CoreRepository(
override val signals: SharedFlow<CoreSignal> = _signals.asSharedFlow()
private var core: VnidropCore? = null
private var currentAppDataDir: String? = null
private var currentRelaySettings = RelaySettings()
private val lifecycleGate = CoreLifecycleGate()
private val sink = object : CoreEventSink {
@@ -77,6 +80,8 @@ class CoreRepository(
previousCore?.shutdown()
core = null
core = VnidropCore.initializeWithNetworkConfig(appDataDir, sink, relaySettings.toNative())
currentAppDataDir = appDataDir
currentRelaySettings = relaySettings
refreshSnapshot(requireCore())
_state.update { it.copy(isInitialized = true) }
}
@@ -84,6 +89,7 @@ class CoreRepository(
override fun shutdown() {
core?.shutdown()
core = null
currentAppDataDir = null
_state.value = CoreState()
}
@@ -168,6 +174,28 @@ class CoreRepository(
)
}
override suspend fun clearTransferCache(): Result<ULong> = runReconfiguration {
val activeCore = requireCore()
val status = activeCore.status()
require(status.activeTransfers == 0UL && status.activeShares == 0UL) {
"Wait for active transfers and shares to finish before clearing the transfer cache"
}
val appDataDir = requireNotNull(currentAppDataDir) { "Core data directory is unavailable" }
val relaySettings = currentRelaySettings
_state.update { it.copy(isInitialized = false, status = null) }
activeCore.shutdown()
core = null
var reclaimed = 0UL
try {
reclaimed = clearInactiveTransferCache(appDataDir)
} finally {
core = VnidropCore.initializeWithNetworkConfig(appDataDir, sink, relaySettings.toNative())
refreshSnapshot(requireCore())
_state.update { it.copy(isInitialized = true) }
}
reclaimed
}
override suspend fun receivedArtifacts(): Result<List<ReceivedArtifactModel>> = runCore { activeCore ->
activeCore.listReceivedArtifacts().map { artifact ->
ReceivedArtifactModel(

View File

@@ -40,7 +40,7 @@ interface FileSystemService {
if (supportsCustomReceiveFolders) configuredFolder else defaultReceiveFolder()
suspend fun validateReceiveFolder(folder: ReceiveFolder): FolderAccessStatus
suspend fun inspectReceivedArtifacts(artifacts: List<ReceivedArtifactModel>): ReceivedStorageInspection
suspend fun temporaryUsage(): ULong
suspend fun temporaryUsage(receiveFolder: ReceiveFolder): ULong
fun createReceiveOutputSink(folder: ReceiveFolder): ReceiveOutputSinkV2?
fun canRevealReceiveFolder(folder: ReceiveFolder): Boolean = false
suspend fun revealReceiveFolder(folder: ReceiveFolder): Result<Unit> =

View File

@@ -41,5 +41,6 @@ fun SettingsRoute(viewModel: SettingsViewModel, windowClass: WindowClass) {
onBugIncludeLogsChanged = viewModel::setBugIncludeLogs,
onSubmitBugReport = viewModel::submitBugReport,
onDeleteAllTransfers = viewModel::deleteAllTransfers,
onClearTransferCache = viewModel::clearTransferCache,
)
}

View File

@@ -31,6 +31,7 @@ fun SettingsScreen(
onBugIncludeLogsChanged: (Boolean) -> Unit,
onSubmitBugReport: () -> Unit,
onDeleteAllTransfers: () -> Unit = {},
onClearTransferCache: () -> Unit = {},
onRelayModeChanged: (RelayMode) -> Unit = {},
onRelayUrlChanged: (Int, String) -> Unit = { _, _ -> },
onAddRelayUrl: () -> Unit = {},
@@ -67,6 +68,7 @@ fun SettingsScreen(
onBugIncludeLogsChanged = onBugIncludeLogsChanged,
onSubmitBugReport = onSubmitBugReport,
onDeleteAllTransfers = onDeleteAllTransfers,
onClearTransferCache = onClearTransferCache,
onRelayModeChanged = onRelayModeChanged,
onRelayUrlChanged = onRelayUrlChanged,
onAddRelayUrl = onAddRelayUrl,
@@ -107,6 +109,7 @@ fun SettingsScreen(
onBugIncludeLogsChanged = onBugIncludeLogsChanged,
onSubmitBugReport = onSubmitBugReport,
onDeleteAllTransfers = onDeleteAllTransfers,
onClearTransferCache = onClearTransferCache,
onRelayModeChanged = onRelayModeChanged,
onRelayUrlChanged = onRelayUrlChanged,
onAddRelayUrl = onAddRelayUrl,
@@ -139,6 +142,7 @@ private fun SettingsSectionContent(
onBugIncludeLogsChanged: (Boolean) -> Unit,
onSubmitBugReport: () -> Unit,
onDeleteAllTransfers: () -> Unit,
onClearTransferCache: () -> Unit,
onRelayModeChanged: (RelayMode) -> Unit,
onRelayUrlChanged: (Int, String) -> Unit,
onAddRelayUrl: () -> Unit,
@@ -160,7 +164,14 @@ private fun SettingsSectionContent(
showBack = showBack,
)
SettingsSection.Notifications -> NotificationSettings(state, onNotificationsChanged, onOpenNotificationSettings, onBack, showBack)
SettingsSection.Storage -> StorageSettings(state, windowClass, onDeleteAllTransfers, onBack, showBack)
SettingsSection.Storage -> StorageSettings(
state,
windowClass,
onDeleteAllTransfers,
onClearTransferCache,
onBack,
showBack,
)
SettingsSection.About -> AboutSettings(
state = state,
onDiagnosticsChanged = onDiagnosticsChanged,

View File

@@ -49,6 +49,8 @@ import vnidrop.shared.generated.resources.notifications_permission_denied
import vnidrop.shared.generated.resources.notifications_settings_open_failed
import vnidrop.shared.generated.resources.notifications_unsupported
import vnidrop.shared.generated.resources.relay_settings_applied
import vnidrop.shared.generated.resources.storage_transfer_cache_cleared
import vnidrop.shared.generated.resources.storage_transfers_deleted
enum class SettingsSection {
Overview,
@@ -111,6 +113,7 @@ data class SettingsState(
val storage: StorageBreakdown? = null,
val isCalculatingStorage: Boolean = false,
val isDeletingTransfers: Boolean = false,
val isClearingTransferCache: Boolean = false,
) {
val hasRelaySettingsChanges: Boolean
get() = relayMode != savedRelaySettings.mode ||
@@ -208,6 +211,7 @@ class SettingsViewModel(
viewModelScope.launch {
_state.update { it.copy(isCalculatingStorage = true) }
try {
val receiveFolder = _state.value.receiveFolder ?: fileSystemService.defaultReceiveFolder()
val coreUsage = repository.storageUsage().getOrThrow()
val artifacts = repository.receivedArtifacts().getOrThrow()
val received = fileSystemService.inspectReceivedArtifacts(artifacts)
@@ -216,7 +220,7 @@ class SettingsViewModel(
storage = StorageBreakdown(
transferCacheBytes = coreUsage.blobStoreBytes,
appDataBytes = coreUsage.appDataBytes,
temporaryBytes = fileSystemService.temporaryUsage(),
temporaryBytes = fileSystemService.temporaryUsage(receiveFolder),
receivedBytes = received.existingBytes,
receivedFileCount = received.existingCount,
missingReceivedFileCount = received.missingCount,
@@ -235,18 +239,45 @@ class SettingsViewModel(
}
fun deleteAllTransfers() {
if (_state.value.isDeletingTransfers) return
if (_state.value.isDeletingTransfers || _state.value.isClearingTransferCache) return
viewModelScope.launch {
_state.update { it.copy(isDeletingTransfers = true) }
val failures = repository.state.value.transfers
.map { repository.delete(it.transferId) }
.count { it.isFailure }
val cleanup = repository.clearTransferCache()
_state.update { it.copy(isDeletingTransfers = false) }
if (failures == 0) {
loadStorageUsage()
} else {
loadStorageUsage()
if (failures > 0) {
messages.error(IllegalStateException("Could not delete $failures transfer records"))
} else if (cleanup.isSuccess) {
messages.tryShow(UiMessage(UiText.Resource(Res.string.storage_transfers_deleted), UiMessageTone.Success))
}
cleanup.onFailure(messages::error)
}
}
fun clearTransferCache() {
if (
_state.value.isDeletingTransfers ||
_state.value.isClearingTransferCache ||
_state.value.hasActiveNetworkWork
) return
viewModelScope.launch {
_state.update { it.copy(isClearingTransferCache = true) }
repository.clearTransferCache().fold(
onSuccess = {
_state.update { it.copy(isClearingTransferCache = false) }
loadStorageUsage()
messages.tryShow(
UiMessage(UiText.Resource(Res.string.storage_transfer_cache_cleared), UiMessageTone.Success),
)
},
onFailure = { error ->
_state.update { it.copy(isClearingTransferCache = false) }
messages.error(error)
},
)
}
}

View File

@@ -33,6 +33,9 @@ import vnidrop.shared.generated.resources.Res
import vnidrop.shared.generated.resources.button_cancel
import vnidrop.shared.generated.resources.storage_app_data
import vnidrop.shared.generated.resources.storage_calculating
import vnidrop.shared.generated.resources.storage_clear_transfer_cache
import vnidrop.shared.generated.resources.storage_clear_transfer_cache_description
import vnidrop.shared.generated.resources.storage_clearing_transfer_cache
import vnidrop.shared.generated.resources.storage_delete_transfers
import vnidrop.shared.generated.resources.storage_delete_transfers_description
import vnidrop.shared.generated.resources.storage_deleting
@@ -48,10 +51,12 @@ internal fun StorageSettings(
state: SettingsState,
windowClass: WindowClass,
onDeleteAllTransfers: () -> Unit,
onClearTransferCache: () -> Unit,
onBack: () -> Unit,
showBack: Boolean,
) {
var showDeleteConfirmation by rememberSaveable { mutableStateOf(false) }
var showClearCacheConfirmation by rememberSaveable { mutableStateOf(false) }
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
SettingsTopBar(stringResource(Res.string.storage_title), onBack, showBack)
val storage = state.storage
@@ -79,9 +84,25 @@ internal fun StorageSettings(
)
}
}
SecondaryButton(
text = stringResource(
if (state.isClearingTransferCache) {
Res.string.storage_clearing_transfer_cache
} else {
Res.string.storage_clear_transfer_cache
},
),
onClick = { showClearCacheConfirmation = true },
enabled = !state.isDeletingTransfers &&
!state.isClearingTransferCache &&
!state.isCalculatingStorage &&
!state.hasActiveNetworkWork,
)
Button(
onClick = { showDeleteConfirmation = true },
enabled = !state.isDeletingTransfers,
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))
@@ -92,6 +113,20 @@ internal fun StorageSettings(
color = LocalVniDropColors.current.foregroundLighter,
)
}
if (showClearCacheConfirmation) {
AdaptiveDrawer(
windowClass = windowClass,
onDismissRequest = { showClearCacheConfirmation = false },
) {
ClearTransferCachePanel(
onCancel = { showClearCacheConfirmation = false },
onConfirm = {
showClearCacheConfirmation = false
onClearTransferCache()
},
)
}
}
if (showDeleteConfirmation) {
AdaptiveDrawer(
windowClass = windowClass,
@@ -108,6 +143,36 @@ internal fun StorageSettings(
}
}
@Composable
private fun ClearTransferCachePanel(
onCancel: () -> Unit,
onConfirm: () -> Unit,
) {
Column(
Modifier.fillMaxWidth().padding(horizontal = 20.dp, vertical = 14.dp),
verticalArrangement = Arrangement.spacedBy(14.dp),
) {
Text(
stringResource(Res.string.storage_clear_transfer_cache),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
)
Text(
stringResource(Res.string.storage_clear_transfer_cache_description),
color = LocalVniDropColors.current.foregroundLighter,
style = MaterialTheme.typography.bodyMedium,
)
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End)) {
SecondaryButton(stringResource(Res.string.button_cancel), onClick = onCancel)
DestructiveButton(
stringResource(Res.string.storage_clear_transfer_cache),
onClick = onConfirm,
modifier = Modifier.testTag("confirm-clear-transfer-cache"),
)
}
}
}
@Composable
private fun DeleteAllTransfersPanel(
onCancel: () -> Unit,