|
@@ -291,7 +291,7 @@ export class App extends React.Component<any, AppState> {
|
|
} else {
|
|
} else {
|
|
// create a map of ids so we don't have to iterate
|
|
// create a map of ids so we don't have to iterate
|
|
// over the array more than once.
|
|
// over the array more than once.
|
|
- const elementMap = elements.reduce(
|
|
|
|
|
|
+ const localElementMap = elements.reduce(
|
|
(
|
|
(
|
|
acc: { [key: string]: ExcalidrawElement },
|
|
acc: { [key: string]: ExcalidrawElement },
|
|
element: ExcalidrawElement,
|
|
element: ExcalidrawElement,
|
|
@@ -302,15 +302,42 @@ export class App extends React.Component<any, AppState> {
|
|
{},
|
|
{},
|
|
);
|
|
);
|
|
// Reconcile
|
|
// Reconcile
|
|
- elements = restoredState.elements.map(element => {
|
|
|
|
- if (
|
|
|
|
- elementMap.hasOwnProperty(element.id) &&
|
|
|
|
- elementMap[element.id].version > element.version
|
|
|
|
- ) {
|
|
|
|
- return elementMap[element.id];
|
|
|
|
- }
|
|
|
|
- return element;
|
|
|
|
- });
|
|
|
|
|
|
+ elements = restoredState.elements
|
|
|
|
+ .reduce((elements, element) => {
|
|
|
|
+ // if the remote element references one that's currently
|
|
|
|
+ // edited on local, skip it (it'll be added in the next
|
|
|
|
+ // step)
|
|
|
|
+ if (
|
|
|
|
+ element.id === this.state.editingElement?.id ||
|
|
|
|
+ element.id === this.state.resizingElement?.id ||
|
|
|
|
+ element.id === this.state.draggingElement?.id
|
|
|
|
+ ) {
|
|
|
|
+ return elements;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (
|
|
|
|
+ localElementMap.hasOwnProperty(element.id) &&
|
|
|
|
+ localElementMap[element.id].version > element.version
|
|
|
|
+ ) {
|
|
|
|
+ elements.push(localElementMap[element.id]);
|
|
|
|
+ } else {
|
|
|
|
+ elements.push(element);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return elements;
|
|
|
|
+ }, [] as any)
|
|
|
|
+ // add local elements that are currently being edited
|
|
|
|
+ // (can't be done in the step above because the elements may
|
|
|
|
+ // not exist on remote at all)
|
|
|
|
+ .concat(
|
|
|
|
+ elements.filter(element => {
|
|
|
|
+ return (
|
|
|
|
+ element.id === this.state.editingElement?.id ||
|
|
|
|
+ element.id === this.state.resizingElement?.id ||
|
|
|
|
+ element.id === this.state.draggingElement?.id
|
|
|
|
+ );
|
|
|
|
+ }),
|
|
|
|
+ );
|
|
}
|
|
}
|
|
this.setState({});
|
|
this.setState({});
|
|
if (this.socketInitialized === false) {
|
|
if (this.socketInitialized === false) {
|
|
@@ -358,7 +385,9 @@ export class App extends React.Component<any, AppState> {
|
|
this.broadcastSocketData({
|
|
this.broadcastSocketData({
|
|
type: "SCENE_UPDATE",
|
|
type: "SCENE_UPDATE",
|
|
payload: {
|
|
payload: {
|
|
- elements,
|
|
|
|
|
|
+ elements: elements.filter(element => {
|
|
|
|
+ return element.id !== this.state.editingElement?.id;
|
|
|
|
+ }),
|
|
appState: this.state,
|
|
appState: this.state,
|
|
},
|
|
},
|
|
});
|
|
});
|
|
@@ -1382,6 +1411,7 @@ export class App extends React.Component<any, AppState> {
|
|
elements = [...elements, element];
|
|
elements = [...elements, element];
|
|
this.setState({
|
|
this.setState({
|
|
draggingElement: element,
|
|
draggingElement: element,
|
|
|
|
+ editingElement: element,
|
|
});
|
|
});
|
|
}
|
|
}
|
|
} else if (element.type === "selection") {
|
|
} else if (element.type === "selection") {
|
|
@@ -1391,7 +1421,11 @@ export class App extends React.Component<any, AppState> {
|
|
});
|
|
});
|
|
} else {
|
|
} else {
|
|
elements = [...elements, element];
|
|
elements = [...elements, element];
|
|
- this.setState({ multiElement: null, draggingElement: element });
|
|
|
|
|
|
+ this.setState({
|
|
|
|
+ multiElement: null,
|
|
|
|
+ draggingElement: element,
|
|
|
|
+ editingElement: element,
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
let resizeArrowFn:
|
|
let resizeArrowFn:
|
|
@@ -1860,6 +1894,7 @@ export class App extends React.Component<any, AppState> {
|
|
isResizing: false,
|
|
isResizing: false,
|
|
resizingElement: null,
|
|
resizingElement: null,
|
|
selectionElement: null,
|
|
selectionElement: null,
|
|
|
|
+ editingElement: multiElement ? this.state.editingElement : null,
|
|
});
|
|
});
|
|
|
|
|
|
resizeArrowFn = null;
|
|
resizeArrowFn = null;
|
|
@@ -1883,7 +1918,10 @@ export class App extends React.Component<any, AppState> {
|
|
y - draggingElement.y,
|
|
y - draggingElement.y,
|
|
]);
|
|
]);
|
|
invalidateShapeForElement(draggingElement);
|
|
invalidateShapeForElement(draggingElement);
|
|
- this.setState({ multiElement: this.state.draggingElement });
|
|
|
|
|
|
+ this.setState({
|
|
|
|
+ multiElement: this.state.draggingElement,
|
|
|
|
+ editingElement: this.state.draggingElement,
|
|
|
|
+ });
|
|
} else if (draggingOccurred && !multiElement) {
|
|
} else if (draggingOccurred && !multiElement) {
|
|
if (!elementLocked) {
|
|
if (!elementLocked) {
|
|
resetCursor();
|
|
resetCursor();
|
|
@@ -2151,7 +2189,9 @@ export class App extends React.Component<any, AppState> {
|
|
this.broadcastSocketData({
|
|
this.broadcastSocketData({
|
|
type: "SCENE_UPDATE",
|
|
type: "SCENE_UPDATE",
|
|
payload: {
|
|
payload: {
|
|
- elements,
|
|
|
|
|
|
+ elements: elements.filter(element => {
|
|
|
|
+ return element.id !== this.state.editingElement?.id;
|
|
|
|
+ }),
|
|
appState: this.state,
|
|
appState: this.state,
|
|
},
|
|
},
|
|
});
|
|
});
|