feat: upload button in AppShell sidebar — click or drag to upload screenshots
- Dashed border button at bottom of sidebar nav - Click to open file picker - Drag files onto the bottom rail area to upload - Shows "Uploading..." then "Saved!" for 2 seconds - Files save to platform/screenshots/ with timestamp names - Works from any page in the Atelier shell Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,6 @@
|
|||||||
CircleDot,
|
CircleDot,
|
||||||
Compass,
|
Compass,
|
||||||
Dumbbell,
|
Dumbbell,
|
||||||
FolderOpen,
|
|
||||||
Landmark,
|
Landmark,
|
||||||
LibraryBig,
|
LibraryBig,
|
||||||
Menu,
|
Menu,
|
||||||
@@ -16,7 +15,7 @@
|
|||||||
Search,
|
Search,
|
||||||
Settings2,
|
Settings2,
|
||||||
SquareCheckBig,
|
SquareCheckBig,
|
||||||
Tag,
|
Upload,
|
||||||
X
|
X
|
||||||
} from '@lucide/svelte';
|
} from '@lucide/svelte';
|
||||||
|
|
||||||
@@ -52,6 +51,33 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mobileNavOpen = $state(false);
|
let mobileNavOpen = $state(false);
|
||||||
|
let uploadInput: HTMLInputElement;
|
||||||
|
let uploadStatus = $state<'' | 'uploading' | 'done'>('');
|
||||||
|
|
||||||
|
async function handleUpload(file: File) {
|
||||||
|
uploadStatus = 'uploading';
|
||||||
|
const fd = new FormData();
|
||||||
|
fd.append('file', file);
|
||||||
|
try {
|
||||||
|
await fetch('/upload', { method: 'POST', body: fd, credentials: 'include' });
|
||||||
|
uploadStatus = 'done';
|
||||||
|
setTimeout(() => uploadStatus = '', 2000);
|
||||||
|
} catch {
|
||||||
|
uploadStatus = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onUploadInput(e: Event) {
|
||||||
|
const input = e.target as HTMLInputElement;
|
||||||
|
if (input.files?.[0]) handleUpload(input.files[0]);
|
||||||
|
input.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRailDrop(e: DragEvent) {
|
||||||
|
e.preventDefault();
|
||||||
|
const file = e.dataTransfer?.files[0];
|
||||||
|
if (file) handleUpload(file);
|
||||||
|
}
|
||||||
|
|
||||||
// Brain sidebar sub-items
|
// Brain sidebar sub-items
|
||||||
interface BrainFolder { id: string; name: string; item_count: number; }
|
interface BrainFolder { id: string; name: string; item_count: number; }
|
||||||
@@ -116,7 +142,13 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rail-bottom">
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
|
<div class="rail-bottom" ondragover={(e) => e.preventDefault()} ondrop={onRailDrop}>
|
||||||
|
<button class="rail-upload" onclick={() => uploadInput?.click()}>
|
||||||
|
<Upload size={14} strokeWidth={1.8} />
|
||||||
|
<span>{uploadStatus === 'uploading' ? 'Uploading...' : uploadStatus === 'done' ? 'Saved!' : 'Upload screenshot'}</span>
|
||||||
|
</button>
|
||||||
|
<input bind:this={uploadInput} type="file" accept="image/*,.pdf" onchange={onUploadInput} hidden />
|
||||||
<div class="rail-date">
|
<div class="rail-date">
|
||||||
<CalendarDays size={14} strokeWidth={1.8} />
|
<CalendarDays size={14} strokeWidth={1.8} />
|
||||||
<span>{new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric' }).format(new Date())}</span>
|
<span>{new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric' }).format(new Date())}</span>
|
||||||
@@ -383,6 +415,26 @@
|
|||||||
border-top: 1px solid var(--shell-line);
|
border-top: 1px solid var(--shell-line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rail-upload {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 9px 12px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px dashed var(--shell-line);
|
||||||
|
background: none;
|
||||||
|
color: var(--shell-muted);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-family: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 160ms;
|
||||||
|
}
|
||||||
|
.rail-upload:hover {
|
||||||
|
border-color: var(--shell-ink);
|
||||||
|
color: var(--shell-ink);
|
||||||
|
background: rgba(255,255,255,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
.rail-date {
|
.rail-date {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user