import { BottomSheetBackdrop, type BottomSheetBackdropProps, BottomSheetModal, BottomSheetScrollView, } from "@gorhom/bottom-sheet"; import { useQuery } from "@tanstack/react-query"; import { forwardRef, useCallback, useState } from "react"; import { useTranslation } from "react-i18next"; import { ActivityIndicator, Platform, TouchableOpacity, View, } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { toast } from "sonner-native"; import { Text } from "@/components/common/Text"; import type { StorageLocation } from "@/modules"; import { useSettings } from "@/utils/atoms/settings"; import { clearStorageLocationsCache, getAvailableStorageLocations, } from "@/utils/storage"; interface StorageLocationPickerProps { onClose: () => void; } export const StorageLocationPicker = forwardRef< BottomSheetModal, StorageLocationPickerProps >(({ onClose }, ref) => { const { t } = useTranslation(); const { settings, updateSettings } = useSettings(); const insets = useSafeAreaInsets(); const [selectedId, setSelectedId] = useState( settings.downloadStorageLocation || "internal", ); const { data: locations, isLoading } = useQuery({ queryKey: ["storageLocations"], queryFn: getAvailableStorageLocations, enabled: Platform.OS === "android", }); const handleSelect = (location: StorageLocation) => { setSelectedId(location.id); }; 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", }), ); onClose(); }; const renderBackdrop = useCallback( (props: BottomSheetBackdropProps) => ( ), [], ); if (Platform.OS !== "android") { return null; } return ( {t("settings.storage.select_storage_location", { defaultValue: "Select Storage Location", })} {t("settings.storage.existing_downloads_note", { defaultValue: "Existing downloads will remain in their current location", })} {isLoading ? ( {t("settings.storage.loading_storage", { defaultValue: "Loading storage options...", })} ) : !locations || locations.length === 0 ? ( {t("settings.storage.no_storage_found", { defaultValue: "No storage locations found", })} ) : ( <> {locations.map((location) => { const isSelected = selectedId === location.id; const freeSpaceGB = (location.freeSpace / 1024 ** 3).toFixed(2); const totalSpaceGB = (location.totalSpace / 1024 ** 3).toFixed( 2, ); const usedPercent = ( ((location.totalSpace - location.freeSpace) / location.totalSpace) * 100 ).toFixed(0); return ( handleSelect(location)} className={`p-4 mb-2 rounded-lg ${ isSelected ? "bg-purple-600/20 border border-purple-600" : "bg-neutral-800" }`} > {location.label} {location.type === "external" && ( {t("settings.storage.removable", { defaultValue: "Removable", })} )} {t("settings.storage.space_info", { defaultValue: "{{free}} GB free of {{total}} GB ({{used}}% used)", free: freeSpaceGB, total: totalSpaceGB, used: usedPercent, })} {isSelected && ( )} ); })} {t("common.cancel", { defaultValue: "Cancel" })} {t("common.confirm", { defaultValue: "Confirm" })} )} ); });