import { DialogButton, Focusable, SteamSpinner, TextField } from 'decky-frontend-lib'; import { useEffect } from 'react'; import { FunctionComponent, useState } from 'react'; import { FileIcon, defaultStyles } from 'react-file-icon'; import { FaArrowUp, FaFolder } from 'react-icons/fa'; import Logger from '../../../logger'; import { styleDefObj } from './iconCustomizations'; const logger = new Logger('FilePicker'); export interface FilePickerProps { startPath: string; includeFiles?: boolean; regex?: RegExp; onSubmit: (val: { path: string; realpath: string }) => void; closeModal?: () => void; } interface File { isdir: boolean; name: string; realpath: string; } interface FileListing { realpath: string; files: File[]; } function getList( path: string, includeFiles: boolean = true, ): Promise<{ result: FileListing | string; success: boolean }> { return window.DeckyPluginLoader.callServerMethod('filepicker_ls', { path, include_files: includeFiles }); } const iconStyles = { paddingRight: '10px', width: '1em', }; const FilePicker: FunctionComponent = ({ startPath, includeFiles = true, regex, onSubmit, closeModal, }) => { if (startPath.endsWith('/')) startPath = startPath.substring(0, startPath.length - 1); // remove trailing path const [path, setPath] = useState(startPath); const [listing, setListing] = useState({ files: [], realpath: path }); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { (async () => { if (error) setError(null); setLoading(true); const listing = await getList(path, includeFiles); if (!listing.success) { setListing({ files: [], realpath: path }); setLoading(false); setError(listing.result as string); logger.error(listing.result); return; } setLoading(false); setListing(listing.result as FileListing); logger.log('reloaded', path, listing); })(); }, [path]); return (
{ const newPathArr = path.split('/'); newPathArr.pop(); const newPath = newPathArr.join('/'); setPath(newPath); }} >
{ e.target.value && setPath(e.target.value); }} style={{ height: '100%' }} />
{loading && } {!loading && listing.files .filter((file) => (includeFiles || file.isdir) && (!regex || regex.test(file.name))) .map((file) => { let extension = file.realpath.split('.').pop() as string; return ( { const fullPath = `${path}/${file.name}`; if (file.isdir) setPath(fullPath); else { onSubmit({ path: fullPath, realpath: file.realpath }); closeModal?.(); } }} >
{file.isdir ? ( ) : (
{file.realpath.includes('.') ? ( ) : ( )}
)} {file.name}
); })} {error}
{!loading && !error && !includeFiles && ( { onSubmit({ path, realpath: listing.realpath }); closeModal?.(); }} > Use this folder )}
); }; export default FilePicker;