diff --git a/components/settings/StorageLocationPicker.tsx b/components/settings/StorageLocationPicker.tsx index 751d471b..2de76bd7 100644 --- a/components/settings/StorageLocationPicker.tsx +++ b/components/settings/StorageLocationPicker.tsx @@ -18,7 +18,10 @@ import { toast } from "sonner-native"; import { Text } from "@/components/common/Text"; import type { StorageLocation } from "@/modules"; import { useSettings } from "@/utils/atoms/settings"; -import { getAvailableStorageLocations } from "@/utils/storage"; +import { + clearStorageLocationsCache, + getAvailableStorageLocations, +} from "@/utils/storage"; interface StorageLocationPickerProps { onClose: () => void; @@ -47,6 +50,7 @@ export const StorageLocationPicker = forwardRef< const handleConfirm = () => { updateSettings({ downloadStorageLocation: selectedId }); + clearStorageLocationsCache(); // Clear cache so next download uses new location toast.success( t("settings.storage.storage_location_updated", { defaultValue: "Storage location updated", diff --git a/providers/Downloads/fileOperations.ts b/providers/Downloads/fileOperations.ts index 8ef5deb8..2b302fcc 100644 --- a/providers/Downloads/fileOperations.ts +++ b/providers/Downloads/fileOperations.ts @@ -1,4 +1,4 @@ -import { Directory, File, Paths } from "expo-file-system"; +import { Directory, File } from "expo-file-system"; import { getAllDownloadedItems, getDownloadedItemById } from "./database"; import type { DownloadedItem } from "./types"; import { filePathToUri } from "./utils"; @@ -39,13 +39,11 @@ export function deleteAllAssociatedFiles(item: DownloadedItem): void { stream.DeliveryUrl ) { try { - const subtitleFilename = stream.DeliveryUrl.split("/").pop(); - if (subtitleFilename) { - const subtitleFile = new File(Paths.document, subtitleFilename); - if (subtitleFile.exists) { - subtitleFile.delete(); - console.log(`[DELETE] Subtitle deleted: ${subtitleFilename}`); - } + // Use the full path from DeliveryUrl (it's already a full file:// URI) + const subtitleFile = new File(stream.DeliveryUrl); + if (subtitleFile.exists) { + subtitleFile.delete(); + console.log(`[DELETE] Subtitle deleted: ${stream.DeliveryUrl}`); } } catch (error) { console.error("[DELETE] Failed to delete subtitle:", error); @@ -57,15 +55,13 @@ export function deleteAllAssociatedFiles(item: DownloadedItem): void { // Delete trickplay directory if (item.trickPlayData?.path) { try { - const trickplayDirName = item.trickPlayData.path.split("/").pop(); - if (trickplayDirName) { - const trickplayDir = new Directory(Paths.document, trickplayDirName); - if (trickplayDir.exists) { - trickplayDir.delete(); - console.log( - `[DELETE] Trickplay directory deleted: ${trickplayDirName}`, - ); - } + // Use the full path from trickPlayData (it's already a full file:// URI) + const trickplayDir = new Directory(item.trickPlayData.path); + if (trickplayDir.exists) { + trickplayDir.delete(); + console.log( + `[DELETE] Trickplay directory deleted: ${item.trickPlayData.path}`, + ); } } catch (error) { console.error("[DELETE] Failed to delete trickplay directory:", error); diff --git a/utils/storage.ts b/utils/storage.ts index 8cc3104f..4d92cbe5 100644 --- a/utils/storage.ts +++ b/utils/storage.ts @@ -1,9 +1,13 @@ -import { Paths } from "expo-file-system"; +import { Directory, Paths } from "expo-file-system"; import { Platform } from "react-native"; import { BackgroundDownloader, type StorageLocation } from "@/modules"; let cachedStorageLocations: StorageLocation[] | null = null; +// Debug mode: Set to true to simulate an SD card for testing in emulator +// This creates a real writable directory that mimics SD card behavior +const DEBUG_SIMULATE_SD_CARD = false; + /** * Get all available storage locations (Android only) * Returns cached result on subsequent calls @@ -21,6 +25,29 @@ export async function getAvailableStorageLocations(): Promise< try { const locations = await BackgroundDownloader.getAvailableStorageLocations(); + + // Debug mode: Add a functional simulated SD card for testing + if (DEBUG_SIMULATE_SD_CARD && locations.length === 1) { + // Use a real writable path within the app's document directory + const sdcardSimDir = new Directory(Paths.document, "sdcard_sim"); + + // Create the directory if it doesn't exist + if (!sdcardSimDir.exists) { + sdcardSimDir.create({ intermediates: true }); + } + + const mockSdCard: StorageLocation = { + id: "sdcard_sim", + path: sdcardSimDir.uri.replace("file://", ""), + type: "external", + label: "SD Card (Simulated)", + totalSpace: 64 * 1024 * 1024 * 1024, // 64 GB + freeSpace: 32 * 1024 * 1024 * 1024, // 32 GB free + }; + locations.push(mockSdCard); + console.log("[DEBUG] Added simulated SD card:", mockSdCard.path); + } + cachedStorageLocations = locations; return locations; } catch (error) {