ultisuite-client/lib/demo/demo-drive-preview.ts
R3D347HR4Y ad1370ea7e
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat: enhance configuration and add new demo layouts
- Introduced turbopack alias for canvas in next.config.mjs.
- Updated package.json scripts for development and branding tasks.
- Added new dependencies for Tiptap extensions.
- Implemented new demo layouts for agenda, contacts, drive, and mail applications.
- Enhanced globals.css for improved theming and splash screen animations.
- Added OAuth callback handling for drive mounts.
- Updated layout components to integrate new demo shells and improve structure.
2026-06-12 19:10:24 +02:00

115 lines
4.1 KiB
TypeScript

import type { DriveFileInfo } from "@/lib/api/types"
import { drivePreviewKind, isSvgFile } from "@/lib/drive/drive-preview"
export type DemoDrivePreviewResult =
| { type: "url"; url: string; display: "image" }
| { type: "text"; content: string }
| { type: "svg"; markup: string }
function demoSeed(file: { path: string; file_id?: number }): string {
return file.file_id ? `ultimail-drive-${file.file_id}` : `ultimail-drive-${file.path}`
}
/** Stable Picsum URL for demo raster previews / thumbnails. */
export function demoDrivePicsumUrl(
file: { path: string; file_id?: number },
width = 400,
height = 300
): string {
return `https://picsum.photos/seed/${encodeURIComponent(demoSeed(file))}/${width}/${height}`
}
const DEMO_TEXT_BY_PATH: Record<string, string> = {
"/Perso/Notes réunion.txt": `# Notes réunion — 9 juin
- Roadmap Q3 validée en comité
- Beta agenda : livraison cible vendredi
- Design system : tokens couleur à figer
- Prochaine démo interne jeudi 11h`,
"/Release notes v2.3.txt": `# Ultimail v2.3
## Nouveautés
- UltiAgenda : visio UltiMeet intégrée aux événements
- UltiDrive : favoris et corbeille unifiés
- Contacts : fusion et labels personnalisés
## Corrections
- Sync calendrier CalDAV sur événements récurrents
- Aperçu PDF plus rapide sur gros fichiers`,
}
function demoGenericText(name: string): string {
return `# ${name.replace(/\.[^.]+$/, "")}
Contenu de démonstration — fichier fictif pour la landing page Ultimail.`
}
function demoDriveSvgMarkup(name: string): string {
const title = name.replace(/\.svg$/i, "")
const isLogo = /logo/i.test(name)
if (isLogo) {
return `<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 80" role="img">
<rect width="320" height="80" rx="12" fill="#f1f3f4"/>
<circle cx="40" cy="40" r="22" fill="#1967d2"/>
<text x="40" y="46" text-anchor="middle" fill="#fff" font-family="system-ui,sans-serif" font-size="18" font-weight="700">U</text>
<text x="78" y="48" fill="#202124" font-family="system-ui,sans-serif" font-size="22" font-weight="600">${title}</text>
</svg>`
}
return `<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" role="img">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#e8f0fe"/>
<stop offset="100%" stop-color="#fce8e6"/>
</linearGradient>
</defs>
<rect width="640" height="360" fill="url(#bg)"/>
<rect x="48" y="48" width="140" height="72" rx="8" fill="#1967d2" opacity="0.9"/>
<rect x="220" y="48" width="140" height="72" rx="8" fill="#34a853" opacity="0.9"/>
<rect x="392" y="48" width="200" height="72" rx="8" fill="#fbbc04" opacity="0.9"/>
<rect x="120" y="160" width="400" height="56" rx="8" fill="#fff" stroke="#dadce0"/>
<rect x="180" y="248" width="280" height="56" rx="8" fill="#fff" stroke="#dadce0"/>
<text x="320" y="28" text-anchor="middle" fill="#5f6368" font-family="system-ui,sans-serif" font-size="14">${title}</text>
</svg>`
}
/** Resolve a demo preview without hitting the API. */
export function resolveDemoDrivePreview(
file: Pick<DriveFileInfo, "path" | "name" | "mime_type" | "file_id">,
size?: { width: number; height: number }
): DemoDrivePreviewResult | null {
const width = size?.width ?? 1200
const height = size?.height ?? 900
if (isSvgFile(file)) {
return { type: "svg", markup: demoDriveSvgMarkup(file.name) }
}
const kind = drivePreviewKind(file)
if (kind === "text") {
return {
type: "text",
content: DEMO_TEXT_BY_PATH[file.path] ?? demoGenericText(file.name),
}
}
if (kind === "image" || kind === "pdf") {
return { type: "url", url: demoDrivePicsumUrl(file, width, height), display: "image" }
}
// Office / bureautique : vignette Picsum (pas de binaire réel en démo).
const mime = (file.mime_type ?? "").toLowerCase()
if (
mime.includes("officedocument") ||
mime.includes("spreadsheet") ||
mime.includes("presentation") ||
mime.includes("msword")
) {
return { type: "url", url: demoDrivePicsumUrl(file, width, height), display: "image" }
}
return null
}