mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix: show all uploaded files with format and size in left panel
Replace the single-file pill with a full file list showing name (truncated), format badge, and size for each file. First 5 files are visible by default with a "show more" toggle for the rest. Clicking a file selects it in the viewer. Applies to all tools.
This commit is contained in:
@@ -57,28 +57,40 @@ function canBrowserPreview(url: string, filename?: string | null): boolean {
|
|||||||
return BROWSER_PREVIEWABLE_EXTS.has(ext);
|
return BROWSER_PREVIEWABLE_EXTS.has(ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getFileFormat(name: string): string {
|
||||||
|
const ext = name.split(".").pop()?.toLowerCase() ?? "";
|
||||||
|
return ext.toUpperCase() || "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
const COLLAPSED_LIMIT = 5;
|
||||||
|
|
||||||
/** File selection indicator shown in left panel */
|
/** File selection indicator shown in left panel */
|
||||||
function FileSelectionInfo({
|
function FileSelectionInfo({
|
||||||
files,
|
files,
|
||||||
selectedFileName,
|
selectedIndex,
|
||||||
selectedFileSize,
|
onSelect,
|
||||||
onClear,
|
onClear,
|
||||||
onAddMore,
|
onAddMore,
|
||||||
}: {
|
}: {
|
||||||
files: File[];
|
files: File[];
|
||||||
selectedFileName: string | null;
|
selectedIndex: number;
|
||||||
selectedFileSize: number | null;
|
onSelect: (index: number) => void;
|
||||||
onClear: () => void;
|
onClear: () => void;
|
||||||
onAddMore: () => void;
|
onAddMore: () => void;
|
||||||
}) {
|
}) {
|
||||||
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
|
||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
return (
|
return (
|
||||||
<p className="text-xs text-muted-foreground italic">Drop or upload an image to get started</p>
|
<p className="text-xs text-muted-foreground italic">Drop or upload an image to get started</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showToggle = files.length > COLLAPSED_LIMIT;
|
||||||
|
const visible = expanded ? files : files.slice(0, COLLAPSED_LIMIT);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1.5">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<span className="text-xs font-medium text-foreground">Files ({files.length})</span>
|
<span className="text-xs font-medium text-foreground">Files ({files.length})</span>
|
||||||
<button
|
<button
|
||||||
@@ -89,13 +101,38 @@ function FileSelectionInfo({
|
|||||||
+ Add more
|
+ Add more
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1.5 text-xs text-foreground bg-muted rounded px-2 py-1.5">
|
|
||||||
<CheckCircle2 className="h-3.5 w-3.5 text-green-500 shrink-0" />
|
<div className="space-y-0.5">
|
||||||
<span className="truncate flex-1">{selectedFileName ?? files[0].name}</span>
|
{visible.map((file, i) => {
|
||||||
<span className="text-muted-foreground shrink-0 ml-1">
|
const isSelected = i === selectedIndex;
|
||||||
{formatFileSize(selectedFileSize ?? files[0].size)}
|
return (
|
||||||
</span>
|
<button
|
||||||
|
key={`${file.name}-${i}`}
|
||||||
|
type="button"
|
||||||
|
onClick={() => onSelect(i)}
|
||||||
|
className={`w-full flex items-center gap-1.5 text-xs rounded px-2 py-1.5 text-left transition-colors ${isSelected ? "bg-primary/10 text-foreground" : "text-muted-foreground hover:bg-muted"}`}
|
||||||
|
>
|
||||||
|
{isSelected && <CheckCircle2 className="h-3 w-3 text-primary shrink-0" />}
|
||||||
|
<span className="truncate flex-1 min-w-0">{file.name}</span>
|
||||||
|
<span className="shrink-0 text-[10px] text-muted-foreground/70">
|
||||||
|
{getFileFormat(file.name)}
|
||||||
|
</span>
|
||||||
|
<span className="shrink-0 text-[10px] tabular-nums">{formatFileSize(file.size)}</span>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{showToggle && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setExpanded(!expanded)}
|
||||||
|
className="text-xs text-primary hover:text-primary/80"
|
||||||
|
>
|
||||||
|
{expanded ? "Show less" : `Show ${files.length - COLLAPSED_LIMIT} more`}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onClear}
|
onClick={onClear}
|
||||||
@@ -609,8 +646,8 @@ export function ToolPage() {
|
|||||||
<h3 className="text-sm font-medium text-muted-foreground">Files</h3>
|
<h3 className="text-sm font-medium text-muted-foreground">Files</h3>
|
||||||
<FileSelectionInfo
|
<FileSelectionInfo
|
||||||
files={files}
|
files={files}
|
||||||
selectedFileName={selectedFileName}
|
selectedIndex={selectedIndex}
|
||||||
selectedFileSize={selectedFileSize}
|
onSelect={setSelectedIndex}
|
||||||
onClear={reset}
|
onClear={reset}
|
||||||
onAddMore={handleAddMore}
|
onAddMore={handleAddMore}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user