/** * Full-window upload progress over the files tree: a blurred scrim (same mask * token as the repo's Modal primitive) with a card showing the target * directory, file-level progress, and a cancel button. Esc cancels too — * clicking the scrim does not, so a stray click can never abort an upload. * Rendered inside TreePanel (absolute inset-0), so it covers only the file * window and never the conversation column. */ import { useEffect, type ReactNode } from 'react' import { IconUploadOutline16 } from './icons.tsx' import { t } from './locales.ts' import { uploadHintText } from './upload.ts' import css from './sidebar.module.css' export function UploadOverlay(props: { /** Absolute upload directory (the session workspace or a tree directory). */ dir: string done: number total: number /** Relative path of the file being uploaded ('' when none is in flight). */ current: string onCancel: () => void /** True while cancellation is in flight (disables the cancel button). */ cancelling?: boolean }): ReactNode { const { dir, done, total, current, onCancel, cancelling } = props // Esc cancels (MermaidModal-style native listener; the overlay is not a // focus-trapped dialog, so a window listener is the honest scope). useEffect(() => { const onKey = (event: KeyboardEvent): void => { if (event.key === 'Escape') onCancel() } window.addEventListener('keydown', onKey) return () => { window.removeEventListener('keydown', onKey) } }, [onCancel]) const percent = total === 0 ? 0 : Math.min(100, Math.round((done / total) * 100)) return (
{t('uploadingTo', { dir })}
{uploadHintText(done, total, current, dir, t)}
) }