Spaces:
Running
Running
revert
Browse files
client/src/components/BlockEditor/BlockEditor.tsx
CHANGED
|
@@ -795,9 +795,9 @@ export default function BlockEditor() {
|
|
| 795 |
const block = ws.getBlockById(e.blockId);
|
| 796 |
if (block && !block.getParent()) {
|
| 797 |
try {
|
| 798 |
-
const dom = Blockly.Xml.
|
| 799 |
const xml = Blockly.Xml.domToText(dom);
|
| 800 |
-
emitBlockCreateEvent(e.blockId,
|
| 801 |
} catch {}
|
| 802 |
}
|
| 803 |
}
|
|
|
|
| 795 |
const block = ws.getBlockById(e.blockId);
|
| 796 |
if (block && !block.getParent()) {
|
| 797 |
try {
|
| 798 |
+
const dom = Blockly.Xml.blockToDom(block, { xy: true } as any);
|
| 799 |
const xml = Blockly.Xml.domToText(dom);
|
| 800 |
+
emitBlockCreateEvent(e.blockId, xml);
|
| 801 |
} catch {}
|
| 802 |
}
|
| 803 |
}
|
client/src/hooks/useWebSocket.ts
CHANGED
|
@@ -112,25 +112,12 @@ export function useWebSocket() {
|
|
| 112 |
useCollaborationStore.getState().updateElementHover(userId, elementId);
|
| 113 |
});
|
| 114 |
|
| 115 |
-
s.on('block_state_synced', (
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
if (data.initialBlocksXml) {
|
| 119 |
-
const store = useEditorStore.getState();
|
| 120 |
-
for (const [fid, entry] of Object.entries(data.initialBlocksXml)) {
|
| 121 |
-
if (entry.xml) store.setBlocksXml(fid, entry.xml);
|
| 122 |
-
}
|
| 123 |
-
if (store.activeFileId && data.initialBlocksXml[store.activeFileId]?.xml) {
|
| 124 |
-
store.setVisualElements(store.elementRegistry[store.activeFileId] || []);
|
| 125 |
-
}
|
| 126 |
-
return;
|
| 127 |
-
}
|
| 128 |
-
// Real-time sync update
|
| 129 |
-
if (data.updatedBy === useAuthStore.getState().user?.id) return;
|
| 130 |
-
useEditorStore.getState().setBlocksXml(data.fileId, data.xml);
|
| 131 |
const store = useEditorStore.getState();
|
| 132 |
-
if (store.activeFileId ===
|
| 133 |
-
store.setVisualElements(store.elementRegistry[
|
| 134 |
}
|
| 135 |
});
|
| 136 |
|
|
@@ -161,14 +148,8 @@ export function useWebSocket() {
|
|
| 161 |
useCollaborationStore.getState().pushPendingBlockChange({ blockId, name, value });
|
| 162 |
});
|
| 163 |
|
| 164 |
-
s.on('collaborator_block_create_event', ({ blockId,
|
| 165 |
-
|
| 166 |
-
// Only apply to the currently active file; otherwise the block would appear
|
| 167 |
-
// on the wrong file's workspace. The full XML sync (block_state_synced) will
|
| 168 |
-
// handle it when the collaborator switches to that file.
|
| 169 |
-
if (store.activeFileId === fileId) {
|
| 170 |
-
useCollaborationStore.getState().pushPendingBlockCreate({ blockId, xml });
|
| 171 |
-
}
|
| 172 |
});
|
| 173 |
|
| 174 |
s.on('file_updated', ({ fileId, content }: { fileId: string; content: string }) => {
|
|
@@ -448,10 +429,10 @@ export function useProjectSocket(projectId: string | undefined) {
|
|
| 448 |
}
|
| 449 |
}, [projectId]);
|
| 450 |
|
| 451 |
-
const emitBlockCreateEvent = useCallback((blockId: string,
|
| 452 |
const s = globalSocket;
|
| 453 |
if (s?.connected && projectId) {
|
| 454 |
-
s.emit('block_create_event', { projectId,
|
| 455 |
}
|
| 456 |
}, [projectId]);
|
| 457 |
|
|
|
|
| 112 |
useCollaborationStore.getState().updateElementHover(userId, elementId);
|
| 113 |
});
|
| 114 |
|
| 115 |
+
s.on('block_state_synced', ({ fileId, xml, updatedBy }: { fileId: string; xml: string; updatedBy: string }) => {
|
| 116 |
+
if (updatedBy === useAuthStore.getState().user?.id) return;
|
| 117 |
+
useEditorStore.getState().setBlocksXml(fileId, xml);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
const store = useEditorStore.getState();
|
| 119 |
+
if (store.activeFileId === fileId) {
|
| 120 |
+
store.setVisualElements(store.elementRegistry[fileId] || []);
|
| 121 |
}
|
| 122 |
});
|
| 123 |
|
|
|
|
| 148 |
useCollaborationStore.getState().pushPendingBlockChange({ blockId, name, value });
|
| 149 |
});
|
| 150 |
|
| 151 |
+
s.on('collaborator_block_create_event', ({ blockId, xml }: { blockId: string; xml: string }) => {
|
| 152 |
+
useCollaborationStore.getState().pushPendingBlockCreate({ blockId, xml });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
});
|
| 154 |
|
| 155 |
s.on('file_updated', ({ fileId, content }: { fileId: string; content: string }) => {
|
|
|
|
| 429 |
}
|
| 430 |
}, [projectId]);
|
| 431 |
|
| 432 |
+
const emitBlockCreateEvent = useCallback((blockId: string, xml: string) => {
|
| 433 |
const s = globalSocket;
|
| 434 |
if (s?.connected && projectId) {
|
| 435 |
+
s.emit('block_create_event', { projectId, blockId, xml });
|
| 436 |
}
|
| 437 |
}, [projectId]);
|
| 438 |
|
server/src/services/realtime.ts
CHANGED
|
@@ -506,12 +506,11 @@ export function initRealtime(httpServer: HttpServer): Server {
|
|
| 506 |
});
|
| 507 |
});
|
| 508 |
|
| 509 |
-
socket.on('block_create_event', (data: { projectId: string;
|
| 510 |
const session = sessions.get(socket.id);
|
| 511 |
if (!session) return;
|
| 512 |
socket.to(`project:${data.projectId}`).emit('collaborator_block_create_event', {
|
| 513 |
userId: session.userId,
|
| 514 |
-
fileId: data.fileId,
|
| 515 |
blockId: data.blockId,
|
| 516 |
xml: data.xml,
|
| 517 |
});
|
|
|
|
| 506 |
});
|
| 507 |
});
|
| 508 |
|
| 509 |
+
socket.on('block_create_event', (data: { projectId: string; blockId: string; xml: string }) => {
|
| 510 |
const session = sessions.get(socket.id);
|
| 511 |
if (!session) return;
|
| 512 |
socket.to(`project:${data.projectId}`).emit('collaborator_block_create_event', {
|
| 513 |
userId: session.userId,
|
|
|
|
| 514 |
blockId: data.blockId,
|
| 515 |
xml: data.xml,
|
| 516 |
});
|