Skip to content

Commit

Permalink
Allow the file uploader on Sharing to upload directories (#1060)
Browse files Browse the repository at this point in the history
* Allow the file uploader on Sharing to upload directories

* Split file and directory uploaders

* Remove the directory name from the uploaded file
  • Loading branch information
whitphx authored Aug 9, 2024
1 parent b8cb290 commit e304167
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 9 deletions.
29 changes: 25 additions & 4 deletions packages/sharing-editor/src/Editor/FileUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import React, { useCallback } from "react";
import FileUploaderComponent from "./components/FileUploader";
import { readArrayBuffer } from "./file";

function supportsWebkitDirectory() {
const input = document.createElement("input");
return "webkitdirectory" in input;
}
export const isDirectoryUploadSupported = supportsWebkitDirectory();

interface ReadFile {
name: string;
type: string;
Expand All @@ -10,8 +16,9 @@ interface ReadFile {

export interface FileUploaderProps {
onUpload: (files: ReadFile[]) => void;
directory?: boolean;
}
function FileUploader({ onUpload }: FileUploaderProps) {
function FileUploader({ onUpload, directory = false }: FileUploaderProps) {
const handleFileChange = useCallback<
React.ChangeEventHandler<HTMLInputElement>
>(
Expand All @@ -24,9 +31,13 @@ function FileUploader({ onUpload }: FileUploaderProps) {
for (let idx = 0; idx < e.target.files.length; ++idx) {
const file = e.target.files[idx];

const name = directory
? file.webkitRelativePath.split("/").slice(1).join("/") // Remove the first segment of the path to get rid of the directory name.
: file.name;

fileReadPromises.push(
readArrayBuffer(file).then((arrayBuffer) => ({
name: file.name,
name,
type: file.type,
data: new Uint8Array(arrayBuffer),
})),
Expand All @@ -37,10 +48,20 @@ function FileUploader({ onUpload }: FileUploaderProps) {

e.target.value = "";
},
[onUpload],
[onUpload, directory],
);

return <FileUploaderComponent onChange={handleFileChange} multiple />;
const additionalProps = directory
? { directory: "", webkitdirectory: "" } // Allow selecting directories. Ref: https://stackoverflow.com/a/55615518/13103190
: { multiple: true };

return (
<FileUploaderComponent
onChange={handleFileChange}
directoryIcon={directory}
{...additionalProps}
/>
);
}

export default FileUploader;
12 changes: 8 additions & 4 deletions packages/sharing-editor/src/Editor/components/FileUploader.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import React from "react";
import { RiUpload2Line } from "react-icons/ri";
import { RiUpload2Line, RiFolderUploadLine } from "react-icons/ri";
import styles from "./FileUploader.module.scss";

type InputProps = JSX.IntrinsicElements["input"];
function FileUploader(props: InputProps) {
interface FileUploaderProps extends InputProps {
directoryIcon?: boolean;
}
function FileUploader(props: FileUploaderProps) {
const { directoryIcon, ...inputProps } = props;
return (
<label className={styles.label}>
<RiUpload2Line />
<input type="file" {...props} className={styles.fileInput} />
{directoryIcon ? <RiFolderUploadLine /> : <RiUpload2Line />}
<input type="file" {...inputProps} className={styles.fileInput} />
</label>
);
}
Expand Down
8 changes: 7 additions & 1 deletion packages/sharing-editor/src/Editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import Tab from "./components/Tab";
import Toolbar from "./components/Toolbar";
import ResizableHeader from "./components/ResizableHeader";
import BinaryFileEditor from "./BinaryFileEditor";
import FileUploader, { FileUploaderProps } from "./FileUploader";
import FileUploader, {
FileUploaderProps,
isDirectoryUploadSupported,
} from "./FileUploader";
import AddButton from "./components/AddButton";
import SaveButton from "./components/SaveButton";
import ThemeSelect from "./components/ThemeSelect";
Expand Down Expand Up @@ -244,6 +247,9 @@ const Editor = React.forwardRef<EditorRef, EditorProps>(
<div className={styles.controlButtonGroup}>
<AddButton onClick={handleCreateFile} />
<FileUploader onUpload={handleFileUpload} />
{isDirectoryUploadSupported && (
<FileUploader onUpload={handleFileUpload} directory />
)}
</div>

<div className={styles.requirementsTabContainer}>
Expand Down

0 comments on commit e304167

Please sign in to comment.