upload multi files
This commit is contained in:
@@ -12,7 +12,7 @@ import { CloudUpload } from "lucide-react";
|
|||||||
interface DropZoneProps {
|
interface DropZoneProps {
|
||||||
fileType: "js" | "css";
|
fileType: "js" | "css";
|
||||||
isSaving: boolean;
|
isSaving: boolean;
|
||||||
onFileSelected: (file: File) => Promise<void>;
|
onFileSelected: (files: File[]) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = createStyles(({ token, css }) => ({
|
const useStyles = createStyles(({ token, css }) => ({
|
||||||
@@ -56,9 +56,9 @@ const DropZone: React.FC<DropZoneProps> = ({ fileType, isSaving, onFileSelected
|
|||||||
|
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
async (e: React.ChangeEvent<HTMLInputElement>) => {
|
async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const file = e.target.files?.[0];
|
const files = Array.from(e.target.files || []);
|
||||||
if (file) {
|
if (files.length > 0) {
|
||||||
await onFileSelected(file);
|
await onFileSelected(files);
|
||||||
}
|
}
|
||||||
e.target.value = "";
|
e.target.value = "";
|
||||||
},
|
},
|
||||||
@@ -84,6 +84,7 @@ const DropZone: React.FC<DropZoneProps> = ({ fileType, isSaving, onFileSelected
|
|||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
type="file"
|
type="file"
|
||||||
accept={`.${fileType}`}
|
accept={`.${fileType}`}
|
||||||
|
multiple
|
||||||
style={{ display: "none" }}
|
style={{ display: "none" }}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -127,57 +127,61 @@ const FileSection: React.FC<FileSectionProps> = ({
|
|||||||
|
|
||||||
// ── Shared save logic ─────────────────────────────────────────────────────
|
// ── Shared save logic ─────────────────────────────────────────────────────
|
||||||
const saveFile = useCallback(
|
const saveFile = useCallback(
|
||||||
async (file: File) => {
|
async (fileOrFiles: File | File[]) => {
|
||||||
const ext = file.name.split(".").pop()?.toLowerCase();
|
const files = Array.isArray(fileOrFiles) ? fileOrFiles : [fileOrFiles];
|
||||||
if (ext !== fileType) {
|
|
||||||
message.error(t("fileTypeNotSupported", { expected: `.${fileType}` }));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (file.size > MAX_FILE_SIZE) {
|
|
||||||
message.error(t("fileSizeExceeded"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sourcePath =
|
for (const file of files) {
|
||||||
window.api.getPathForFile(file) || (file as File & { path?: string }).path;
|
const ext = file.name.split(".").pop()?.toLowerCase();
|
||||||
if (!sourcePath) {
|
if (ext !== fileType) {
|
||||||
message.error(t("fileAddFailed"));
|
message.error(t("fileTypeNotSupported", { expected: `.${fileType}` }));
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (file.size > MAX_FILE_SIZE) {
|
||||||
setIsSaving(true);
|
message.error(t("fileSizeExceeded"));
|
||||||
try {
|
continue;
|
||||||
const fileId = crypto.randomUUID();
|
|
||||||
const result = await window.api.saveFile({
|
|
||||||
domainId,
|
|
||||||
appId,
|
|
||||||
platform,
|
|
||||||
fileType,
|
|
||||||
fileId,
|
|
||||||
sourcePath,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!result.success) {
|
|
||||||
message.error(result.error || t("fileAddFailed"));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const entry: FileEntry = {
|
const sourcePath =
|
||||||
id: fileId,
|
window.api.getPathForFile(file) || (file as File & { path?: string }).path;
|
||||||
fileName: result.data.fileName,
|
if (!sourcePath) {
|
||||||
fileType,
|
message.error(t("fileAddFailed"));
|
||||||
platform,
|
continue;
|
||||||
status: "added",
|
}
|
||||||
size: result.data.size,
|
|
||||||
storagePath: result.data.storagePath,
|
|
||||||
};
|
|
||||||
|
|
||||||
addFile(domainId, appId, entry);
|
setIsSaving(true);
|
||||||
message.success(t("fileAdded", { name: result.data.fileName }));
|
try {
|
||||||
} catch {
|
const fileId = crypto.randomUUID();
|
||||||
message.error(t("fileAddFailed"));
|
const result = await window.api.saveFile({
|
||||||
} finally {
|
domainId,
|
||||||
setIsSaving(false);
|
appId,
|
||||||
|
platform,
|
||||||
|
fileType,
|
||||||
|
fileId,
|
||||||
|
sourcePath,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
message.error(result.error || t("fileAddFailed"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entry: FileEntry = {
|
||||||
|
id: fileId,
|
||||||
|
fileName: result.data.fileName,
|
||||||
|
fileType,
|
||||||
|
platform,
|
||||||
|
status: "added",
|
||||||
|
size: result.data.size,
|
||||||
|
storagePath: result.data.storagePath,
|
||||||
|
};
|
||||||
|
|
||||||
|
addFile(domainId, appId, entry);
|
||||||
|
message.success(t("fileAdded", { name: result.data.fileName }));
|
||||||
|
} catch {
|
||||||
|
message.error(t("fileAddFailed"));
|
||||||
|
} finally {
|
||||||
|
setIsSaving(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[domainId, appId, platform, fileType, addFile, message, t],
|
[domainId, appId, platform, fileType, addFile, message, t],
|
||||||
@@ -248,7 +252,7 @@ const FileSection: React.FC<FileSectionProps> = ({
|
|||||||
|
|
||||||
const droppedFiles = Array.from(e.dataTransfer.files);
|
const droppedFiles = Array.from(e.dataTransfer.files);
|
||||||
if (droppedFiles.length === 0) return;
|
if (droppedFiles.length === 0) return;
|
||||||
await saveFile(droppedFiles[0]);
|
await saveFile(droppedFiles);
|
||||||
},
|
},
|
||||||
[saveFile],
|
[saveFile],
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user