Implement `FileSystemFileHandle` for file input (#124)

This removes the `FileSystemFileHandleLike` interface in preference to
just implementing the correct interface. The advantage of the
`FileSystemFileHandle` interface is that it can be passed to the
worker directly to load the file.
This commit is contained in:
Ian Flanigan 2022-06-03 19:12:30 +02:00 committed by GitHub
parent 3bbc77049d
commit 203d89b8d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 12 additions and 27 deletions

View File

@ -12,17 +12,9 @@ const ACCEPT_EVERYTHING_TYPE: FilePickerAcceptType = {
accept: { '*/*': [] },
};
export interface FileSystemFileHandleLike {
readonly name: string;
readonly kind: string;
readonly isWritable: boolean;
getFile(): Promise<File>;
createWritable: FileSystemFileHandle['createWritable'];
}
export interface FileChooserProps {
disabled?: boolean;
onChange: (handles: Array<FileSystemFileHandleLike>) => void;
onChange: (handles: Array<FileSystemFileHandle>) => void;
accept?: FilePickerAcceptType[];
control?: typeof controlDefault;
}
@ -170,7 +162,7 @@ export const FileChooser = ({
}: FileChooserProps) => {
const onChangeForInput = useCallback((files: FileList) => {
const handles: FileSystemFileHandleLike[] = [];
const handles: FileSystemFileHandle[] = [];
for (let i = 0; i < files.length; i++) {
const file = files.item(i);
if (file === null) {
@ -180,25 +172,19 @@ export const FileChooser = ({
kind: 'file',
name: file.name,
getFile: () => Promise.resolve(file),
isWritable: false,
createWritable: (_options) => Promise.reject('File not writable.'),
queryPermission: (descriptor) => Promise.resolve(descriptor === 'read' ? 'granted' : 'denied'),
requestPermission: (descriptor) => Promise.resolve(descriptor === 'read' ? 'granted' : 'denied'),
isSameEntry: (_unused) => Promise.resolve(false),
isDirectory: false,
isFile: true,
});
}
onChange(handles);
}, [onChange]);
const onChangeForPicker = useCallback((fileHandles: FileSystemFileHandle[]) => {
const handles: FileSystemFileHandleLike[] = [];
for (const fileHandle of fileHandles) {
handles.push({
kind: fileHandle.kind,
name: fileHandle.name,
getFile: () => fileHandle.getFile(),
isWritable: true,
createWritable: (options) => fileHandle.createWritable(options),
});
}
onChange(handles);
onChange(fileHandles);
}, [onChange]);
return control === 'picker'

View File

@ -7,9 +7,9 @@ import DiskII from '../cards/disk2';
import { ErrorModal } from './ErrorModal';
import index from 'json/disks/index.json';
import { FileChooser, FilePickerAcceptType, FileSystemFileHandleLike } from './FileChooser';
import { noAwait } from './util/promises';
import { useHash } from './hooks/useHash';
import { FileChooser, FilePickerAcceptType } from './FileChooser';
const DISK_TYPES: FilePickerAcceptType[] = [
{
@ -50,7 +50,7 @@ export const FileModal = ({ disk2, number, onClose, isOpen }: FileModalProps) =>
const [busy, setBusy] = useState<boolean>(false);
const [empty, setEmpty] = useState<boolean>(true);
const [category, setCategory] = useState<string>();
const [handles, setHandles] = useState<FileSystemFileHandleLike[]>();
const [handles, setHandles] = useState<FileSystemFileHandle[]>();
const [filename, setFilename] = useState<string>();
const [error, setError] = useState<unknown>();
const hash = useHash();
@ -82,7 +82,7 @@ export const FileModal = ({ disk2, number, onClose, isOpen }: FileModalProps) =>
setHashParts(hashParts);
}, [disk2, filename, number, onClose, handles, hash]);
const onChange = useCallback((handles: FileSystemFileHandleLike[]) => {
const onChange = useCallback((handles: FileSystemFileHandle[]) => {
setEmpty(handles.length === 0);
setHandles(handles);
}, []);

View File

@ -69,9 +69,9 @@ describe('FileChooser', () => {
const handle = handleList[0];
expect(handle.kind).toBe('file');
expect(handle.name).toBe(FAKE_FILE.name);
expect(handle.isWritable).toBe(false);
await expect(handle.getFile()).resolves.toBe(FAKE_FILE);
await expect(handle.createWritable()).rejects.toEqual('File not writable.');
await expect(handle.queryPermission({ mode: 'readwrite' })).resolves.toBe('denied');
});
});
});
@ -125,7 +125,6 @@ describe('FileChooser', () => {
const handle = handleList[0];
expect(handle.kind).toBe(FAKE_FILE_HANDLE.kind);
expect(handle.name).toBe(FAKE_FILE_HANDLE.name);
expect(handle.isWritable).toBe(true);
});
});
});