Spaces:
Running
Running
File size: 2,526 Bytes
e327f0d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | /**
* WindowFileDrop — relays Tauri window-level file-drop events to the page.
*
* When the user drags files from the OS file manager onto the window, Tauri
* emits a `tauri://drag-drop` event with the absolute paths. We re-emit a
* DOM-level `hasarui:files-dropped` event carrying File objects so individual
* pages (BatchUploader, InspectPage) can handle it without each subscribing
* to a Tauri event.
*/
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { getCurrentWindow } from '@tauri-apps/api/window';
import { pathToFile } from '@/lib/commands';
import { MAX_FILE_SIZE_MB } from '@/lib/file-picker';
const IMAGE_EXT = /\.(jpe?g|png|webp)$/i;
const MAX_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;
const isTauri = () => typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window;
export function WindowFileDrop() {
const navigate = useNavigate();
useEffect(() => {
if (!isTauri()) return;
const w = getCurrentWindow();
let unlisten: (() => void) | null = null;
(async () => {
unlisten = await w.onDragDropEvent(async (e) => {
const payload = e.payload as { type: string; paths?: string[] };
if (payload.type !== 'drop' || !payload.paths) return;
const paths = payload.paths.filter((p) => IMAGE_EXT.test(p));
if (paths.length === 0) return;
try {
const all = await Promise.all(paths.map((p) => pathToFile(p)));
const files = all.filter((f) => f.size <= MAX_BYTES);
const rejected = all
.filter((f) => f.size > MAX_BYTES)
.map((f) => ({ name: f.name, size: f.size }));
if (rejected.length) {
window.dispatchEvent(
new CustomEvent('hasarui:file-size-rejected', {
detail: { rejected, maxMb: MAX_FILE_SIZE_MB },
}),
);
}
if (!files.length) return;
window.dispatchEvent(
new CustomEvent('hasarui:files-dropped', { detail: { files } }),
);
// If we're not on inspect/batch, route to inspect for convenience.
const loc = window.location.pathname;
if (!loc.startsWith('/inspect') && !loc.startsWith('/batch')) {
navigate(files.length > 5 ? '/batch' : '/inspect');
}
} catch (err) {
console.warn('Window drop failed:', err);
}
});
})();
return () => unlisten?.();
}, [navigate]);
return null;
}
export default WindowFileDrop;
|