Skip to content

Commit 31d4484

Browse files
authored
Live bug fixes (codesandbox#1506)
* Add auto repair to Live * Fix lint * Update syncing status * Add manual module sync * Fix null check * Revert yarn.lock
1 parent 0290207 commit 31d4484

File tree

11 files changed

+90
-35
lines changed

11 files changed

+90
-35
lines changed

packages/app/src/app/components/CodeEditor/Monaco/index.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
275275
// have the correct cursor pos no matter what
276276
const { onSelectionChanged, isLive } = this.props;
277277
// Reason 3 is update by mouse or arrow keys
278-
if (isLive) {
278+
if (isLive && editor.getModel()) {
279279
const lines = editor.getModel().getLinesContent() || [];
280280
const data = {
281281
primary: getSelection(lines, selectionChange.selection),
@@ -425,14 +425,21 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
425425
if (sendTransforms && changeEvent.changes) {
426426
this.liveOperationCode =
427427
this.liveOperationCode || this.currentModule.code || '';
428-
const { operation, newCode } = eventToTransform(
429-
changeEvent,
430-
this.liveOperationCode
431-
);
428+
try {
429+
const { operation, newCode } = eventToTransform(
430+
changeEvent,
431+
this.liveOperationCode
432+
);
433+
434+
this.liveOperationCode = newCode;
432435

433-
this.liveOperationCode = newCode;
436+
sendTransforms(operation);
437+
} catch (e) {
438+
// Something went wrong while composing the operation, so we're opting for a full sync
439+
console.error(e);
434440

435-
sendTransforms(operation);
441+
this.props.onModuleStateMismatch();
442+
}
436443

437444
requestAnimationFrame(() => {
438445
this.liveOperationCode = '';
@@ -570,9 +577,14 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
570577
return;
571578
}
572579

573-
const code = operation.apply(module.code || '');
574-
if (this.props.onChange) {
575-
this.props.onChange(code, module.shortid);
580+
try {
581+
const code = operation.apply(module.code || '');
582+
if (this.props.onChange) {
583+
this.props.onChange(code, module.shortid);
584+
}
585+
} catch (e) {
586+
// Something went wrong while applying
587+
this.props.onModuleStateMismatch();
576588
}
577589
return;
578590
}

packages/app/src/app/components/CodeEditor/Monaco/live-decorations.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ export function updateUserSelections(
3333
}
3434
>
3535
) {
36+
if (!editor.getModel()) {
37+
return;
38+
}
39+
3640
const lines = editor.getModel().getLinesContent() || [];
3741

3842
userSelections.forEach(data => {

packages/app/src/app/components/CodeEditor/VSCode/index.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -512,14 +512,21 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
512512
if (sendTransforms && changeEvent.changes) {
513513
this.liveOperationCode =
514514
this.liveOperationCode || this.currentModule.code || '';
515-
const { operation, newCode } = eventToTransform(
516-
changeEvent,
517-
this.liveOperationCode
518-
);
515+
try {
516+
const { operation, newCode } = eventToTransform(
517+
changeEvent,
518+
this.liveOperationCode
519+
);
519520

520-
this.liveOperationCode = newCode;
521+
this.liveOperationCode = newCode;
521522

522-
sendTransforms(operation);
523+
sendTransforms(operation);
524+
} catch (e) {
525+
// Something went wrong while composing the operation, so we're opting for a full sync
526+
console.error(e);
527+
528+
this.props.onModuleStateMismatch();
529+
}
523530

524531
requestAnimationFrame(() => {
525532
this.liveOperationCode = '';
@@ -669,9 +676,14 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
669676
return;
670677
}
671678

672-
const code = operation.apply(module.code || '');
673-
if (this.props.onChange) {
674-
this.props.onChange(code, module.shortid);
679+
try {
680+
const code = operation.apply(module.code || '');
681+
if (this.props.onChange) {
682+
this.props.onChange(code, module.shortid);
683+
}
684+
} catch (e) {
685+
// Something went wrong while applying
686+
this.props.onModuleStateMismatch();
675687
}
676688
return;
677689
}

packages/app/src/app/components/CodeEditor/types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,5 @@ export type Props = {
8989
receivingCode?: boolean,
9090
onCodeReceived?: () => void,
9191
onSelectionChanged: (d: { selection: any, moduleShortid: string }) => void,
92+
onModuleStateMismatch?: () => void,
9293
};

packages/app/src/app/pages/Sandbox/Editor/Content/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ class EditorPreview extends React.Component<Props, State> {
483483
isLive={store.live.isLive}
484484
onCodeReceived={signals.live.onCodeReceived}
485485
onSelectionChanged={signals.live.onSelectionChanged}
486+
onModuleStateMismatch={signals.live.onModuleStateMismatch}
486487
onNpmDependencyAdded={name => {
487488
if (sandbox.owned) {
488489
signals.editor.addNpmDependency({ name, isDev: true });

packages/app/src/app/store/modules/live/actions.js

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -310,18 +310,28 @@ export function sendChangeCurrentModule({ props, state, live }) {
310310
}
311311

312312
export function clearUserSelections({ props, state }) {
313-
const userIndex = state
314-
.get('live.roomInfo.users')
315-
.findIndex(u => u.id === props.data.live_user_id);
316-
317-
if (userIndex > -1) {
318-
if (state.get(`live.roomInfo.users.${userIndex}`)) {
319-
state.set(`live.roomInfo.users.${userIndex}.selection`, null);
320-
state.push('editor.pendingUserSelections', {
321-
userId: props.data.live_user_id,
322-
selection: null,
323-
});
313+
const clearSelections = userId => {
314+
const userIndex = state
315+
.get('live.roomInfo.users')
316+
.findIndex(u => u.id === userId);
317+
318+
if (userIndex > -1) {
319+
if (state.get(`live.roomInfo.users.${userIndex}`)) {
320+
state.set(`live.roomInfo.users.${userIndex}.selection`, null);
321+
state.push('editor.pendingUserSelections', {
322+
userId,
323+
selection: null,
324+
});
325+
}
324326
}
327+
};
328+
329+
if (!props.data) {
330+
// All users
331+
332+
state.get('live.roomInfo.users').forEach(u => clearSelections(u.id));
333+
} else {
334+
clearSelections(props.data.live_user_id);
325335
}
326336
}
327337

@@ -372,6 +382,10 @@ export function receiveTransformation({ ot, props, live }) {
372382
}
373383
}
374384

385+
export function syncModuleState({ live }) {
386+
live.send('live:module_state', {});
387+
}
388+
375389
export function applyTransformation({ props, state }) {
376390
const sandbox = state.get('editor.currentSandbox');
377391
const module = sandbox.modules.find(

packages/app/src/app/store/modules/live/common-sequences.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ export const initializeLive = factories.withLoadApp([
3030
actions.unSetReceivingStatus,
3131
set(state`live.isLive`, true),
3232
set(state`live.error`, null),
33+
34+
// We do an extra manual sync of modules because in the time that the user joined there is a chance
35+
// that new messages came in
36+
actions.syncModuleState,
3337
],
3438
error: set(state`live.error`, props`reason`),
3539
},

packages/app/src/app/store/modules/live/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ export default Module({
4343
onSendChat: sequences.sendChat,
4444
onChatEnabledChange: sequences.setChatEnabled,
4545
onFollow: sequences.setFollowing,
46+
onModuleStateMismatch: sequences.syncModuleState,
4647
},
4748
});

packages/app/src/app/store/modules/live/sequences.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,5 @@ export const setFollowing = [
391391
false: [],
392392
},
393393
];
394+
395+
export const syncModuleState = [actions.syncModuleState];

packages/app/src/app/store/providers/Live.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,14 @@ export default Provider({
6060
sentMessages.set(_messageId, payload);
6161

6262
return new Promise((resolve, reject) => {
63-
channel
64-
.push(event, payload)
65-
.receive('ok', resolve)
66-
.receive('error', reject);
63+
if (channel) {
64+
channel
65+
.push(event, payload)
66+
.receive('ok', resolve)
67+
.receive('error', reject);
68+
} else {
69+
reject('Channel is not defined');
70+
}
6771
});
6872
},
6973
});

0 commit comments

Comments
 (0)