feat: delta/instant upload + frontend UI/UX polish
Bundles the backend+frontend delta-upload (content-dedup) feature with a batch of frontend fixes from this session. Upload / dedup: - Client-hashed delta & instant upload (deltaUpload, hashWasm vendor shim) - Backend dedup batch endpoint (dedup_service, dedup_handler, routes) - session store owned-hash helpers; unit tests + upload-strategy bench Frontend UI/UX: - Colour file-type icons in grid/list (per-type tinted tiles + glyph hue) - Robust thumbnail fallback; PDFs now show their type icon (backend generates no PDF thumbnails) instead of a blank tile - Fix PDF preview: load via a same-origin blob: iframe — the API URL is blocked by the global X-Frame-Options: DENY in the browser's framed PDF viewer, matching the existing CSP `frame-src blob:` design - Groups: localized virtual-group description (no DB schema-note leak), add nav.groups to the 15 missing locales, fix primary-button contrast - Repoint --color-text-light → --color-on-accent (was faint grey on accent) - Nudge the admin role badge off the user-menu header divider Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,50 @@ export function iconNameFromClass(iconClass: string | undefined | null): string
|
||||
return token ? token.slice(3) : 'file';
|
||||
}
|
||||
|
||||
/**
|
||||
* Coarse colour bucket for a resolved icon name (see {@link iconNameFromClass}).
|
||||
* One hue per broad file family so the grid/list glyphs render in type-specific
|
||||
* colours instead of a flat monochrome. Each bucket is backed by a
|
||||
* `--file-kind-*` token (variables.css) and consumed via the `.file-icon--*`
|
||||
* modifier classes (resourceList.css).
|
||||
*/
|
||||
export function fileIconKind(iconName: string): string {
|
||||
switch (iconName) {
|
||||
case 'folder':
|
||||
case 'folder-open':
|
||||
return 'folder';
|
||||
case 'file-pdf':
|
||||
return 'pdf';
|
||||
case 'file-word':
|
||||
return 'doc';
|
||||
case 'file-excel':
|
||||
return 'sheet';
|
||||
case 'file-powerpoint':
|
||||
return 'slides';
|
||||
case 'file-archive':
|
||||
case 'file-zipper':
|
||||
return 'archive';
|
||||
case 'file-code':
|
||||
return 'code';
|
||||
case 'file-image':
|
||||
return 'image';
|
||||
case 'file-video':
|
||||
return 'video';
|
||||
case 'file-audio':
|
||||
return 'audio';
|
||||
case 'file-alt':
|
||||
case 'file-lines':
|
||||
return 'text';
|
||||
default:
|
||||
return 'generic';
|
||||
}
|
||||
}
|
||||
|
||||
/** `.file-icon` colour-bucket modifier class for a resolved icon name. */
|
||||
export function fileIconKindClass(iconName: string): string {
|
||||
return `file-icon--${fileIconKind(iconName)}`;
|
||||
}
|
||||
|
||||
/** Format a timestamp (epoch seconds/ms or ISO-8601 string) as a local date. */
|
||||
export function formatDate(value: number | string | null | undefined): string {
|
||||
if (value === null || value === undefined) return '';
|
||||
|
||||
Reference in New Issue
Block a user