mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
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:
parent
3bbc77049d
commit
203d89b8d9
@ -12,17 +12,9 @@ const ACCEPT_EVERYTHING_TYPE: FilePickerAcceptType = {
|
|||||||
accept: { '*/*': [] },
|
accept: { '*/*': [] },
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface FileSystemFileHandleLike {
|
|
||||||
readonly name: string;
|
|
||||||
readonly kind: string;
|
|
||||||
readonly isWritable: boolean;
|
|
||||||
getFile(): Promise<File>;
|
|
||||||
createWritable: FileSystemFileHandle['createWritable'];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FileChooserProps {
|
export interface FileChooserProps {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
onChange: (handles: Array<FileSystemFileHandleLike>) => void;
|
onChange: (handles: Array<FileSystemFileHandle>) => void;
|
||||||
accept?: FilePickerAcceptType[];
|
accept?: FilePickerAcceptType[];
|
||||||
control?: typeof controlDefault;
|
control?: typeof controlDefault;
|
||||||
}
|
}
|
||||||
@ -170,7 +162,7 @@ export const FileChooser = ({
|
|||||||
}: FileChooserProps) => {
|
}: FileChooserProps) => {
|
||||||
|
|
||||||
const onChangeForInput = useCallback((files: FileList) => {
|
const onChangeForInput = useCallback((files: FileList) => {
|
||||||
const handles: FileSystemFileHandleLike[] = [];
|
const handles: FileSystemFileHandle[] = [];
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
const file = files.item(i);
|
const file = files.item(i);
|
||||||
if (file === null) {
|
if (file === null) {
|
||||||
@ -180,25 +172,19 @@ export const FileChooser = ({
|
|||||||
kind: 'file',
|
kind: 'file',
|
||||||
name: file.name,
|
name: file.name,
|
||||||
getFile: () => Promise.resolve(file),
|
getFile: () => Promise.resolve(file),
|
||||||
isWritable: false,
|
|
||||||
createWritable: (_options) => Promise.reject('File not writable.'),
|
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(handles);
|
||||||
}, [onChange]);
|
}, [onChange]);
|
||||||
|
|
||||||
const onChangeForPicker = useCallback((fileHandles: FileSystemFileHandle[]) => {
|
const onChangeForPicker = useCallback((fileHandles: FileSystemFileHandle[]) => {
|
||||||
const handles: FileSystemFileHandleLike[] = [];
|
onChange(fileHandles);
|
||||||
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]);
|
}, [onChange]);
|
||||||
|
|
||||||
return control === 'picker'
|
return control === 'picker'
|
||||||
|
@ -7,9 +7,9 @@ import DiskII from '../cards/disk2';
|
|||||||
import { ErrorModal } from './ErrorModal';
|
import { ErrorModal } from './ErrorModal';
|
||||||
|
|
||||||
import index from 'json/disks/index.json';
|
import index from 'json/disks/index.json';
|
||||||
import { FileChooser, FilePickerAcceptType, FileSystemFileHandleLike } from './FileChooser';
|
|
||||||
import { noAwait } from './util/promises';
|
import { noAwait } from './util/promises';
|
||||||
import { useHash } from './hooks/useHash';
|
import { useHash } from './hooks/useHash';
|
||||||
|
import { FileChooser, FilePickerAcceptType } from './FileChooser';
|
||||||
|
|
||||||
const DISK_TYPES: FilePickerAcceptType[] = [
|
const DISK_TYPES: FilePickerAcceptType[] = [
|
||||||
{
|
{
|
||||||
@ -50,7 +50,7 @@ export const FileModal = ({ disk2, number, onClose, isOpen }: FileModalProps) =>
|
|||||||
const [busy, setBusy] = useState<boolean>(false);
|
const [busy, setBusy] = useState<boolean>(false);
|
||||||
const [empty, setEmpty] = useState<boolean>(true);
|
const [empty, setEmpty] = useState<boolean>(true);
|
||||||
const [category, setCategory] = useState<string>();
|
const [category, setCategory] = useState<string>();
|
||||||
const [handles, setHandles] = useState<FileSystemFileHandleLike[]>();
|
const [handles, setHandles] = useState<FileSystemFileHandle[]>();
|
||||||
const [filename, setFilename] = useState<string>();
|
const [filename, setFilename] = useState<string>();
|
||||||
const [error, setError] = useState<unknown>();
|
const [error, setError] = useState<unknown>();
|
||||||
const hash = useHash();
|
const hash = useHash();
|
||||||
@ -82,7 +82,7 @@ export const FileModal = ({ disk2, number, onClose, isOpen }: FileModalProps) =>
|
|||||||
setHashParts(hashParts);
|
setHashParts(hashParts);
|
||||||
}, [disk2, filename, number, onClose, handles, hash]);
|
}, [disk2, filename, number, onClose, handles, hash]);
|
||||||
|
|
||||||
const onChange = useCallback((handles: FileSystemFileHandleLike[]) => {
|
const onChange = useCallback((handles: FileSystemFileHandle[]) => {
|
||||||
setEmpty(handles.length === 0);
|
setEmpty(handles.length === 0);
|
||||||
setHandles(handles);
|
setHandles(handles);
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -69,9 +69,9 @@ describe('FileChooser', () => {
|
|||||||
const handle = handleList[0];
|
const handle = handleList[0];
|
||||||
expect(handle.kind).toBe('file');
|
expect(handle.kind).toBe('file');
|
||||||
expect(handle.name).toBe(FAKE_FILE.name);
|
expect(handle.name).toBe(FAKE_FILE.name);
|
||||||
expect(handle.isWritable).toBe(false);
|
|
||||||
await expect(handle.getFile()).resolves.toBe(FAKE_FILE);
|
await expect(handle.getFile()).resolves.toBe(FAKE_FILE);
|
||||||
await expect(handle.createWritable()).rejects.toEqual('File not writable.');
|
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];
|
const handle = handleList[0];
|
||||||
expect(handle.kind).toBe(FAKE_FILE_HANDLE.kind);
|
expect(handle.kind).toBe(FAKE_FILE_HANDLE.kind);
|
||||||
expect(handle.name).toBe(FAKE_FILE_HANDLE.name);
|
expect(handle.name).toBe(FAKE_FILE_HANDLE.name);
|
||||||
expect(handle.isWritable).toBe(true);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user