From c6db63d183f86693a80566be764a206351c2d948 Mon Sep 17 00:00:00 2001 From: grnd-alt Date: Mon, 2 Dec 2024 21:50:27 +0100 Subject: [PATCH] feat(fileuploads): download files when element clicked Signed-off-by: grnd-alt --- src/files/files.ts | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/files/files.ts b/src/files/files.ts index e2f670a..c23a2c7 100644 --- a/src/files/files.ts +++ b/src/files/files.ts @@ -5,7 +5,7 @@ import type { ExcalidrawImperativeAPI, } from '@excalidraw/excalidraw/types/types' import { Collab } from '../collaboration/collab' -import type { FileId } from '@excalidraw/excalidraw/types/element/types' +import type { ExcalidrawElement, FileId } from '@excalidraw/excalidraw/types/element/types' export class FileHandle { private collab: Collab @@ -34,7 +34,33 @@ export class FileHandle { this.filesDragEventListener(ev, excalidrawApi), ) } - this.excalidrawApi.onPointerDown((tool, state, event) => { + this.excalidrawApi.onPointerDown((_, state, __) => { + const clickedElement = this.getElementAt(state.lastCoords.x, state.lastCoords.y) + if (!clickedElement) { + return + } + this.downloadFile(clickedElement.customData?.meta) + }) + } + + private downloadFile(meta: any) { + const blob = new Blob([meta.dataurl], { type: meta.type }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = meta.name + a.click() + URL.revokeObjectURL(url) + } + + private getElementAt(px: number, py: number): ExcalidrawElement | undefined { + const elements = this.excalidrawApi.getSceneElements() + return elements.find((element) => { + const { x, y, width, height } = element + return ( + px >= x && px <= x + width && + py >= y && py <= y + height + ) }) } @@ -62,11 +88,14 @@ export class FileHandle { id: (Math.random() + 1).toString(36).substring(7) as FileId, dataURL: fr.result as DataURL, } - this.addCustomFileElement(constructedFile, file.name) + let meta = { + name: file.name, type: file.type, lastModified: file.lastModified, dataurl: fr.result + } + this.addCustomFileElement(constructedFile, meta) } } - private addCustomFileElement(constructedFile: BinaryFileData, filename: string) { + private addCustomFileElement(constructedFile: BinaryFileData, meta: any) { this.collab.addFile(constructedFile) const elements = this.excalidrawApi .getSceneElementsIncludingDeleted() @@ -74,8 +103,8 @@ export class FileHandle { const newElements = convertToExcalidrawElements([ { type: 'text', - text: filename, - customData: { filedata: { constructedFile } }, + text: meta.name, + customData: { meta: meta }, groupIds: ['1'], y: 0, x: 0, @@ -83,6 +112,7 @@ export class FileHandle { { type: 'image', fileId: 'placeholder_image' as FileId, + customData: { meta: meta }, groupIds: ['1'], y: 0, x: 0,