Skip to content

Commit

Permalink
Merge pull request #45 from jmrog/configurable-legacy-cleanup-and-reject
Browse files Browse the repository at this point in the history
Make legacy fileOpen API accept configurable cleanup and rejection
  • Loading branch information
tomayac authored May 5, 2021
2 parents 6269b4a + 5eb4c53 commit 8997ed1
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 12 deletions.
9 changes: 9 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ export function fileOpen<M extends boolean | undefined = false>(options?: {
description?: string;
/** Allow multiple files to be selected. Defaults to false. */
multiple?: M;
/**
* Configurable cleanup and `Promise` rejector usable with legacy API for determining when (and reacting when) a user cancels the operation.
* The method will be called a reference to the internal `rejectionHandler` that can, e.g., be attached to/removed from the window or called after a timeout.
* The method should return a function that will be called when either the user chooses to open a file or the `rejectionHandler` is called.
* In the latter case, the returned function will also be passed a reference to the `reject` callback for the `Promise` returned by `fileOpen`, so that developers may reject the `Promise` when desired at that time.
*/
setupLegacyCleanupAndRejection?: (
rejectionHandler?: () => void
) => (reject: (reason?: any) => void) => void;
}): M extends false | undefined
? Promise<FileWithHandle>
: Promise<FileWithHandle[]>;
Expand Down
33 changes: 21 additions & 12 deletions src/legacy/file-open.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,30 @@ export default async (options = {}) => {

// ToDo: Remove this workaround once
// https://github.com/whatwg/html/issues/6376 is specified and supported.
const rejectOnPageInteraction = () => {
window.removeEventListener('pointermove', rejectOnPageInteraction);
window.removeEventListener('pointerdown', rejectOnPageInteraction);
window.removeEventListener('keydown', rejectOnPageInteraction);
reject(new DOMException('The user aborted a request.', 'AbortError'));
};
let cleanupListenersAndMaybeReject;
const rejectionHandler = () => cleanupListenersAndMaybeReject(reject);
if (options.setupLegacyCleanupAndRejection) {
cleanupListenersAndMaybeReject = options.setupLegacyCleanupAndRejection(
rejectionHandler
);
} else {
// Default rejection behavior; works in most cases, but not in Chrome in non-secure contexts.
cleanupListenersAndMaybeReject = (reject) => {
window.removeEventListener('pointermove', rejectionHandler);
window.removeEventListener('pointerdown', rejectionHandler);
window.removeEventListener('keydown', rejectionHandler);
if (reject) {
reject(new DOMException('The user aborted a request.', 'AbortError'));
}
};

window.addEventListener('pointermove', rejectOnPageInteraction);
window.addEventListener('pointerdown', rejectOnPageInteraction);
window.addEventListener('keydown', rejectOnPageInteraction);
window.addEventListener('pointermove', rejectionHandler);
window.addEventListener('pointerdown', rejectionHandler);
window.addEventListener('keydown', rejectionHandler);
}

input.addEventListener('change', () => {
window.removeEventListener('pointermove', rejectOnPageInteraction);
window.removeEventListener('pointerdown', rejectOnPageInteraction);
window.removeEventListener('keydown', rejectOnPageInteraction);
cleanupListenersAndMaybeReject();
resolve(input.multiple ? Array.from(input.files) : input.files[0]);
});

Expand Down

0 comments on commit 8997ed1

Please sign in to comment.