Skip to content

Commit 32b856f

Browse files
author
Ives van Hoorne
committed
Handle fork and user leaving sandbox
1 parent 1c14543 commit 32b856f

File tree

14 files changed

+178
-77
lines changed

14 files changed

+178
-77
lines changed

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -518,10 +518,10 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
518518
const lines = this.editor.getModel().getLinesContent();
519519

520520
userSelections.forEach(data => {
521-
if (data.selection === null) {
522-
const { userId } = data;
521+
const { userId } = data;
523522

524-
const decorationId = this.currentModule.shortid + userId;
523+
const decorationId = this.currentModule.shortid + userId;
524+
if (data.selection === null) {
525525
this.userSelectionDecorations[
526526
decorationId
527527
] = this.editor.deltaDecorations(
@@ -534,7 +534,7 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
534534
}
535535

536536
const decorations = [];
537-
const { selection, color, userId, name } = data;
537+
const { selection, color, name } = data;
538538

539539
if (selection) {
540540
const addCursor = (position, className) => {
@@ -570,10 +570,11 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
570570
});
571571
};
572572

573-
const cursorClassName = userId + '-cursor';
574-
const secondaryCursorClassName = userId + '-secondary-cursor';
575-
const selectionClassName = userId + '-selection';
576-
const secondarySelectionClassName = userId + '-secondary-selection';
573+
const prefix = color.join('-') + userId;
574+
const cursorClassName = prefix + '-cursor';
575+
const secondaryCursorClassName = prefix + '-secondary-cursor';
576+
const selectionClassName = prefix + '-selection';
577+
const secondarySelectionClassName = prefix + '-secondary-selection';
577578

578579
if (!this.userClassesGenerated[cursorClassName]) {
579580
const nameStyles = {
@@ -667,7 +668,6 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
667668

668669
// Allow new model to attach in case it's attaching
669670
requestAnimationFrame(() => {
670-
const decorationId = this.currentModule.shortid + userId;
671671
this.userSelectionDecorations[
672672
decorationId
673673
] = this.editor.deltaDecorations(

packages/app/src/app/components/NewSandbox/index.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function NewSandbox({ signals }) {
5151
height={50}
5252
text="Vanilla"
5353
href={parcelSandboxUrl()}
54-
onClick={() => signals.closeModal()}
54+
onClick={() => signals.modalClosed()}
5555
/>
5656

5757
<Logo
@@ -60,7 +60,7 @@ function NewSandbox({ signals }) {
6060
height={50}
6161
text="React"
6262
href={newSandboxUrl()}
63-
onClick={() => signals.closeModal()}
63+
onClick={() => signals.modalClosed()}
6464
/>
6565

6666
<Logo
@@ -69,7 +69,7 @@ function NewSandbox({ signals }) {
6969
height={50}
7070
text="Vue"
7171
href={newVueSandboxUrl()}
72-
onClick={() => signals.closeModal()}
72+
onClick={() => signals.modalClosed()}
7373
/>
7474

7575
<Logo
@@ -78,47 +78,47 @@ function NewSandbox({ signals }) {
7878
height={50}
7979
text="Angular"
8080
href={newAngularSandboxUrl()}
81-
onClick={() => signals.closeModal()}
81+
onClick={() => signals.modalClosed()}
8282
/>
8383
<Logo
8484
Icon={PreactIcon}
8585
width={50}
8686
height={50}
8787
text="Preact"
8888
href={newPreactSandboxUrl()}
89-
onClick={() => signals.closeModal()}
89+
onClick={() => signals.modalClosed()}
9090
/>
9191
<Logo
9292
Icon={SvelteIcon}
9393
width={50}
9494
height={50}
9595
text="Svelte"
9696
href={newSvelteSandboxUrl()}
97-
onClick={() => signals.closeModal()}
97+
onClick={() => signals.modalClosed()}
9898
/>
9999
<Logo
100100
Icon={ReactIcon}
101101
width={50}
102102
height={50}
103103
text="React TypeScript"
104104
href={newReactTypeScriptSandboxUrl()}
105-
onClick={() => signals.closeModal()}
105+
onClick={() => signals.modalClosed()}
106106
/>
107107
<Logo
108108
Icon={GithubIcon}
109109
width={50}
110110
height={50}
111111
text="Import from Github"
112112
href={importFromGitHubUrl()}
113-
onClick={() => signals.closeModal()}
113+
onClick={() => signals.modalClosed()}
114114
/>
115115
<Logo
116116
Icon={TerminalIcon}
117117
width={50}
118118
height={50}
119119
text="Upload from CLI"
120120
href={uploadFromCliUrl()}
121-
onClick={() => signals.closeModal()}
121+
onClick={() => signals.modalClosed()}
122122
/>
123123
</RowContainer>
124124
</Container>

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,23 @@ class EditorPreview extends React.Component<Props, State> {
218218
editor.applyOperation(
219219
TextOperation.fromJSON(store.editor.pendingOperation)
220220
);
221-
222-
this.props.signals.live.onOperationApplied();
223221
} else {
224-
console.log('not applying; setting code manually');
225-
// TODO apply logic itself and call `editor.changeCode` manually
222+
try {
223+
if (editor.currentModule) {
224+
const operation = TextOperation.fromJSON(
225+
store.editor.pendingOperation
226+
);
227+
228+
this.props.signals.editor.codeChanged({
229+
code: operation.apply(editor.currentModule.code || ''),
230+
moduleShortid: editor.currentModule.shortid,
231+
});
232+
}
233+
} catch (e) {
234+
console.error(e);
235+
}
226236
}
237+
this.props.signals.live.onOperationApplied();
227238
}
228239
}
229240
);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import styled from 'styled-components';
3-
import { observer } from 'mobx-react';
3+
import { inject, observer } from 'mobx-react';
44
import { sortBy } from 'lodash';
55

66
import RecordIcon from 'react-icons/lib/md/fiber-manual-record';
@@ -254,4 +254,4 @@ class LiveInfo extends React.Component {
254254
}
255255
}
256256

257-
export default observer(LiveInfo);
257+
export default inject('store')(observer(LiveInfo));
Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React from 'react';
22
import { inject, observer } from 'mobx-react';
33

4-
import Button from 'app/components/Button';
54
import LiveInfo from './LiveInfo';
65
import LiveButton from './LiveButton';
76

@@ -11,44 +10,42 @@ import {
1110
WorkspaceSubtitle,
1211
} from '../../elements';
1312

14-
const Live = ({ signals, store }) => {
15-
return (
16-
<div>
17-
{store.live.isLive ? (
18-
<LiveInfo
19-
setMode={signals.live.onModeChanged}
20-
addEditor={signals.live.onAddEditorClicked}
21-
removeEditor={signals.live.onRemoveEditorClicked}
22-
isOwner={store.live.isOwner}
23-
roomInfo={store.live.roomInfo}
24-
ownerId={store.editor.currentSandbox.author.id}
25-
currentUserId={store.user.id}
26-
/>
27-
) : (
28-
<React.Fragment>
29-
<Description style={{ marginBottom: '1rem' }}>
30-
Invite others to live edit this sandbox with you. We{"'"}re doing it
31-
live!
32-
</Description>
13+
const Live = ({ signals, store }) => (
14+
<div>
15+
{store.live.isLive ? (
16+
<LiveInfo
17+
setMode={signals.live.onModeChanged}
18+
addEditor={signals.live.onAddEditorClicked}
19+
removeEditor={signals.live.onRemoveEditorClicked}
20+
isOwner={store.live.isOwner}
21+
roomInfo={store.live.roomInfo}
22+
ownerId={store.editor.currentSandbox.author.id}
23+
currentUserId={store.user.id}
24+
/>
25+
) : (
26+
<React.Fragment>
27+
<Description style={{ marginBottom: '1rem' }}>
28+
Invite others to live edit this sandbox with you. We{"'"}re doing it
29+
live!
30+
</Description>
3331

34-
<WorkspaceSubtitle>Create live room</WorkspaceSubtitle>
35-
<Description>
36-
To invite others you need to generate a URL that others can join.
37-
</Description>
38-
<WorkspaceInputContainer>
39-
<LiveButton
40-
onClick={() => {
41-
signals.live.createLiveClicked({
42-
sandboxId: store.editor.currentId,
43-
});
44-
}}
45-
isLoading={store.live.isLoading}
46-
/>
47-
</WorkspaceInputContainer>
48-
</React.Fragment>
49-
)}
50-
</div>
51-
);
52-
};
32+
<WorkspaceSubtitle>Create live room</WorkspaceSubtitle>
33+
<Description>
34+
To invite others you need to generate a URL that others can join.
35+
</Description>
36+
<WorkspaceInputContainer>
37+
<LiveButton
38+
onClick={() => {
39+
signals.live.createLiveClicked({
40+
sandboxId: store.editor.currentId,
41+
});
42+
}}
43+
isLoading={store.live.isLoading}
44+
/>
45+
</WorkspaceInputContainer>
46+
</React.Fragment>
47+
)}
48+
</div>
49+
);
5350

5451
export default inject('signals', 'store')(observer(Live));

packages/app/src/app/pages/Sandbox/SignOutNoticeModal/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ function SignOutNotice({ signals }) {
2323
style={{ marginRight: '.5rem' }}
2424
red
2525
onClick={() => {
26-
signals.closeModal();
26+
signals.modalClosed();
2727
}}
2828
>
2929
Close

packages/app/src/app/pages/Sandbox/ZenModeIntroductionModal/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function ZenModeIntroduction({ signals }) {
2121
<Button
2222
style={{ marginRight: '.5rem' }}
2323
onClick={() => {
24-
signals.closeModal();
24+
signals.modalClosed();
2525
}}
2626
>
2727
Close
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import styled from 'styled-components';
2+
3+
export const Container = styled.div`
4+
background-color: ${props => props.theme.background};
5+
padding: 1rem;
6+
margin: 0;
7+
color: rgba(255, 255, 255, 0.8);
8+
`;
9+
10+
export const Heading = styled.h2`
11+
margin-top: 0;
12+
`;
13+
14+
export const Explanation = styled.p`
15+
line-height: 1.3;
16+
margin-bottom: 2rem;
17+
`;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react';
2+
import { inject } from 'mobx-react';
3+
4+
import Button from 'app/components/Button';
5+
import Row from 'common/components/flex/Row';
6+
7+
import { Container, Heading, Explanation } from './elements';
8+
9+
function LiveModeEnded({ signals }) {
10+
return (
11+
<Container>
12+
<Heading>The Live session has ended</Heading>
13+
<Explanation>
14+
The host has ended the live session, you can continue working by forking
15+
the sandbox or by creating a new sandbox.
16+
</Explanation>
17+
18+
<Row justifyContent="space-around">
19+
<Button href="/s">Create Sandbox</Button>
20+
<Button
21+
onClick={() => {
22+
signals.editor.forkSandboxClicked();
23+
signals.modalClosed();
24+
}}
25+
>
26+
Fork Sandbox
27+
</Button>
28+
</Row>
29+
</Container>
30+
);
31+
}
32+
33+
export default inject('signals')(LiveModeEnded);

packages/app/src/app/pages/common/Modals/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import PRModal from './PRModal';
1313
import SelectSandboxModal from './SelectSandboxModal';
1414
import SearchDependenciesModal from './SearchDependenciesModal';
1515
import DeleteProfileSandboxModal from './DeleteProfileSandboxModal';
16+
import LiveSessionEndedModal from './LiveSessionEndedModal';
1617

1718
const modals = {
1819
preferences: {
@@ -59,6 +60,10 @@ const modals = {
5960
Component: SearchDependenciesModal,
6061
width: 600,
6162
},
63+
liveSessionEnded: {
64+
Component: LiveSessionEndedModal,
65+
width: 600,
66+
},
6267
};
6368

6469
function Modals({ store, signals }) {

0 commit comments

Comments
 (0)