From 1dd1940334be3bc192a39677bfed895c88f11958 Mon Sep 17 00:00:00 2001 From: Gauvain Date: Wed, 10 Jun 2026 22:29:53 +0200 Subject: [PATCH] fix(downloads): compute storage usage from live file sizes The storage bar showed 0.00% because calculateTotalDownloadedSize summed the stored videoFileSize, which is 0 for items downloaded before the size was recorded (or when fileInfo.size was undefined). Stat the file on disk and fall back to the stored value. --- components/settings/StorageSettings.tsx | 9 +++++++- providers/Downloads/fileOperations.ts | 18 +++++++++++++++- .../Downloads/hooks/useDownloadOperations.ts | 21 +++++++++++++++++-- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/components/settings/StorageSettings.tsx b/components/settings/StorageSettings.tsx index c4f798d4..82a97d50 100644 --- a/components/settings/StorageSettings.tsx +++ b/components/settings/StorageSettings.tsx @@ -1,4 +1,4 @@ -import { useQuery } from "@tanstack/react-query"; +import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useTranslation } from "react-i18next"; import { Alert, Platform, View } from "react-native"; import { toast } from "sonner-native"; @@ -12,6 +12,7 @@ import { ListItem } from "../list/ListItem"; export const StorageSettings = () => { const { deleteAllFiles, appSizeUsage } = useDownload(); const { t } = useTranslation(); + const queryClient = useQueryClient(); const successHapticFeedback = useHaptic("success"); const errorHapticFeedback = useHaptic("error"); @@ -27,6 +28,8 @@ export const StorageSettings = () => { used: (app.total - app.remaining) / app.total, }; }, + // Keep the bar moving while a download is writing to disk. + refetchInterval: 10 * 1000, }); const onDeleteClicked = () => { @@ -48,6 +51,10 @@ export const StorageSettings = () => { } catch (_e) { errorHapticFeedback(); toast.error(t("home.settings.toasts.error_deleting_files")); + } finally { + // Reflect the freed space immediately instead of waiting for + // the next poll. + queryClient.invalidateQueries({ queryKey: ["appSize"] }); } }, }, diff --git a/providers/Downloads/fileOperations.ts b/providers/Downloads/fileOperations.ts index 8ef5deb8..6a038740 100644 --- a/providers/Downloads/fileOperations.ts +++ b/providers/Downloads/fileOperations.ts @@ -96,5 +96,21 @@ export function getDownloadedItemSize(id: string): number { */ export function calculateTotalDownloadedSize(): number { const items = getAllDownloadedItems(); - return items.reduce((sum, item) => sum + (item.videoFileSize || 0), 0); + return items.reduce((sum, item) => { + // Read the live file size on disk so the total reflects actual usage and + // self-heals items whose stored videoFileSize is 0 (old schema, or + // `fileInfo.size` was undefined at download time). Fall back to the stored + // value if the file can't be stat'd. + if (item.videoFilePath) { + try { + const file = new File(filePathToUri(item.videoFilePath)); + if (file.exists) { + return sum + (file.size ?? item.videoFileSize ?? 0); + } + } catch (error) { + console.warn("Failed to stat downloaded file for size:", error); + } + } + return sum + (item.videoFileSize ?? 0); + }, 0); } diff --git a/providers/Downloads/hooks/useDownloadOperations.ts b/providers/Downloads/hooks/useDownloadOperations.ts index 90e8036c..0710263b 100644 --- a/providers/Downloads/hooks/useDownloadOperations.ts +++ b/providers/Downloads/hooks/useDownloadOperations.ts @@ -289,7 +289,24 @@ export function useDownloadOperations({ ); const appSizeUsage = useCallback(async () => { - const totalSize = calculateTotalDownloadedSize(); + let totalSize = calculateTotalDownloadedSize(); + + // Also count in-progress downloads (they write straight to their final + // path) so the growing file shows up as app usage instead of drifting + // into the generic device share until completion. + for (const process of processes) { + try { + const file = new File( + Paths.document, + `${generateFilename(process.item)}.mp4`, + ); + if (file.exists) { + totalSize += file.size ?? 0; + } + } catch { + // File not created yet — ignore. + } + } try { const [freeDiskStorage, totalDiskCapacity] = await Promise.all([ @@ -310,7 +327,7 @@ export function useDownloadOperations({ appSize: totalSize, }; } - }, []); + }, [processes]); return { startBackgroundDownload,