86 lines
2.7 KiB
TypeScript
86 lines
2.7 KiB
TypeScript
import { apiClient } from "@/lib/api/client"
|
|
import { fetchDrivePreviewBlob } from "@/lib/api/drive-download"
|
|
import type { DriveFileInfo } from "@/lib/api/types"
|
|
|
|
export async function resolveDriveDrawFileId(file: DriveFileInfo): Promise<string> {
|
|
let fileId = file.file_id
|
|
if (!fileId) {
|
|
const info = await apiClient.get<DriveFileInfo>(
|
|
`/drive/files/info${file.path.startsWith("/") ? file.path : `/${file.path}`}`
|
|
)
|
|
fileId = info.file_id
|
|
}
|
|
if (!fileId) {
|
|
throw new Error("Identifiant du dessin introuvable")
|
|
}
|
|
return String(fileId)
|
|
}
|
|
|
|
function readSvgDimensions(svg: SVGSVGElement): { width: number; height: number } {
|
|
const viewBox = svg.getAttribute("viewBox")
|
|
if (viewBox) {
|
|
const parts = viewBox.split(/\s+/).map(Number)
|
|
if (parts.length === 4 && parts.every((n) => Number.isFinite(n))) {
|
|
return {
|
|
width: Math.max(24, Math.round(parts[2])),
|
|
height: Math.max(24, Math.round(parts[3])),
|
|
}
|
|
}
|
|
}
|
|
const width = Number(svg.getAttribute("width"))
|
|
const height = Number(svg.getAttribute("height"))
|
|
if (Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0) {
|
|
return { width: Math.round(width), height: Math.round(height) }
|
|
}
|
|
return { width: 320, height: 240 }
|
|
}
|
|
|
|
/** Load an UltiDraw file from Drive and build embedded graphic attrs. */
|
|
export async function importExcalidrawFromDriveFile(file: DriveFileInfo): Promise<{
|
|
drawScene: string
|
|
src: string
|
|
width: number
|
|
height: number
|
|
drawDriveFileId: string
|
|
alt: string
|
|
}> {
|
|
const blob = await fetchDrivePreviewBlob(file)
|
|
const text = await blob.text()
|
|
const data = JSON.parse(text) as {
|
|
elements?: Parameters<
|
|
Awaited<typeof import("@excalidraw/excalidraw")>["restoreElements"]
|
|
>[0]
|
|
appState?: Record<string, unknown>
|
|
files?: Record<string, unknown>
|
|
}
|
|
|
|
const { restoreElements, restoreAppState, exportToSvg, serializeAsJSON } = await import(
|
|
"@excalidraw/excalidraw"
|
|
)
|
|
|
|
const elements = restoreElements(data.elements ?? [], null)
|
|
const appState = restoreAppState(data.appState ?? {}, null)
|
|
const files = (data.files ?? {}) as import("@excalidraw/excalidraw/types").BinaryFiles
|
|
|
|
const drawScene = serializeAsJSON(elements, appState, files, "local")
|
|
const svg = await exportToSvg({
|
|
elements,
|
|
appState,
|
|
files,
|
|
skipInliningFonts: true,
|
|
})
|
|
const svgString = new XMLSerializer().serializeToString(svg)
|
|
const src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}`
|
|
const { width, height } = readSvgDimensions(svg)
|
|
const drawDriveFileId = await resolveDriveDrawFileId(file)
|
|
|
|
return {
|
|
drawScene,
|
|
src,
|
|
width,
|
|
height,
|
|
drawDriveFileId,
|
|
alt: file.name,
|
|
}
|
|
}
|