mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-11-04 12:54:23 +01:00 
			
		
		
		
	clear deleted elements on room create (#2270)
This commit is contained in:
		@@ -654,8 +654,10 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (isCollaborationScene) {
 | 
					    if (isCollaborationScene) {
 | 
				
			||||||
      // when joining a room we don't want user's local scene data to be merged
 | 
					      // when joining a room we don't want user's local scene data to be merged
 | 
				
			||||||
      //  into the remote scene, so set `clearScene`
 | 
					      //  into the remote scene
 | 
				
			||||||
      this.initializeSocketClient({ showLoadingState: true, clearScene: true });
 | 
					      this.resetScene();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      this.initializeSocketClient({ showLoadingState: true });
 | 
				
			||||||
    } else if (scene) {
 | 
					    } else if (scene) {
 | 
				
			||||||
      if (scene.appState) {
 | 
					      if (scene.appState) {
 | 
				
			||||||
        scene.appState = {
 | 
					        scene.appState = {
 | 
				
			||||||
@@ -1256,6 +1258,14 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 | 
				
			|||||||
      "Excalidraw",
 | 
					      "Excalidraw",
 | 
				
			||||||
      await generateCollaborationLink(),
 | 
					      await generateCollaborationLink(),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					    // remove deleted elements from elements array & history to ensure we don't
 | 
				
			||||||
 | 
					    // expose potentially sensitive user data in case user manually deletes
 | 
				
			||||||
 | 
					    // existing elements (or clears scene), which would otherwise be persisted
 | 
				
			||||||
 | 
					    // to database even if deleted before creating the room.
 | 
				
			||||||
 | 
					    history.clear();
 | 
				
			||||||
 | 
					    history.resumeRecording();
 | 
				
			||||||
 | 
					    this.scene.replaceAllElements(this.scene.getElements());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.initializeSocketClient({ showLoadingState: false });
 | 
					    this.initializeSocketClient({ showLoadingState: false });
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1365,14 +1375,11 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  private initializeSocketClient = async (opts: {
 | 
					  private initializeSocketClient = async (opts: {
 | 
				
			||||||
    showLoadingState: boolean;
 | 
					    showLoadingState: boolean;
 | 
				
			||||||
    clearScene?: boolean;
 | 
					 | 
				
			||||||
  }) => {
 | 
					  }) => {
 | 
				
			||||||
    if (this.portal.socket) {
 | 
					    if (this.portal.socket) {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (opts.clearScene) {
 | 
					
 | 
				
			||||||
      this.resetScene();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    const roomMatch = getCollaborationLinkData(window.location.href);
 | 
					    const roomMatch = getCollaborationLinkData(window.location.href);
 | 
				
			||||||
    if (roomMatch) {
 | 
					    if (roomMatch) {
 | 
				
			||||||
      const roomID = roomMatch[1];
 | 
					      const roomID = roomMatch[1];
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										67
									
								
								src/tests/collab.test.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/tests/collab.test.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import { render, waitFor } from "./test-utils";
 | 
				
			||||||
 | 
					import App from "../components/App";
 | 
				
			||||||
 | 
					import { API } from "./helpers/api";
 | 
				
			||||||
 | 
					import { createUndoAction } from "../actions/actionHistory";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { h } = window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Object.defineProperty(window, "crypto", {
 | 
				
			||||||
 | 
					  value: {
 | 
				
			||||||
 | 
					    getRandomValues: (arr: number[]) =>
 | 
				
			||||||
 | 
					      arr.forEach((v, i) => (arr[i] = Math.floor(Math.random() * 256))),
 | 
				
			||||||
 | 
					    subtle: {
 | 
				
			||||||
 | 
					      generateKey: () => {},
 | 
				
			||||||
 | 
					      exportKey: () => ({ k: "sTdLvMC_M3V8_vGa3UVRDg" }),
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jest.mock("../data/firebase.ts", () => {
 | 
				
			||||||
 | 
					  const loadFromFirebase = async () => null;
 | 
				
			||||||
 | 
					  const saveToFirebase = () => {};
 | 
				
			||||||
 | 
					  const isSavedToFirebase = () => true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    loadFromFirebase,
 | 
				
			||||||
 | 
					    saveToFirebase,
 | 
				
			||||||
 | 
					    isSavedToFirebase,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe("collaboration", () => {
 | 
				
			||||||
 | 
					  it("creating room should reset deleted elements", async () => {
 | 
				
			||||||
 | 
					    render(
 | 
				
			||||||
 | 
					      <App
 | 
				
			||||||
 | 
					        initialData={{
 | 
				
			||||||
 | 
					          elements: [
 | 
				
			||||||
 | 
					            API.createElement({ type: "rectangle", id: "A" }),
 | 
				
			||||||
 | 
					            API.createElement({ type: "rectangle", id: "B", isDeleted: true }),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await waitFor(() => {
 | 
				
			||||||
 | 
					      expect(h.elements).toEqual([
 | 
				
			||||||
 | 
					        expect.objectContaining({ id: "A" }),
 | 
				
			||||||
 | 
					        expect.objectContaining({ id: "B", isDeleted: true }),
 | 
				
			||||||
 | 
					      ]);
 | 
				
			||||||
 | 
					      expect(API.getStateHistory().length).toBe(1);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    h.app.openPortal();
 | 
				
			||||||
 | 
					    await waitFor(() => {
 | 
				
			||||||
 | 
					      expect(h.elements).toEqual([expect.objectContaining({ id: "A" })]);
 | 
				
			||||||
 | 
					      expect(API.getStateHistory().length).toBe(1);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const undoAction = createUndoAction(h.history);
 | 
				
			||||||
 | 
					    // noop
 | 
				
			||||||
 | 
					    h.app.actionManager.executeAction(undoAction);
 | 
				
			||||||
 | 
					    await waitFor(() => {
 | 
				
			||||||
 | 
					      expect(h.elements).toEqual([expect.objectContaining({ id: "A" })]);
 | 
				
			||||||
 | 
					      expect(API.getStateHistory().length).toBe(1);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
		Reference in New Issue
	
	Block a user