Skip to content

Commit

Permalink
Bc 6591 unsupported file type error (#70)
Browse files Browse the repository at this point in the history
* BC-6593-Correct type display in upload dialog

* fix

* fix

* fix openAsset

* fix openAsset

* fix openAsset

* fix comments

* fix comments

* fix comment

* delete keyof

* fix comments

* fix prettier

* fix proxy

* delete split

* BC-6591-Unsupported file type error

* delete import

* fix conflicts

* rewriting tldraw functions

* fix import

* fix imports

* fix imports

* Test function

* Test function

* Testing upload

* move func

* fix errors

* Testing 1

* Delete loading

* Testing 2

* Testing 3

* Testing 4

* restore main

* overwrite and fix tldraw file upload methods

* Add check

* fix

* Show console.error

* Delete symbol

---------

Co-authored-by: Artemida <Artemida>
Co-authored-by: davwas <[email protected]>
  • Loading branch information
VikDavydiuk and davwas authored Apr 5, 2024
1 parent 4445fd1 commit 8388870
Show file tree
Hide file tree
Showing 12 changed files with 291 additions and 51 deletions.
21 changes: 11 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
"@mdi/react": "^1.6.1",
"@tldraw/core": "^1.23.2",
"@tldraw/tldraw": "^1.29.2",
"@tldraw/vec": "^1.9.2",
"@y-presence/client": "^2.0.1",
"browser-fs-access": "^0.35.0",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-cookie": "^6.1.3",
"react-dom": "^18.2.0",
"react-toastify": "^9.1.3",
"react-toastify": "^10.0.5",
"y-websocket": "^1.5.3",
"yjs": "^13.6.11"
},
Expand Down
1 change: 0 additions & 1 deletion src/configuration/index.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/guards/index.ts

This file was deleted.

170 changes: 168 additions & 2 deletions src/hooks/useMultiplayerState.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import lodash from "lodash";
import {
TDAsset,
TDAssetType,
TDBinding,
TDExport,
TDShape,
TDShapeType,
TDUser,
TLDR,
TldrawApp,
TldrawPatch,
} from "@tldraw/tldraw";
Expand All @@ -27,11 +30,24 @@ import { UserPresence } from "../types/UserPresence";
import {
importAssetsToS3,
openFromFileSystem,
openAssetsFromFileSystem,
} from "../utils/boardImportUtils";
import { saveToFileSystem } from "../utils/boardExportUtils";
import {
fileToBase64,
fileToText,
saveToFileSystem,
} from "../utils/boardExportUtils";
import { uploadFileToStorage } from "../utils/fileUpload";
import { getImageBlob } from "../utils/tldrawImageExportUtils";
import { Utils } from "@tldraw/core";
import {
getImageSizeFromSrc,
getVideoSizeFromSrc,
getViewboxFromSVG,
IMAGE_EXTENSIONS,
openAssetsFromFileSystem,
VIDEO_EXTENSIONS,
} from "../utils/tldrawFileUploadUtils";
import { Vec } from "@tldraw/vec";

declare const window: Window & { app: TldrawApp };

Expand Down Expand Up @@ -105,6 +121,156 @@ export function useMultiplayerState({

// below functions are overwriting the original tldraw implementations
// some of them had to be changed/fixed to support additional functionality
app.addMediaFromFiles = async (files, point) => {
app.setIsLoading(true);

const shapesToCreate: TDShape[] = [];
const pointArr = point ?? app.centerPoint;
const pagePoint = app.getPagePoint(pointArr);

for (const file of files) {
try {
const id = Utils.uniqueId();
const extension = file.name.match(/\.[0-9a-z]+$/i);

if (!extension) {
toast.info("Asset of this type is not allowed");
continue;
}

const isImage = IMAGE_EXTENSIONS.includes(
extension[0].toLowerCase(),
);
const isVideo = VIDEO_EXTENSIONS.includes(
extension[0].toLowerCase(),
);

if (!(isImage || isVideo)) {
toast.info("Asset of this type is not allowed");
continue;
}

const shapeType = isImage ? TDShapeType.Image : TDShapeType.Video;
const assetType = isImage ? TDAssetType.Image : TDAssetType.Video;

let src: string | ArrayBuffer | null;

if (app.callbacks.onAssetCreate) {
const result = await app.callbacks.onAssetCreate(app, file, id);

if (!result)
throw Error("Asset creation callback returned false");

src = result;
} else {
src = await fileToBase64(file);
}

if (typeof src === "string") {
let size = [0, 0];

if (isImage) {
// attempt to get actual svg size from viewBox attribute as
if (extension[0] == ".svg") {
let viewBox: string[];
const svgString = await fileToText(file);
const viewBoxAttribute = getViewboxFromSVG(app, svgString);

if (viewBoxAttribute) {
viewBox = viewBoxAttribute.split(" ");
size[0] = parseFloat(viewBox[2]);
size[1] = parseFloat(viewBox[3]);
}
}
if (Vec.isEqual(size, [0, 0])) {
size = await getImageSizeFromSrc(src);
}
} else {
size = await getVideoSizeFromSrc(src);
}

const match = Object.values(app.document.assets).find(
(asset) => asset.type === assetType && asset.src === src,
);

let assetId: string;

if (!match) {
assetId = id;

const asset = {
id: assetId,
type: assetType,
name: file.name,
src,
size,
};

app.patchState({
document: {
assets: {
[assetId]: asset,
},
},
});
} else {
assetId = match.id;
}

shapesToCreate.push(
app.getImageOrVideoShapeAtPoint(
id,
shapeType,
pointArr,
size,
assetId,
),
);
}
} catch (error) {
console.error("An error occurred while uploading asset", error);
}
}

if (shapesToCreate.length) {
const currentPoint = Vec.add(pagePoint, [0, 0]);

shapesToCreate.forEach((shape, i) => {
const bounds = TLDR.getBounds(shape);

if (i === 0) {
// For the first shape, offset the current point so
// that the first shape's center is at the page point
currentPoint[0] -= bounds.width / 2;
currentPoint[1] -= bounds.height / 2;
}

// Set the shape's point the current point
shape.point = [...currentPoint];

// Then bump the page current point by this shape's width
currentPoint[0] += bounds.width;
});

const commonBounds = Utils.getCommonBounds(
shapesToCreate.map(TLDR.getBounds),
);

app.createShapes(...shapesToCreate);

// Are the common bounds too big for the viewport?
if (!Utils.boundsContain(app.viewport, commonBounds)) {
app.zoomToSelection();
if (app.zoom > 1) {
app.resetZoom();
}
}
}

app.setIsLoading(false);
return app;
};

app.saveProjectAs = async (filename) => {
await onSaveAs(app, filename);
return app;
Expand Down
4 changes: 2 additions & 2 deletions src/mapper/configuration.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Envs } from "../types";
import { TypeGuard } from "../guards";
import { Envs } from "../types/Envs";
import { TypeGuard } from "../guards/type.guard";

const checkEnvType = (obj: Record<string, unknown>): void => {
TypeGuard.checkKeyAndValueExists(obj, "FEATURE_TLDRAW_ENABLED");
Expand Down
1 change: 0 additions & 1 deletion src/mapper/index.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/types/index.ts

This file was deleted.

14 changes: 13 additions & 1 deletion src/utils/boardExportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,16 @@ const fileToBase64 = (file: Blob): Promise<string | ArrayBuffer | null> => {
});
};

export { saveToFileSystem };
const fileToText = (file: Blob): Promise<string | ArrayBuffer | null> => {
return new Promise((resolve, reject) => {
if (file) {
const reader = new FileReader();
reader.readAsText(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
reader.onabort = (error) => reject(error);
}
});
};

export { saveToFileSystem, fileToBase64, fileToText };
27 changes: 1 addition & 26 deletions src/utils/boardImportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { TDAsset, TDDocument, TDFile } from "@tldraw/tldraw";
import { fileOpen } from "browser-fs-access";
import { toast } from "react-toastify";
import { API } from "../configuration/api/api.configuration";
import { envs } from "../stores/setup";

const openFromFileSystem = async (): Promise<null | {
fileHandle: FileSystemFileHandle | null;
Expand Down Expand Up @@ -104,28 +103,4 @@ const uploadAction = (
return promise;
};

const fileMimeExtensions: { [key: string]: string[] } = {
"image/jpeg": [".jpg", ".jpeg"],
"image/png": [".png"],
"image/svg+xml": [".svg"],
"image/gif": [".gif"],
};

const allowedMimeTypes = envs?.TLDRAW__ASSETS_ALLOWED_MIME_TYPES_LIST || [];

const openAssetsFromFileSystem = async () => {
const extensions = allowedMimeTypes.flatMap(
(mimeType) => fileMimeExtensions[mimeType] || [],
);
// NOTE: The extensions here are selected based on the MIME types allowed by TLDRAW,
// taking into account additional extension checks performed internally by TLDRAW.

const result = await fileOpen({
description: "Image",
extensions: extensions,
multiple: true,
});
return result;
};

export { openFromFileSystem, importAssetsToS3, openAssetsFromFileSystem };
export { openFromFileSystem, importAssetsToS3 };
8 changes: 4 additions & 4 deletions src/utils/envConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Envs } from "../types";
import { API } from "../configuration";
import { ConfigurationMapper } from "../mapper";
import { HttpGuard } from "../guards";
import { Envs } from "../types/Envs";
import { API } from "../configuration/api/api.configuration";
import { ConfigurationMapper } from "../mapper/configuration.mapper";
import { HttpGuard } from "../guards/http.guard";

// the try catch should not part of getEnvs, the place that use it must handle the errors
// should be part of a store
Expand Down
Loading

0 comments on commit 8388870

Please sign in to comment.