Skip to content

Commit 68c062f

Browse files
committed
Refactor redux stores
1 parent a056b26 commit 68c062f

File tree

12 files changed

+192
-174
lines changed

12 files changed

+192
-174
lines changed

src/backend/tracers/js/worker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const sandbox = code => {
77
eval(code);
88
};
99

10-
onmessage = e => { // TODO: stop after the first delay() on the initial run
10+
onmessage = e => {
1111
const lines = e.data.split('\n').map((line, i) => line.replace(/(.+\. *delay *)(\( *\))/g, `$1(${i})`));
1212
const { code } = Babel.transform(lines.join('\n'), { presets: ['es2015'] });
1313
sandbox(code);

src/frontend/common/util.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ const createProjectFile = (name, content) => createFile(name, content, [{
3030

3131
const createUserFile = (name, content) => createFile(name, content, undefined);
3232

33+
const isSaved = ({ titles, files, lastTitles, lastFiles }) => {
34+
const serialize = (titles, files) => JSON.stringify({
35+
titles,
36+
files: files.map(({ name, content }) => ({ name, content })),
37+
});
38+
return serialize(titles, files) === serialize(lastTitles, lastFiles);
39+
};
40+
3341
export {
3442
classes,
3543
distance,
@@ -38,4 +46,5 @@ export {
3846
createFile,
3947
createProjectFile,
4048
createUserFile,
49+
isSaved,
4150
};

src/frontend/components/App/index.jsx

Lines changed: 14 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ import Cookies from 'js-cookie';
33
import { connect } from 'react-redux';
44
import Promise from 'bluebird';
55
import { Helmet } from 'react-helmet';
6-
import AutosizeInput from 'react-input-autosize';
76
import queryString from 'query-string';
8-
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
9-
import faPlus from '@fortawesome/fontawesome-free-solid/faPlus';
107
import {
118
BaseComponent,
129
CodeEditor,
@@ -32,7 +29,6 @@ class App extends BaseComponent {
3229
this.state = {
3330
navigatorOpened: true,
3431
workspaceWeights: [1, 2, 2],
35-
editorTabIndex: -1,
3632
};
3733

3834
this.codeEditorRef = React.createRef();
@@ -79,11 +75,12 @@ class App extends BaseComponent {
7975

8076
toggleHistoryBlock(enable = !this.unblock) {
8177
if (enable) {
78+
const { saved } = this.props.current;
8279
const warningMessage = 'Are you sure you want to discard changes?';
83-
window.onbeforeunload = () => this.isSaved() ? undefined : warningMessage;
80+
window.onbeforeunload = () => saved ? undefined : warningMessage;
8481
this.unblock = this.props.history.block((location) => {
8582
if (location.pathname === this.props.location.pathname) return;
86-
if (!this.isSaved()) return warningMessage;
83+
if (!saved) return warningMessage;
8784
});
8885
} else {
8986
window.onbeforeunload = undefined;
@@ -189,97 +186,44 @@ class App extends BaseComponent {
189186
selectDefaultTab() {
190187
const { ext } = this.props.env;
191188
const { files } = this.props.current;
192-
let editorTabIndex = files.findIndex(file => extension(file.name) === 'json');
193-
if (!~editorTabIndex) files.findIndex(file => extension(file.name) === ext);
194-
if (!~editorTabIndex) editorTabIndex = files.findIndex(file => exts.includes(extension(file.name)));
195-
if (!~editorTabIndex) editorTabIndex = Math.min(0, files.length - 1);
196-
this.handleChangeEditorTabIndex(editorTabIndex);
189+
const editingFile = files.find(file => extension(file.name) === 'json') ||
190+
files.find(file => extension(file.name) === ext) ||
191+
files.find(file => exts.includes(extension(file.name))) ||
192+
files[files.length - 1];
193+
this.props.setEditingFile(editingFile);
197194
}
198195

199196
handleChangeWorkspaceWeights(workspaceWeights) {
200197
this.setState({ workspaceWeights });
201198
this.codeEditorRef.current.getWrappedInstance().handleResize();
202199
}
203200

204-
handleChangeEditorTabIndex(editorTabIndex) {
205-
const { files } = this.props.current;
206-
if (editorTabIndex === files.length) this.handleAddFile();
207-
this.setState({ editorTabIndex });
208-
this.props.shouldBuild();
209-
}
210-
211-
handleAddFile() {
212-
const { ext } = this.props.env;
213-
const { files } = this.props.current;
214-
const language = languages.find(language => language.ext === ext);
215-
const file = { ...language.skeleton };
216-
let count = 0;
217-
while (files.some(existingFile => existingFile.name === file.name)) file.name = `code-${++count}.${ext}`;
218-
this.props.addFile(file);
219-
}
220-
221-
handleRenameFile(e) {
222-
const { value } = e.target;
223-
const { editorTabIndex } = this.state;
224-
this.props.renameFile(editorTabIndex, value);
225-
}
226-
227-
handleDeleteFile() {
228-
const { editorTabIndex } = this.state;
229-
const { files } = this.props.current;
230-
this.handleChangeEditorTabIndex(Math.min(editorTabIndex, files.length - 2));
231-
this.props.deleteFile(editorTabIndex);
232-
}
233-
234201
toggleNavigatorOpened(navigatorOpened = !this.state.navigatorOpened) {
235202
this.setState({ navigatorOpened });
236203
}
237204

238-
isSaved() {
239-
const { titles, files, lastTitles, lastFiles } = this.props.current;
240-
const serialize = (titles, files) => JSON.stringify({
241-
titles,
242-
files: files.map(({ name, content }) => ({ name, content })),
243-
});
244-
return serialize(titles, files) === serialize(lastTitles, lastFiles);
245-
}
246-
247205
render() {
248-
const { navigatorOpened, workspaceWeights, editorTabIndex } = this.state;
206+
const { navigatorOpened, workspaceWeights } = this.state;
249207

250-
const { files, titles, description } = this.props.current;
251-
const saved = this.isSaved();
208+
const { titles, description, saved } = this.props.current;
252209
const title = `${saved ? '' : '(Unsaved) '}${titles.join(' - ')}`;
253-
const file = files[editorTabIndex];
254-
255-
const editorTitles = files.map(file => file.name);
256-
if (file) {
257-
editorTitles[editorTabIndex] = (
258-
<AutosizeInput className={styles.input_title} value={file.name}
259-
onClick={e => e.stopPropagation()} onChange={e => this.handleRenameFile(e)} />
260-
);
261-
}
262-
editorTitles.push(
263-
<FontAwesomeIcon fixedWidth icon={faPlus} />,
264-
);
265210

266211
return (
267212
<div className={styles.app}>
268213
<Helmet>
269214
<title>{title}</title>
270215
<meta name="description" content={description} />
271216
</Helmet>
272-
<Header className={styles.header} onClickTitleBar={() => this.toggleNavigatorOpened()} saved={saved}
273-
navigatorOpened={navigatorOpened} loadScratchPapers={() => this.loadScratchPapers()} file={file}
217+
<Header className={styles.header} onClickTitleBar={() => this.toggleNavigatorOpened()}
218+
navigatorOpened={navigatorOpened} loadScratchPapers={() => this.loadScratchPapers()}
274219
ignoreHistoryBlock={this.ignoreHistoryBlock} />
275220
<ResizableContainer className={styles.workspace} horizontal weights={workspaceWeights}
276221
visibles={[navigatorOpened, true, true]}
277222
onChangeWeights={weights => this.handleChangeWorkspaceWeights(weights)}>
278223
<Navigator />
279224
<VisualizationViewer className={styles.visualization_viewer} />
280-
<TabContainer className={styles.editor_tab_container} titles={editorTitles} tabIndex={editorTabIndex}
281-
onChangeTabIndex={tabIndex => this.handleChangeEditorTabIndex(tabIndex)}>
282-
<CodeEditor ref={this.codeEditorRef} file={file} onClickDelete={() => this.handleDeleteFile()} />
225+
<TabContainer className={styles.editor_tab_container}>
226+
<CodeEditor ref={this.codeEditorRef} />
283227
</TabContainer>
284228
</ResizableContainer>
285229
<ToastContainer className={styles.toast_container} />

src/frontend/components/App/stylesheet.scss

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,6 @@ button {
6060
}
6161

6262
.editor_tab_container {
63-
.input_title {
64-
input {
65-
&:hover,
66-
&:focus {
67-
margin: -4px;
68-
padding: 4px;
69-
background-color: $theme-normal;
70-
}
71-
}
72-
}
7363
}
7464
}
7565

src/frontend/components/CodeEditor/index.jsx

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,27 @@ import { languages } from '/common/config';
88
import { Button, Ellipsis, FoldableAceEditor } from '/components';
99
import styles from './stylesheet.scss';
1010

11-
@connect(({ env, player }) => ({ env, player }), actions, null, { withRef: true })
11+
@connect(({ current, env, player }) => ({ current, env, player }), actions, null, { withRef: true })
1212
class CodeEditor extends React.Component {
1313
constructor(props) {
1414
super(props);
1515

1616
this.aceEditorRef = React.createRef();
1717
}
1818

19-
handleChangeCode(code) {
20-
const { file } = this.props;
21-
this.props.modifyFile({ ...file, content: code });
22-
if (extension(file.name) === 'md') this.props.shouldBuild();
23-
}
24-
2519
handleResize() {
2620
this.aceEditorRef.current.editor.resize();
2721
}
2822

2923
render() {
30-
const { className, file, onClickDelete } = this.props;
24+
const { className } = this.props;
25+
const { editingFile } = this.props.current;
3126
const { user } = this.props.env;
32-
const { lineIndicator, buildAt } = this.props.player;
27+
const { lineIndicator } = this.props.player;
3328

34-
if (!file) return null;
29+
if (!editingFile) return null;
3530

36-
const fileExt = extension(file.name);
31+
const fileExt = extension(editingFile.name);
3732
const language = languages.find(language => language.ext === fileExt);
3833
const mode = language ? language.mode :
3934
fileExt === 'md' ? 'markdown' :
@@ -49,7 +44,7 @@ class CodeEditor extends React.Component {
4944
theme="tomorrow_night_eighties"
5045
name="code_editor"
5146
editorProps={{ $blockScrolling: true }}
52-
onChange={code => this.handleChangeCode(code)}
47+
onChange={code => this.props.modifyFile(editingFile, code)}
5348
markers={lineIndicator ? [{
5449
startRow: lineIndicator.lineNumber,
5550
startCol: 0,
@@ -60,12 +55,11 @@ class CodeEditor extends React.Component {
6055
inFront: true,
6156
_key: lineIndicator.cursor,
6257
}] : []}
63-
foldAt={buildAt}
64-
value={file.content} />
58+
value={editingFile.content} />
6559
<div className={classes(styles.contributors_viewer, className)}>
6660
<span className={classes(styles.contributor, styles.label)}>Contributed by</span>
6761
{
68-
(file.contributors || [user || { login: 'guest', avatar_url: faUser }]).map(contributor => (
62+
(editingFile.contributors || [user || { login: 'guest', avatar_url: faUser }]).map(contributor => (
6963
<Button className={styles.contributor} icon={contributor.avatar_url} key={contributor.login}
7064
href={`https://github.com/${contributor.login}`}>
7165
{contributor.login}
@@ -74,8 +68,8 @@ class CodeEditor extends React.Component {
7468
}
7569
<div className={styles.empty}>
7670
<div className={styles.empty} />
77-
<Button className={styles.delete} icon={faTrashAlt} primary onClick={onClickDelete}
78-
confirmNeeded>
71+
<Button className={styles.delete} icon={faTrashAlt} primary confirmNeeded
72+
onClick={() => this.props.deleteFile(editingFile)}>
7973
<Ellipsis>Delete File</Ellipsis>
8074
</Button>
8175
</div>

src/frontend/components/FoldableAceEditor/index.jsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react';
2+
import { connect } from 'react-redux';
23
import AceEditor from 'react-ace';
34
import 'brace/mode/plain_text';
45
import 'brace/mode/markdown';
@@ -8,19 +9,23 @@ import 'brace/mode/c_cpp';
89
import 'brace/mode/java';
910
import 'brace/theme/tomorrow_night_eighties';
1011
import 'brace/ext/searchbox';
12+
import { actions } from '/reducers';
1113

14+
@connect(({ current }) => ({ current }), actions)
1215
class FoldableAceEditor extends AceEditor {
1316
componentDidMount() {
1417
super.componentDidMount();
1518

16-
this.foldTracers();
19+
const { shouldBuild } = this.props.current;
20+
if (shouldBuild) this.foldTracers();
1721
}
1822

1923
componentDidUpdate(prevProps, prevState, snapshot) {
2024
super.componentDidUpdate(prevProps, prevState, snapshot);
2125

22-
if (prevProps.foldAt !== this.props.foldAt) {
23-
this.foldTracers();
26+
const { editingFile, shouldBuild } = this.props.current;
27+
if (editingFile !== prevProps.current.editingFile) {
28+
if (shouldBuild) this.foldTracers();
2429
}
2530
}
2631

src/frontend/components/Header/index.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ class Header extends BaseComponent {
110110
}
111111

112112
render() {
113-
const { className, onClickTitleBar, navigatorOpened, saved, file } = this.props;
114-
const { scratchPaper, titles } = this.props.current;
113+
const { className, onClickTitleBar, navigatorOpened } = this.props;
114+
const { scratchPaper, titles, saved } = this.props.current;
115115
const { ext, user } = this.props.env;
116116

117117
const permitted = this.hasPermission();
@@ -174,7 +174,7 @@ class Header extends BaseComponent {
174174
</div>
175175
</Button>
176176
</div>
177-
<Player className={styles.section} file={file} />
177+
<Player className={styles.section} />
178178
</div>
179179
</header>
180180
);

src/frontend/components/Player/index.jsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { actions } from '/reducers';
1313
import { BaseComponent, Button, ProgressBar } from '/components';
1414
import styles from './stylesheet.scss';
1515

16-
@connect(({ player }) => ({ player }), actions)
16+
@connect(({ current, player }) => ({ current, player }), actions)
1717
class Player extends BaseComponent {
1818
constructor(props) {
1919
super(props);
@@ -30,15 +30,14 @@ class Player extends BaseComponent {
3030
}
3131

3232
componentDidMount() {
33-
const { file } = this.props;
34-
this.build(file);
33+
const { editingFile, shouldBuild } = this.props.current;
34+
if (shouldBuild) this.build(editingFile);
3535
}
3636

3737
componentWillReceiveProps(nextProps) {
38-
const { file } = nextProps;
39-
const { buildAt } = nextProps.player;
40-
if (buildAt !== this.props.player.buildAt) {
41-
this.build(file);
38+
const { editingFile, shouldBuild } = nextProps.current;
39+
if (editingFile !== this.props.current.editingFile) {
40+
if (shouldBuild) this.build(editingFile);
4241
}
4342
}
4443

@@ -145,13 +144,15 @@ class Player extends BaseComponent {
145144
}
146145

147146
render() {
148-
const { className, file } = this.props;
147+
const { className } = this.props;
148+
const { editingFile } = this.props.current;
149149
const { chunks, cursor } = this.props.player;
150150
const { speed, playing, building } = this.state;
151151

152152
return (
153153
<div className={classes(styles.player, className)}>
154-
<Button icon={faWrench} primary disabled={building} inProgress={building} onClick={() => this.build(file)}>
154+
<Button icon={faWrench} primary disabled={building} inProgress={building}
155+
onClick={() => this.build(editingFile)}>
155156
{building ? 'Building' : 'Build'}
156157
</Button>
157158
{

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy