diff --git a/excalidraw-app/app_constants.ts b/excalidraw-app/app_constants.ts index c73c5ee8..26797e03 100644 --- a/excalidraw-app/app_constants.ts +++ b/excalidraw-app/app_constants.ts @@ -29,8 +29,8 @@ export enum WS_SUBTYPES { } export const FIREBASE_STORAGE_PREFIXES = { - shareLinkFiles: `/files/shareLinks`, - collabFiles: `/files/rooms`, + shareLinkFiles: `shareLinks`, + collabFiles: `rooms`, }; export const ROOM_ID_BYTES = 10; diff --git a/excalidraw-app/collab/Collab.tsx b/excalidraw-app/collab/Collab.tsx index 7059a67c..840f24b9 100644 --- a/excalidraw-app/collab/Collab.tsx +++ b/excalidraw-app/collab/Collab.tsx @@ -29,7 +29,6 @@ import { import { CURSOR_SYNC_TIMEOUT, FILE_UPLOAD_MAX_BYTES, - FIREBASE_STORAGE_PREFIXES, INITIAL_SCENE_UPDATE_TIMEOUT, LOAD_IMAGES_TIMEOUT, WS_SUBTYPES, @@ -149,7 +148,7 @@ class Collab extends PureComponent { throw new AbortError(); } - return loadFilesFromFirebase(`files/rooms/${roomId}`, roomKey, fileIds); + return loadFilesFromFirebase(roomId, roomKey, fileIds); }, saveFiles: async ({ addedFiles }) => { const { roomId, roomKey } = this.portal; @@ -158,7 +157,7 @@ class Collab extends PureComponent { } return saveFilesToFirebase({ - prefix: `${FIREBASE_STORAGE_PREFIXES.collabFiles}/${roomId}`, + prefix: roomId, files: await encodeFilesForUpload({ files: addedFiles, encryptionKey: roomKey, diff --git a/excalidraw-app/data/firebase.ts b/excalidraw-app/data/firebase.ts index 12967633..afb0f9fb 100644 --- a/excalidraw-app/data/firebase.ts +++ b/excalidraw-app/data/firebase.ts @@ -13,7 +13,6 @@ import type { BinaryFileMetadata, DataURL, } from "../../packages/excalidraw/types"; -import { FILE_CACHE_MAX_AGE_SEC } from "../app_constants"; import { decompressData } from "../../packages/excalidraw/data/encode"; import { encryptData, @@ -31,72 +30,8 @@ import type { RemoteExcalidrawElement } from "../../packages/excalidraw/data/rec const STORAGE_SERVER_URL = import.meta.env.VITE_APP_WS_SERVER_URL; -let FIREBASE_CONFIG: Record; -try { - FIREBASE_CONFIG = JSON.parse(import.meta.env.VITE_APP_FIREBASE_CONFIG); -} catch (error: any) { - console.warn( - `Error JSON parsing firebase config. Supplied value: ${ - import.meta.env.VITE_APP_FIREBASE_CONFIG - }`, - ); - FIREBASE_CONFIG = {}; -} - -let firebasePromise: Promise | null = - null; -let firebaseStoragePromise: Promise | null | true = null; - -let isFirebaseInitialized = false; - -const _loadFirebase = async () => { - const firebase = ( - await import(/* webpackChunkName: "firebase" */ "firebase/app") - ).default; - - if (!isFirebaseInitialized) { - try { - firebase.initializeApp(FIREBASE_CONFIG); - } catch (error: any) { - // trying initialize again throws. Usually this is harmless, and happens - // mainly in dev (HMR) - if (error.code === "app/duplicate-app") { - console.warn(error.name, error.code); - } else { - throw error; - } - } - isFirebaseInitialized = true; - } - - return firebase; -}; - -const _getFirebase = async (): Promise< - typeof import("firebase/app").default -> => { - if (!firebasePromise) { - firebasePromise = _loadFirebase(); - } - return firebasePromise; -}; - // ----------------------------------------------------------------------------- -export const loadFirebaseStorage = async () => { - const firebase = await _getFirebase(); - if (!firebaseStoragePromise) { - firebaseStoragePromise = import( - /* webpackChunkName: "storage" */ "firebase/storage" - ); - } - if (firebaseStoragePromise !== true) { - await firebaseStoragePromise; - firebaseStoragePromise = true; - } - return firebase; -}; - interface StoredScene { sceneVersion: number; iv: ArrayBuffer; @@ -162,25 +97,21 @@ export const saveFilesToFirebase = async ({ prefix: string; files: { id: FileId; buffer: Uint8Array }[]; }) => { - const firebase = await loadFirebaseStorage(); - const erroredFiles = new Map(); const savedFiles = new Map(); await Promise.all( files.map(async ({ id, buffer }) => { try { - await firebase - .storage() - .ref(`${prefix}/${id}`) - .put( - new Blob([buffer], { - type: MIME_TYPES.binary, - }), - { - cacheControl: `public, max-age=${FILE_CACHE_MAX_AGE_SEC}`, - }, - ); + await fetch(`${STORAGE_SERVER_URL}/file/${prefix}/${id}`, { + method: "PUT", + headers: { + ETag: id, + // "If-Match": id, + "Content-Type": MIME_TYPES.binary, + }, + body: buffer, + }); savedFiles.set(id, true); } catch (error: any) { erroredFiles.set(id, true); @@ -248,7 +179,7 @@ export const saveToFirebase = async ( headers: { ETag: storedScene.sceneVersion.toString(), "If-Match": prevHash.toString(), - "Content-Type": "application/octet-stream", + "Content-Type": MIME_TYPES.binary, }, body, }); @@ -268,9 +199,7 @@ export const loadFromFirebase = async ( roomKey: string, socket: Socket | null, ): Promise => { - const resp = await fetch(`${STORAGE_SERVER_URL}/scene/${roomId}`, { - method: "GET", - }); + const resp = await fetch(`${STORAGE_SERVER_URL}/scene/${roomId}`); if (resp.status === 404) { return null; @@ -305,10 +234,9 @@ export const loadFilesFromFirebase = async ( await Promise.all( [...new Set(filesIds)].map(async (id) => { try { - const url = `https://firebasestorage.googleapis.com/v0/b/${ - FIREBASE_CONFIG.storageBucket - }/o/${encodeURIComponent(prefix.replace(/^\//, ""))}%2F${id}`; - const response = await fetch(`${url}?alt=media`); + const response = await fetch( + `${STORAGE_SERVER_URL}/file/${prefix}/${id}`, + ); if (response.status < 400) { const arrayBuffer = await response.arrayBuffer();