fix(files): a folder made from the upload dialog gives the keyboard back the target once it is made
This commit is contained in:
@@ -218,8 +218,9 @@ describe("UploadDialog · where the file goes", () => {
|
|||||||
await waitFor(() => expect(h.createFolder).toHaveBeenCalledWith("Trips"));
|
await waitFor(() => expect(h.createFolder).toHaveBeenCalledWith("Trips"));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("says a new folder is being made while Upload waits for it", async () => {
|
it("says a new folder is being made, then gives the keyboard back the list", async () => {
|
||||||
h.createFolder.mockReturnValue(new Promise(() => {}));
|
let made: (f: unknown) => void = () => {};
|
||||||
|
h.createFolder.mockReturnValue(new Promise((res) => (made = res)));
|
||||||
wrap();
|
wrap();
|
||||||
fireEvent.click(await target());
|
fireEvent.click(await target());
|
||||||
fireEvent.click(await screen.findByTestId("upload-target-new"));
|
fireEvent.click(await screen.findByTestId("upload-target-new"));
|
||||||
@@ -227,6 +228,8 @@ describe("UploadDialog · where the file goes", () => {
|
|||||||
fireEvent.change(field, { target: { value: "Trips" } });
|
fireEvent.change(field, { target: { value: "Trips" } });
|
||||||
fireEvent.keyDown(field, { key: "Enter" });
|
fireEvent.keyDown(field, { key: "Enter" });
|
||||||
expect(await screen.findByText("downloads.upload.makingFolder")).toBeTruthy();
|
expect(await screen.findByText("downloads.upload.makingFolder")).toBeTruthy();
|
||||||
|
made({ ...FOLDERS[1], id: 7, name: "Trips" });
|
||||||
|
await waitFor(async () => expect(document.activeElement).toBe(await target()));
|
||||||
});
|
});
|
||||||
|
|
||||||
// A failed refetch keeps the list it had: the target the file goes to stays shown.
|
// A failed refetch keeps the list it had: the target the file goes to stays shown.
|
||||||
|
|||||||
@@ -81,13 +81,7 @@ export default function UploadDialog({
|
|||||||
const foldersQ = useQuery({ queryKey: qk.fileFolders(), queryFn: api.fileFolders });
|
const foldersQ = useQuery({ queryKey: qk.fileFolders(), queryFn: api.fileFolders });
|
||||||
const [naming, setNaming] = useState(false);
|
const [naming, setNaming] = useState(false);
|
||||||
const targetBox = useRef<HTMLDivElement>(null);
|
const targetBox = useRef<HTMLDivElement>(null);
|
||||||
// A new folder's name ended by a key leaves the keyboard's focus nowhere: back on the list.
|
|
||||||
const refocusTarget = useRef(false);
|
const refocusTarget = useRef(false);
|
||||||
useEffect(() => {
|
|
||||||
if (naming || !refocusTarget.current) return;
|
|
||||||
refocusTarget.current = false;
|
|
||||||
targetBox.current?.querySelector("button")?.focus();
|
|
||||||
}, [naming]);
|
|
||||||
// A press on Cancel, the ✕ or the backdrop blurs the name field before the dialog closes, and the
|
// A press on Cancel, the ✕ or the backdrop blurs the name field before the dialog closes, and the
|
||||||
// field saves on blur: that press is "never mind", not "make it". The press is seen before the
|
// field saves on blur: that press is "never mind", not "make it". The press is seen before the
|
||||||
// blur it causes, in every browser (which control takes the focus, if any, differs: Safari
|
// blur it causes, in every browser (which control takes the focus, if any, differs: Safari
|
||||||
@@ -112,6 +106,15 @@ export default function UploadDialog({
|
|||||||
},
|
},
|
||||||
meta: { failTitle: "errors.writeFailed.folder.create" },
|
meta: { failTitle: "errors.writeFailed.folder.create" },
|
||||||
});
|
});
|
||||||
|
// A new folder's name ended by a key leaves the keyboard's focus nowhere: back on the list — once
|
||||||
|
// it is back, as the folder is made (or fails): until then its place says it is being made.
|
||||||
|
useEffect(() => {
|
||||||
|
if (naming || !refocusTarget.current) return;
|
||||||
|
const list = targetBox.current?.querySelector("button");
|
||||||
|
if (!list) return;
|
||||||
|
refocusTarget.current = false;
|
||||||
|
list.focus();
|
||||||
|
}, [naming, makeFolder.isPending]);
|
||||||
// Not while a folder is being named or made: the file would go to the last target, not that one.
|
// Not while a folder is being named or made: the file would go to the last target, not that one.
|
||||||
const targetSettling = naming || makeFolder.isPending;
|
const targetSettling = naming || makeFolder.isPending;
|
||||||
const targets = (foldersQ.data ?? []).filter(takesUploads);
|
const targets = (foldersQ.data ?? []).filter(takesUploads);
|
||||||
|
|||||||
Reference in New Issue
Block a user