UI update with sidebar and settings tabs (#3288)

Co-authored-by: Nahiyan Khan <nahiyan@squareup.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Lily Delalande <119957291+lily-de@users.noreply.github.com>
Co-authored-by: Spence <spencrmartin@gmail.com>
Co-authored-by: spencrmartin <spencermartin@squareup.com>
Co-authored-by: Judson Stephenson <Jud@users.noreply.github.com>
Co-authored-by: Max Novich <mnovich@squareup.com>
Co-authored-by: Best Codes <106822363+The-Best-Codes@users.noreply.github.com>
Co-authored-by: caroline-a-mckenzie <cmckenzie@squareup.com>
Co-authored-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
Zane
2025-07-15 17:24:41 -07:00
committed by GitHub
parent b22f50d1a1
commit 77ea27f5f5
195 changed files with 20633 additions and 7238 deletions
+93
View File
@@ -0,0 +1,93 @@
import { useCallback, useState } from 'react';
export interface DroppedFile {
id: string;
path: string;
name: string;
type: string;
isImage: boolean;
dataUrl?: string; // For image previews
isLoading?: boolean;
error?: string;
}
export const useFileDrop = () => {
const [droppedFiles, setDroppedFiles] = useState<DroppedFile[]>([]);
const handleDrop = useCallback(async (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
const files = e.dataTransfer.files;
if (files.length > 0) {
const droppedFileObjects: DroppedFile[] = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
let droppedFile: DroppedFile;
try {
const path = window.electron.getPathForFile(file);
const isImage = file.type.startsWith('image/');
droppedFile = {
id: `dropped-${Date.now()}-${i}`,
path,
name: file.name,
type: file.type,
isImage,
isLoading: isImage, // Only images need loading state for preview generation
};
} catch (error) {
console.error('Error processing file:', file.name, error);
// Create an error file object
droppedFile = {
id: `dropped-error-${Date.now()}-${i}`,
path: '',
name: file.name,
type: file.type,
isImage: false,
isLoading: false,
error: `Failed to get file path: ${error instanceof Error ? error.message : 'Unknown error'}`,
};
}
droppedFileObjects.push(droppedFile);
// For images, generate a preview (only if successfully processed)
if (droppedFile.isImage && !droppedFile.error) {
const reader = new FileReader();
reader.onload = (event) => {
const dataUrl = event.target?.result as string;
setDroppedFiles((prev) =>
prev.map((f) => (f.id === droppedFile.id ? { ...f, dataUrl, isLoading: false } : f))
);
};
reader.onerror = () => {
console.error('Failed to generate preview for:', file.name);
setDroppedFiles((prev) =>
prev.map((f) =>
f.id === droppedFile.id
? { ...f, error: 'Failed to load image preview', isLoading: false }
: f
)
);
};
reader.readAsDataURL(file);
}
}
setDroppedFiles((prev) => [...prev, ...droppedFileObjects]);
}
}, []);
const handleDragOver = useCallback((e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
}, []);
return {
droppedFiles,
setDroppedFiles,
handleDrop,
handleDragOver,
};
};