Skip to content

Commit 452b004

Browse files
author
Ives van Hoorne
committed
Finishing touches
1 parent 464d1f2 commit 452b004

File tree

3 files changed

+98
-59
lines changed
  • packages/app/src/app
    • components/CodeEditor/Monaco
    • pages
      • Patron/PricingModal/PricingInfo
      • Sandbox/Editor/Workspace/items/Live

3 files changed

+98
-59
lines changed

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

Lines changed: 64 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
215215
const { isLive, sendTransforms } = this.props;
216216

217217
if (isLive && sendTransforms && !this.receivingCode) {
218+
console.log(changes);
218219
this.addChangesOperation(changes);
219220
}
220221

@@ -435,7 +436,10 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
435436
*/
436437
addChangesOperation = (changes: Array<any>) => {
437438
// Module changed in the meantime
438-
if (this.changes.moduleShortid !== this.currentModule.shortid) {
439+
if (
440+
this.changes.moduleShortid &&
441+
this.changes.moduleShortid !== this.currentModule.shortid
442+
) {
439443
this.sendChangeOperations();
440444
}
441445

@@ -453,62 +457,77 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
453457
if (this.changeTimeout) {
454458
clearTimeout(this.changeTimeout);
455459
}
456-
this.changeTimeout = setTimeout(() => {
457-
this.sendChangeOperations();
458-
}, 10);
460+
461+
this.sendChangeOperations();
459462
};
460463

461-
sendChangeOperations = () => {
464+
sendChangeOperations = (retry: boolean = false) => {
462465
const { sendTransforms, isLive, onCodeReceived } = this.props;
463466

464-
if (
465-
sendTransforms &&
466-
this.changes.changes &&
467-
this.changes.moduleShortid === this.currentModule.shortid
468-
) {
469-
let code = this.changes.code;
470-
const t = this.changes.changes
471-
.map(change => {
472-
const startPos = change.range.getStartPosition();
473-
const lines = code.split('\n');
474-
const totalLength = code.length;
475-
let index = lineAndColumnToIndex(
476-
lines,
477-
startPos.lineNumber,
478-
startPos.column
479-
);
467+
try {
468+
if (
469+
sendTransforms &&
470+
this.changes.changes &&
471+
this.changes.moduleShortid === this.currentModule.shortid
472+
) {
473+
let code = this.changes.code;
474+
const t = this.changes.changes
475+
.map(change => {
476+
const startPos = change.range.getStartPosition();
477+
const lines = code.split('\n');
478+
const totalLength = code.length;
479+
let index = lineAndColumnToIndex(
480+
lines,
481+
startPos.lineNumber,
482+
startPos.column
483+
);
484+
485+
const operation = new TextOperation();
486+
if (index) {
487+
operation.retain(index);
488+
}
480489

481-
const operation = new TextOperation();
482-
if (index) {
483-
operation.retain(index);
484-
}
490+
if (change.rangeLength > 0) {
491+
// Deletion
492+
operation.delete(change.rangeLength);
485493

486-
if (change.rangeLength > 0) {
487-
// Deletion
488-
operation.delete(change.rangeLength);
494+
index += change.rangeLength;
495+
}
496+
if (change.text) {
497+
// Insertion
498+
operation.insert(change.text);
499+
}
489500

490-
index += change.rangeLength;
491-
}
492-
if (change.text) {
493-
// Insertion
494-
operation.insert(change.text);
495-
}
501+
operation.retain(Math.max(0, totalLength - index));
496502

497-
operation.retain(Math.max(0, totalLength - index));
503+
if (this.changes.changes.length > 1) {
504+
code = operation.apply(code);
505+
}
498506

499-
if (this.changes.changes.length > 1) {
500-
code = operation.apply(code);
501-
}
507+
return operation;
508+
})
509+
.reduce((prev, next) => prev.compose(next));
502510

503-
return operation;
504-
})
505-
.reduce((prev, next) => prev.compose(next));
511+
sendTransforms(t);
512+
} else if (!isLive && onCodeReceived) {
513+
onCodeReceived();
514+
}
515+
this.changes = { moduleShortid: null, code: '', changes: [] };
516+
} catch (e) {
517+
if (retry) {
518+
throw e;
519+
}
506520

507-
sendTransforms(t);
508-
} else if (!isLive && onCodeReceived) {
509-
onCodeReceived();
521+
console.error(e);
522+
// This can happen on undo, Monaco sends a huge list of operations
523+
// that all apply to the same code and causes the `compose` function
524+
// to throw. The solution is to wait for the new code and try again. That's why
525+
// we call this function again in a timeout
526+
527+
setTimeout(() => {
528+
this.sendChangeOperations(true);
529+
}, 10);
510530
}
511-
this.changes = { moduleShortid: null, code: '', changes: [] };
512531
};
513532

514533
userClassesGenerated = {};

packages/app/src/app/pages/Patron/PricingModal/PricingInfo/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ function PricingInfo() {
2020
<tbody>
2121
<Feature feature="Private Sandboxes" free="No" supporter="Yes" />
2222
<Feature feature="Sandbox Limit" free="50" supporter="Unlimited" />
23+
<Feature feature="Live" free="Disabled" supporter="Enabled" />
2324
<Feature
2425
disabled
2526
feature="Static File Hosting"

packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Live/index.js

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from 'react';
22
import { inject, observer } from 'mobx-react';
33

4+
import Button from 'app/components/Button';
5+
46
import LiveInfo from './LiveInfo';
57
import LiveButton from './LiveButton';
68

@@ -30,20 +32,37 @@ const Live = ({ signals, store }) => (
3032
live!
3133
</Description>
3234

33-
<WorkspaceSubtitle>Create live room</WorkspaceSubtitle>
34-
<Description>
35-
To invite others you need to generate a URL that others can join.
36-
</Description>
37-
<WorkspaceInputContainer>
38-
<LiveButton
39-
onClick={() => {
40-
signals.live.createLiveClicked({
41-
sandboxId: store.editor.currentId,
42-
});
43-
}}
44-
isLoading={store.live.isLoading}
45-
/>
46-
</WorkspaceInputContainer>
35+
{store.isPatron ? (
36+
<React.Fragment>
37+
<WorkspaceSubtitle>Create live room</WorkspaceSubtitle>
38+
<Description>
39+
To invite others you need to generate a URL that others can join.
40+
</Description>
41+
<WorkspaceInputContainer>
42+
<LiveButton
43+
onClick={() => {
44+
signals.live.createLiveClicked({
45+
sandboxId: store.editor.currentId,
46+
});
47+
}}
48+
isLoading={store.live.isLoading}
49+
/>
50+
</WorkspaceInputContainer>
51+
</React.Fragment>
52+
) : (
53+
<React.Fragment>
54+
<WorkspaceSubtitle>Patron Required</WorkspaceSubtitle>
55+
<Description>
56+
To share your sandbox for real time collaboration you need to be a
57+
CodeSandbox Patron.
58+
</Description>
59+
<WorkspaceInputContainer>
60+
<Button target="_blank" block to="/patron">
61+
Become a Patron
62+
</Button>
63+
</WorkspaceInputContainer>
64+
</React.Fragment>
65+
)}
4766
</React.Fragment>
4867
)}
4968
</div>

0 commit comments

Comments
 (0)