diff --git a/.env.development b/.env.development
index 08257282..d37b83ac 100644
--- a/.env.development
+++ b/.env.development
@@ -4,5 +4,5 @@ REACT_APP_BACKEND_V2_POST_URL=https://json-dev.excalidraw.com/api/v2/post/
REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
REACT_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
-REACT_APP_SOCKET_SERVER_URL=http://localhost:3002
+REACT_APP_PORTAL_URL=http://localhost:3002
REACT_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}'
diff --git a/.env.production b/.env.production
index 08022700..842ce2b0 100644
--- a/.env.production
+++ b/.env.production
@@ -4,7 +4,7 @@ REACT_APP_BACKEND_V2_POST_URL=https://json.excalidraw.com/api/v2/post/
REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
REACT_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
-REACT_APP_SOCKET_SERVER_URL=https://oss-collab-us1.excalidraw.com
+REACT_APP_PORTAL_URL=https://portal.excalidraw.com
REACT_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyAd15pYlMci_xIp9ko6wkEsDzAAA0Dn0RU","authDomain":"excalidraw-room-persistence.firebaseapp.com","databaseURL":"https://excalidraw-room-persistence.firebaseio.com","projectId":"excalidraw-room-persistence","storageBucket":"excalidraw-room-persistence.appspot.com","messagingSenderId":"654800341332","appId":"1:654800341332:web:4a692de832b55bd57ce0c1"}'
# production-only vars
diff --git a/public/index.html b/public/index.html
index 0df8b246..0d8ce3b9 100644
--- a/public/index.html
+++ b/public/index.html
@@ -72,12 +72,6 @@
crossorigin="anonymous"
/>
-
-
{
/* webpackChunkName: "socketIoClient" */ "socket.io-client"
);
- this.portal.socket = this.portal.open(
- socketIOClient(SOCKET_SERVER),
- roomId,
- roomKey,
- );
+ try {
+ const socketServerData = await getCollabServer();
+ this.portal.socket = this.portal.open(
+ socketIOClient(socketServerData.url, {
+ transports: socketServerData.polling
+ ? ["websocket", "polling"]
+ : ["websocket"],
+ }),
+ roomId,
+ roomKey,
+ );
+ } catch (error: any) {
+ console.error(error);
+ this.setState({ errorMessage: error.message });
+ return null;
+ }
if (!existingRoomLinkData) {
const elements = this.excalidrawAPI.getSceneElements().map((element) => {
diff --git a/src/excalidraw-app/data/index.ts b/src/excalidraw-app/data/index.ts
index 11b59b82..64049c70 100644
--- a/src/excalidraw-app/data/index.ts
+++ b/src/excalidraw-app/data/index.ts
@@ -30,7 +30,25 @@ const generateRoomId = async () => {
return bytesToHexString(buffer);
};
-export const SOCKET_SERVER = process.env.REACT_APP_SOCKET_SERVER_URL;
+/**
+ * Right now the reason why we resolve connection params (url, polling...)
+ * from upstream is to allow changing the params immediately when needed without
+ * having to wait for clients to update the SW.
+ */
+export const getCollabServer = async (): Promise<{
+ url: string;
+ polling: boolean;
+}> => {
+ try {
+ const resp = await fetch(
+ `${process.env.REACT_APP_PORTAL_URL}/collab-server`,
+ );
+ return await resp.json();
+ } catch (error) {
+ console.error(error);
+ throw new Error(t("errors.cannotResolveCollabServer"));
+ }
+};
export type EncryptedData = {
data: ArrayBuffer;
diff --git a/src/global.d.ts b/src/global.d.ts
index ef24cb5a..337a5f0d 100644
--- a/src/global.d.ts
+++ b/src/global.d.ts
@@ -21,7 +21,7 @@ declare namespace NodeJS {
interface ProcessEnv {
readonly REACT_APP_BACKEND_V2_GET_URL: string;
readonly REACT_APP_BACKEND_V2_POST_URL: string;
- readonly REACT_APP_SOCKET_SERVER_URL: string;
+ readonly REACT_APP_PORTAL_URL: string;
readonly REACT_APP_FIREBASE_CONFIG: string;
}
}
diff --git a/src/locales/en.json b/src/locales/en.json
index b5595c2d..e7b2e572 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -180,7 +180,8 @@
"imageInsertError": "Couldn't insert image. Try again later...",
"fileTooBig": "File is too big. Maximum allowed size is {{maxSize}}.",
"svgImageInsertError": "Couldn't insert SVG image. The SVG markup looks invalid.",
- "invalidSVGString": "Invalid SVG."
+ "invalidSVGString": "Invalid SVG.",
+ "cannotResolveCollabServer": "Couldn't connect to the collab server. Please reload the page and try again."
},
"toolBar": {
"selection": "Selection",
diff --git a/src/tests/collab.test.tsx b/src/tests/collab.test.tsx
index d80b06dc..84fd9e3a 100644
--- a/src/tests/collab.test.tsx
+++ b/src/tests/collab.test.tsx
@@ -15,6 +15,14 @@ Object.defineProperty(window, "crypto", {
},
});
+jest.mock("../excalidraw-app/data/index.ts", () => ({
+ __esmodule: true,
+ ...jest.requireActual("../excalidraw-app/data/index.ts"),
+ getCollabServer: jest.fn(() => ({
+ url: /* doesn't really matter */ "http://localhost:3002",
+ })),
+}));
+
jest.mock("../excalidraw-app/data/firebase.ts", () => {
const loadFromFirebase = async () => null;
const saveToFirebase = () => {};