Skip to content

Commit 8997ed1

Browse files
authored
Merge pull request #45 from jmrog/configurable-legacy-cleanup-and-reject
Make legacy fileOpen API accept configurable cleanup and rejection
2 parents 6269b4a + 5eb4c53 commit 8997ed1

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

index.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ export function fileOpen<M extends boolean | undefined = false>(options?: {
1010
description?: string;
1111
/** Allow multiple files to be selected. Defaults to false. */
1212
multiple?: M;
13+
/**
14+
* Configurable cleanup and `Promise` rejector usable with legacy API for determining when (and reacting when) a user cancels the operation.
15+
* 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.
16+
* The method should return a function that will be called when either the user chooses to open a file or the `rejectionHandler` is called.
17+
* 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.
18+
*/
19+
setupLegacyCleanupAndRejection?: (
20+
rejectionHandler?: () => void
21+
) => (reject: (reason?: any) => void) => void;
1322
}): M extends false | undefined
1423
? Promise<FileWithHandle>
1524
: Promise<FileWithHandle[]>;

src/legacy/file-open.mjs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,30 @@ export default async (options = {}) => {
3333

3434
// ToDo: Remove this workaround once
3535
// https://github.com/whatwg/html/issues/6376 is specified and supported.
36-
const rejectOnPageInteraction = () => {
37-
window.removeEventListener('pointermove', rejectOnPageInteraction);
38-
window.removeEventListener('pointerdown', rejectOnPageInteraction);
39-
window.removeEventListener('keydown', rejectOnPageInteraction);
40-
reject(new DOMException('The user aborted a request.', 'AbortError'));
41-
};
36+
let cleanupListenersAndMaybeReject;
37+
const rejectionHandler = () => cleanupListenersAndMaybeReject(reject);
38+
if (options.setupLegacyCleanupAndRejection) {
39+
cleanupListenersAndMaybeReject = options.setupLegacyCleanupAndRejection(
40+
rejectionHandler
41+
);
42+
} else {
43+
// Default rejection behavior; works in most cases, but not in Chrome in non-secure contexts.
44+
cleanupListenersAndMaybeReject = (reject) => {
45+
window.removeEventListener('pointermove', rejectionHandler);
46+
window.removeEventListener('pointerdown', rejectionHandler);
47+
window.removeEventListener('keydown', rejectionHandler);
48+
if (reject) {
49+
reject(new DOMException('The user aborted a request.', 'AbortError'));
50+
}
51+
};
4252

43-
window.addEventListener('pointermove', rejectOnPageInteraction);
44-
window.addEventListener('pointerdown', rejectOnPageInteraction);
45-
window.addEventListener('keydown', rejectOnPageInteraction);
53+
window.addEventListener('pointermove', rejectionHandler);
54+
window.addEventListener('pointerdown', rejectionHandler);
55+
window.addEventListener('keydown', rejectionHandler);
56+
}
4657

4758
input.addEventListener('change', () => {
48-
window.removeEventListener('pointermove', rejectOnPageInteraction);
49-
window.removeEventListener('pointerdown', rejectOnPageInteraction);
50-
window.removeEventListener('keydown', rejectOnPageInteraction);
59+
cleanupListenersAndMaybeReject();
5160
resolve(input.multiple ? Array.from(input.files) : input.files[0]);
5261
});
5362

0 commit comments

Comments
 (0)