Web: Files: Hotkeys: added support for copying from desktop, removed useless files-converter

This commit is contained in:
Nikita Gopienko 2023-09-08 15:53:47 +03:00
parent 7051e55778
commit 35a4287e03
4 changed files with 48 additions and 141 deletions

View File

@ -61,8 +61,8 @@ const withHotkeys = (Component) => {
setInviteUsersWarningDialogVisible, setInviteUsersWarningDialogVisible,
security, security,
setHotkeysClipboard, copyToClipboard,
moveFilesFromClipboard, uploadClipboardFiles,
} = props; } = props;
const navigate = useNavigate(); const navigate = useNavigate();
@ -118,13 +118,21 @@ const withHotkeys = (Component) => {
} }
}; };
const onPaste = async (e) => {
e.preventDefault();
uploadClipboardFiles(t, e);
};
useEffect(() => { useEffect(() => {
const throttledKeyDownEvent = throttle(onKeyDown, 300); const throttledKeyDownEvent = throttle(onKeyDown, 300);
window.addEventListener("keydown", throttledKeyDownEvent); window.addEventListener("keydown", throttledKeyDownEvent);
document.addEventListener("paste", onPaste);
return () => return () => {
window.removeEventListener("keypress", throttledKeyDownEvent); window.removeEventListener("keypress", throttledKeyDownEvent);
document.removeEventListener("paste", onPaste);
};
}); });
//Select/deselect item //Select/deselect item
@ -333,9 +341,8 @@ const withHotkeys = (Component) => {
hotkeysFilter hotkeysFilter
); );
useHotkeys("Ctrl+c", () => setHotkeysClipboard(), hotkeysFilter); useHotkeys("Ctrl+c", () => copyToClipboard(t), hotkeysFilter);
useHotkeys("Ctrl+x", () => setHotkeysClipboard(true), hotkeysFilter); useHotkeys("Ctrl+x", () => copyToClipboard(t, true), hotkeysFilter);
useHotkeys("Ctrl+v", () => moveFilesFromClipboard(t), hotkeysFilter);
//Upload file //Upload file
useHotkeys( useHotkeys(
@ -401,8 +408,8 @@ const withHotkeys = (Component) => {
selectAll, selectAll,
activateHotkeys, activateHotkeys,
uploadFile, uploadFile,
setHotkeysClipboard, copyToClipboard,
moveFilesFromClipboard, uploadClipboardFiles,
} = hotkeyStore; } = hotkeyStore;
const { const {
@ -489,8 +496,9 @@ const withHotkeys = (Component) => {
setInviteUsersWarningDialogVisible, setInviteUsersWarningDialogVisible,
security, security,
setHotkeysClipboard, copyToClipboard,
moveFilesFromClipboard,
uploadClipboardFiles,
}; };
} }
)(observer(WithHotkeys)); )(observer(WithHotkeys));

View File

@ -1,128 +0,0 @@
export const onConvertFiles = (e, resolve) => {
const items = e.dataTransfer.items;
const files = [];
const callItemFromQueue = (queue, callback) => {
let i = 0;
let queueLength = queue.length;
if (!queue || !queue.length) {
callback();
}
const callNext = (i) => {
queue[i]((error) => {
if (!error && i + 1 < queueLength) {
i++;
callNext(i);
} else {
callback(error);
}
});
};
callNext(i);
};
const readDirEntry = (dirEntry, callback) => {
const entries = [];
const dirReader = dirEntry.createReader();
const getEntries = (entriesCallback) => {
dirReader.readEntries((moreEntries) => {
if (moreEntries.length) {
Array.prototype.push.apply(entries, moreEntries);
getEntries(entriesCallback);
} else {
entriesCallback();
}
}, entriesCallback);
};
getEntries(() => {
readEntries(entries, callback);
});
};
const readEntry = (entry, callback) => {
if (entry.isFile) {
entry.file(
(file) => {
addItem(file, entry.fullPath);
callback();
},
() => {
callback();
}
);
} else if (entry.isDirectory) {
readDirEntry(entry, callback);
}
};
const readEntries = (entries, callback) => {
const queue = [];
loop(entries, (entry) => {
queue.push((func) => {
readEntry(entry, func);
});
});
callItemFromQueue(queue, () => callback());
};
const addFile = (file, relativePath) => {
file.path = relativePath || "";
files.push(file);
};
const loop = (items, callback) => {
let itemsLength;
if (items) {
try {
itemsLength = items.length;
} catch (err) {
itemsLength = null;
}
if (itemsLength === null || typeof itemsLength !== "number") {
// Loop object items
for (let key in items) {
if (items.hasOwnProperty(key)) {
if (callback(items[key], key) === false) {
return;
}
}
}
} else {
// Loop array items
for (let i = 0; i < itemsLength; i++) {
if (callback(items[i], i) === false) {
return;
}
}
}
}
};
const readItems = (items, callback) => {
const entries = [];
loop(items, (item) => {
const entry = item.webkitGetAsEntry();
if (entry) {
if (entry.isFile) {
addItem(item.getAsFile(), entry.fullPath);
} else {
entries.push(entry);
}
}
});
if (entries.length) {
readEntries(entries, callback);
} else {
callback();
}
};
readItems(items, () => resolve(files));
};

View File

@ -6,6 +6,7 @@ import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import toastr from "@docspace/components/toast/toastr"; import toastr from "@docspace/components/toast/toastr";
import { RoomsType } from "@docspace/common/constants"; import { RoomsType } from "@docspace/common/constants";
import { encryptionUploadDialog } from "../helpers/desktop"; import { encryptionUploadDialog } from "../helpers/desktop";
import getFilesFromEvent from "@docspace/components/drag-and-drop/get-files-from-event";
class HotkeyStore { class HotkeyStore {
filesStore; filesStore;
@ -611,12 +612,38 @@ class HotkeyStore {
.catch((e) => { .catch((e) => {
toastr.error(e); toastr.error(e);
clearActiveOperations(fileIds, folderIds); clearActiveOperations(fileIds, folderIds);
})
.finally(() => {
this.filesStore.setHotkeysClipboard([]);
}); });
} else { } else {
toastr.error(t("Common:ErrorEmptyList")); toastr.error(t("Common:ErrorEmptyList"));
} }
}; };
uploadClipboardFiles = async (t, event) => {
const { uploadEmptyFolders } = this.filesActionsStore;
const { startUpload } = this.uploadDataStore;
const currentFolderId = this.selectedFolderStore.id;
if (this.filesStore.hotkeysClipboard.length) {
return this.moveFilesFromClipboard(t);
}
const files = await getFilesFromEvent(event);
const emptyFolders = files.filter((f) => f.isEmptyDirectory);
if (emptyFolders.length > 0) {
uploadEmptyFolders(emptyFolders, currentFolderId).then(() => {
const onlyFiles = files.filter((f) => !f.isEmptyDirectory);
if (onlyFiles.length > 0) startUpload(onlyFiles, currentFolderId, t);
});
} else {
startUpload(files, currentFolderId, t);
}
};
get countTilesInRow() { get countTilesInRow() {
const isDesktopView = isDesktop(); const isDesktopView = isDesktop();
const tileGap = isDesktopView ? 16 : 14; const tileGap = isDesktopView ? 16 : 14;

View File

@ -30,8 +30,8 @@ const FILES_TO_IGNORE = [
* @param evt * @param evt
*/ */
export default async function getFilesFromEvent(evt) { export default async function getFilesFromEvent(evt) {
return isDragEvt(evt) && evt.dataTransfer return (isDragEvt(evt) && evt.dataTransfer) || evt.clipboardData
? getDataTransferFiles(evt.dataTransfer, evt.type) ? getDataTransferFiles(evt.dataTransfer ?? evt.clipboardData, evt.type)
: getInputFiles(evt); : getInputFiles(evt);
} }
@ -59,7 +59,7 @@ async function getDataTransferFiles(dt, type) {
const items = fromList(dt.items).filter((item) => item.kind === "file"); const items = fromList(dt.items).filter((item) => item.kind === "file");
// According to https://html.spec.whatwg.org/multipage/dnd.html#dndevents, // According to https://html.spec.whatwg.org/multipage/dnd.html#dndevents,
// only 'dragstart' and 'drop' has access to the data (source node) // only 'dragstart' and 'drop' has access to the data (source node)
if (type !== "drop") { if (type !== "drop" && type !== "paste") {
return items; return items;
} }
const files = await Promise.all(items.map(toFilePromises)); const files = await Promise.all(items.map(toFilePromises));