Skip to content

Commit 4c5b9bb

Browse files
author
Ives van Hoorne
committed
Live progress
1 parent 975ea37 commit 4c5b9bb

File tree

15 files changed

+318
-136
lines changed

15 files changed

+318
-136
lines changed

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

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -488,19 +488,38 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
488488

489489
userClassesGenerated = {};
490490
userSelectionDecorations = {};
491-
userSelections = [];
492491
updateUserSelections = (
493-
userSelections: Array<{
494-
userId: string,
495-
name: string,
496-
selection: any,
497-
color: Array<number>,
498-
}>
492+
userSelections: Array<
493+
| {
494+
userId: string,
495+
selection: null,
496+
}
497+
| {
498+
userId: string,
499+
name: string,
500+
selection: any,
501+
color: Array<number>,
502+
}
503+
>
499504
) => {
500-
this.userSelections = userSelections;
501505
const lines = this.editor.getModel().getLinesContent();
502506

503507
userSelections.forEach(data => {
508+
if (data.selection === null) {
509+
const { userId } = data;
510+
511+
const decorationId = this.currentModule.shortid + userId;
512+
this.userSelectionDecorations[
513+
decorationId
514+
] = this.editor.deltaDecorations(
515+
this.userSelectionDecorations[decorationId] || [],
516+
[],
517+
data.userId
518+
);
519+
520+
return;
521+
}
522+
504523
const decorations = [];
505524
const { selection, color, userId, name } = data;
506525

@@ -559,11 +578,12 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
559578
borderBottomLeftRadius: 0,
560579
fontSize: '.75rem',
561580
fontWeight: 600,
581+
userSelect: 'none',
582+
pointerEvents: 'none',
562583
};
563584
this.userClassesGenerated[cursorClassName] = `${css({
564585
backgroundColor: `rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.8)`,
565586
width: '2px !important',
566-
marginLeft: -1,
567587
cursor: 'text',
568588
zIndex: 30,
569589
':before': {
@@ -588,7 +608,6 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
588608
this.userClassesGenerated[secondaryCursorClassName] = `${css({
589609
backgroundColor: `rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.6)`,
590610
width: '2px !important',
591-
marginLeft: -1,
592611
})}`;
593612
}
594613

@@ -632,14 +651,17 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
632651
}
633652
}
634653

635-
this.userSelectionDecorations[
636-
this.currentModule.shortid + userId
637-
] = this.editor.deltaDecorations(
638-
this.userSelectionDecorations[this.currentModule.shortid + userId] ||
639-
[],
640-
decorations,
641-
userId
642-
);
654+
// Allow new model to attach in case it's attaching
655+
requestAnimationFrame(() => {
656+
const decorationId = this.currentModule.shortid + userId;
657+
this.userSelectionDecorations[
658+
decorationId
659+
] = this.editor.deltaDecorations(
660+
this.userSelectionDecorations[decorationId] || [],
661+
decorations,
662+
userId
663+
);
664+
});
643665
});
644666
};
645667

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,21 @@ class EditorPreview extends React.Component<Props, State> {
228228
}
229229
);
230230

231-
const disposeLiveSelectionHandler = autorun(() => {
231+
const updateUserSelections = () => {
232232
if (store.editor.pendingUserSelections) {
233233
if (editor.updateUserSelections) {
234-
editor.updateUserSelections(store.editor.pendingUserSelections);
234+
requestAnimationFrame(() => {
235+
editor.updateUserSelections(store.editor.pendingUserSelections);
236+
this.props.signals.live.onSelectionDecorationsApplied();
237+
});
235238
}
236239
}
237-
});
240+
};
241+
const disposeLiveSelectionHandler = reaction(
242+
() => store.editor.pendingUserSelections.map(x => x),
243+
updateUserSelections
244+
);
245+
updateUserSelections();
238246

239247
const disposeModuleHandler = reaction(
240248
() => [store.editor.currentModule, store.editor.currentModule.code],
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React from 'react';
2+
import { inject, observer } from 'mobx-react';
3+
import getType from 'app/utils/get-type';
4+
import validateTitle from '../validateTitle';
5+
import Entry from '../Entry';
6+
7+
class ModuleEntry extends React.Component {
8+
validateTitle = (id, title) => {
9+
const { directories, modules } = this.props.store.editor.currentSandbox;
10+
return !!validateTitle(id, title, [...directories, ...modules]);
11+
};
12+
13+
render() {
14+
const {
15+
store,
16+
module,
17+
setCurrentModule,
18+
markTabsNotDirty,
19+
depth,
20+
renameModule,
21+
deleteEntry,
22+
} = this.props;
23+
const currentModuleShortid = store.editor.currentModuleShortid;
24+
const mainModuleId = store.editor.mainModule.id;
25+
26+
const isActive = module.shortid === currentModuleShortid;
27+
const isMainModule = module.id === mainModuleId;
28+
const type = getType(module.title, module.code);
29+
30+
const hasError = store.editor.errors.filter(
31+
error => error.moduleId === module.id
32+
).length;
33+
34+
return (
35+
<Entry
36+
id={module.id}
37+
shortid={module.shortid}
38+
title={module.title}
39+
depth={depth + 1}
40+
active={isActive}
41+
type={type || 'function'}
42+
rename={isMainModule ? undefined : renameModule}
43+
deleteEntry={isMainModule ? undefined : deleteEntry}
44+
isNotSynced={!store.editor.isModuleSynced(module.shortid)}
45+
renameValidator={this.validateTitle}
46+
setCurrentModule={setCurrentModule}
47+
isMainModule={isMainModule}
48+
moduleHasError={hasError}
49+
markTabsNotDirty={markTabsNotDirty}
50+
/>
51+
);
52+
}
53+
}
54+
55+
export default inject('store')(observer(ModuleEntry));

packages/app/src/app/pages/Sandbox/Editor/Workspace/Files/DirectoryEntry/DirectoryChildren/index.js

Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,45 @@
11
import * as React from 'react';
22
import { inject, observer } from 'mobx-react';
3-
import getType from 'app/utils/get-type';
3+
import { sortBy } from 'lodash';
44
import validateTitle from '../validateTitle';
5-
import Entry from '../Entry';
5+
import ModuleEntry from './ModuleEntry';
66
import DirectoryEntry from '../';
77

88
class DirectoryChildren extends React.Component {
99
validateTitle = (id, title) => {
10-
const { directories, modules } = this.props;
10+
const { directories, modules } = this.props.store.editor.currentSandbox;
1111
return !!validateTitle(id, title, [...directories, ...modules]);
1212
};
1313

1414
render() {
1515
const {
1616
depth = 0,
1717
renameModule,
18-
openMenu,
1918
setCurrentModule,
20-
directories,
2119
parentShortid,
22-
sandboxId,
23-
mainModuleId,
24-
sandboxTemplate,
25-
modules,
2620
deleteEntry,
27-
currentModuleId,
2821
isInProjectView,
2922
markTabsNotDirty,
23+
store,
24+
} = this.props;
25+
26+
const {
27+
id: sandboxId,
28+
modules,
29+
directories,
30+
template: sandboxTemplate,
31+
} = store.editor.currentSandbox;
32+
const {
33+
mainModule,
34+
currentModuleShortid,
3035
errors,
3136
corrections,
32-
} = this.props;
37+
} = store.editor;
38+
const mainModuleId = mainModule.id;
3339

3440
return (
3541
<div>
36-
{directories
42+
{sortBy(directories, 'title')
3743
.filter(x => x.directoryShortid === parentShortid)
3844
.map(dir => (
3945
<DirectoryEntry
@@ -48,43 +54,27 @@ class DirectoryChildren extends React.Component {
4854
mainModuleId={mainModuleId}
4955
modules={modules}
5056
directories={directories}
51-
currentModuleId={currentModuleId}
57+
currentModuleShortid={currentModuleShortid}
5258
isInProjectView={isInProjectView}
5359
markTabsNotDirty={markTabsNotDirty}
5460
errors={errors}
5561
corrections={corrections}
5662
/>
5763
))}
58-
{modules.filter(x => x.directoryShortid === parentShortid).map(m => {
59-
const isActive = m.id === currentModuleId;
60-
const mainModule = m.id === mainModuleId;
61-
const type = getType(m.title, m.code);
62-
63-
const hasError =
64-
m && errors.filter(error => error.moduleId === m.id).length;
65-
66-
return (
67-
<Entry
68-
key={m.id}
69-
id={m.id}
70-
shortid={m.shortid}
71-
title={m.title}
72-
depth={depth + 1}
73-
active={isActive}
74-
type={type || 'function'}
75-
rename={mainModule ? undefined : renameModule}
76-
openMenu={openMenu}
77-
deleteEntry={mainModule ? undefined : deleteEntry}
78-
isNotSynced={!this.props.store.editor.isModuleSynced(m.shortid)}
79-
renameValidator={this.validateTitle}
80-
setCurrentModule={setCurrentModule}
81-
isInProjectView={isInProjectView}
82-
isMainModule={mainModule}
83-
moduleHasError={hasError}
84-
markTabsNotDirty={markTabsNotDirty}
85-
/>
86-
);
87-
})}
64+
{sortBy(
65+
modules.filter(x => x.directoryShortid === parentShortid),
66+
'title'
67+
).map(m => (
68+
<ModuleEntry
69+
key={m.id}
70+
module={m}
71+
depth={depth}
72+
setCurrentModule={setCurrentModule}
73+
markTabsNotDirty={markTabsNotDirty}
74+
renameModule={renameModule}
75+
deleteEntry={deleteEntry}
76+
/>
77+
))}
8878
</div>
8979
);
9080
}

0 commit comments

Comments
 (0)