Skip to content

Commit 1a939a4

Browse files
authored
Merge branch 'develop' into refactor/modal
2 parents 403a19e + 2255bf1 commit 1a939a4

File tree

10 files changed

+81
-70
lines changed

10 files changed

+81
-70
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ Learn more about [our community](https://p5js.org/community/) and read our commu
1616

1717
Make your first sketch in the [p5.js Editor](https://editor.p5js.org/)! Learn more about sketching with p5.js on the [Get Started](https://p5js.org/get-started/) and find everything you can do in the [Reference](https://p5js.org/reference/). You can also look at [examples](https://editor.p5js.org/p5/sketches) and remix them in the p5.js Editor.
1818

19+
## Setting Up the Development Environment
20+
21+
- Refer to [this documentation for setting up your environment](https://github.com/processing/p5.js-web-editor/blob/develop/contributor_docs/installation.md)
22+
23+
24+
1925
## Issues
2026

2127
If you have found a bug in the p5.js Web Editor, you can file it under the ["issues" tab](https://github.com/processing/p5.js-web-editor/issues). You can also request new features here. A set of templates for reporting issues and requesting features are provided to assist you (and us!). The p5.js Editor is maintained mostly by volunteers, so we thank you for your patience as we try to address your issues as soon as we can. Please post bugs and feature requests in the correct repository if you can:

client/components/Nav.jsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ class Nav extends React.PureComponent {
278278
onClick={this.toggleDropdownForFile}
279279
onBlur={this.handleBlur}
280280
onFocus={this.clearHideTimeout}
281+
title="File"
281282
onMouseOver={() => {
282283
if (this.state.dropdownOpen !== 'none') {
283284
this.setDropdown('file');
@@ -396,6 +397,7 @@ class Nav extends React.PureComponent {
396397
onClick={this.toggleDropdownForEdit}
397398
onBlur={this.handleBlur}
398399
onFocus={this.clearHideTimeout}
400+
title="Edit"
399401
onMouseOver={() => {
400402
if (this.state.dropdownOpen !== 'none') {
401403
this.setDropdown('edit');
@@ -454,6 +456,7 @@ class Nav extends React.PureComponent {
454456
onClick={this.toggleDropdownForSketch}
455457
onBlur={this.handleBlur}
456458
onFocus={this.clearHideTimeout}
459+
title="Sketch"
457460
onMouseOver={() => {
458461
if (this.state.dropdownOpen !== 'none') {
459462
this.setDropdown('sketch');
@@ -539,6 +542,7 @@ class Nav extends React.PureComponent {
539542
onClick={this.toggleDropdownForHelp}
540543
onBlur={this.handleBlur}
541544
onFocus={this.clearHideTimeout}
545+
title="Help"
542546
onMouseOver={() => {
543547
if (this.state.dropdownOpen !== 'none') {
544548
this.setDropdown('help');
@@ -600,6 +604,7 @@ class Nav extends React.PureComponent {
600604
onClick={this.toggleDropdownForLang}
601605
onBlur={this.handleBlur}
602606
onFocus={this.clearHideTimeout}
607+
title="Language"
603608
onMouseOver={() => {
604609
if (this.state.dropdownOpen !== 'none') {
605610
this.setDropdown('lang');
@@ -760,15 +765,15 @@ class Nav extends React.PureComponent {
760765
this.renderLanguageMenu(navDropdownState)}
761766
<li className="nav__item">
762767
<Link to="/login" className="nav__auth-button">
763-
<span className="nav__item-header">
768+
<span className="nav__item-header" title="Login">
764769
{this.props.t('Nav.Login')}
765770
</span>
766771
</Link>
767772
</li>
768773
<span className="nav__item-or">{this.props.t('Nav.LoginOr')}</span>
769774
<li className="nav__item">
770775
<Link to="/signup" className="nav__auth-button">
771-
<span className="nav__item-header">
776+
<span className="nav__item-header" title="SignUp">
772777
{this.props.t('Nav.SignUp')}
773778
</span>
774779
</Link>

client/components/__snapshots__/Nav.unit.test.jsx.snap

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ exports[`Nav renders correctly 1`] = `
2222
<li
2323
class="nav__item"
2424
>
25-
<button>
25+
<button
26+
title="File"
27+
>
2628
<span
2729
class="nav__item-header"
2830
/>
@@ -65,7 +67,9 @@ exports[`Nav renders correctly 1`] = `
6567
<li
6668
class="nav__item"
6769
>
68-
<button>
70+
<button
71+
title="Edit"
72+
>
6973
<span
7074
class="nav__item-header"
7175
/>
@@ -116,7 +120,9 @@ exports[`Nav renders correctly 1`] = `
116120
<li
117121
class="nav__item"
118122
>
119-
<button>
123+
<button
124+
title="Sketch"
125+
>
120126
<span
121127
class="nav__item-header"
122128
/>
@@ -166,7 +172,9 @@ exports[`Nav renders correctly 1`] = `
166172
<li
167173
class="nav__item"
168174
>
169-
<button>
175+
<button
176+
title="Help"
177+
>
170178
<span
171179
class="nav__item-header"
172180
/>

client/modules/IDE/components/Console.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ const Console = () => {
267267
style={{ fontSize }}
268268
>
269269
<ConsoleFeed
270+
variant={theme === 'light' ? 'light' : 'dark'}
270271
styles={getConsoleFeedStyle(theme, fontSize)}
271272
logs={consoleEvents}
272273
key={`${theme}-${fontSize}`}

client/modules/IDE/components/Editor.jsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ import UnsavedChangesDotIcon from '../../../images/unsaved-changes-dot.svg';
5151
import RightArrowIcon from '../../../images/right-arrow.svg';
5252
import LeftArrowIcon from '../../../images/left-arrow.svg';
5353
import { getHTMLFile } from '../reducers/files';
54-
import { getIsUserOwner } from '../selectors/users';
5554

5655
import * as FileActions from '../actions/files';
5756
import * as IDEActions from '../actions/ide';
@@ -420,10 +419,7 @@ class Editor extends React.Component {
420419
) : null}
421420
</span>
422421
</span>
423-
<Timer
424-
projectSavedTime={this.props.projectSavedTime}
425-
isUserOwner={this.props.isUserOwner}
426-
/>
422+
<Timer />
427423
</div>
428424
</header>
429425
<article
@@ -474,7 +470,6 @@ Editor.propTypes = {
474470
isPlaying: PropTypes.bool.isRequired,
475471
theme: PropTypes.string.isRequired,
476472
unsavedChanges: PropTypes.bool.isRequired,
477-
projectSavedTime: PropTypes.string.isRequired,
478473
files: PropTypes.arrayOf(
479474
PropTypes.shape({
480475
id: PropTypes.string.isRequired,
@@ -485,7 +480,6 @@ Editor.propTypes = {
485480
isExpanded: PropTypes.bool.isRequired,
486481
collapseSidebar: PropTypes.func.isRequired,
487482
expandSidebar: PropTypes.func.isRequired,
488-
isUserOwner: PropTypes.bool.isRequired,
489483
clearConsole: PropTypes.func.isRequired,
490484
// showRuntimeErrorWarning: PropTypes.func.isRequired,
491485
hideRuntimeErrorWarning: PropTypes.func.isRequired,
@@ -516,9 +510,7 @@ function mapStateToProps(state) {
516510
...state.ide,
517511
...state.project,
518512
...state.editorAccessibility,
519-
isExpanded: state.ide.sidebarIsExpanded,
520-
projectSavedTime: state.project.updatedAt,
521-
isUserOwner: getIsUserOwner(state)
513+
isExpanded: state.ide.sidebarIsExpanded
522514
};
523515
}
524516

client/modules/IDE/components/Preferences/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ class Preferences extends React.Component {
5959
}
6060

6161
decreaseFontSize() {
62-
const newValue = this.state.fontSize - 2;
62+
const newValue = Number(this.state.fontSize) - 2;
6363
this.setFontSize(newValue);
6464
}
6565

6666
increaseFontSize() {
67-
const newValue = this.state.fontSize + 2;
67+
const newValue = Number(this.state.fontSize) + 2;
6868
this.setFontSize(newValue);
6969
}
7070

Lines changed: 38 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,46 @@
11
import classNames from 'classnames';
2-
import PropTypes from 'prop-types';
3-
import React from 'react';
4-
import { withTranslation } from 'react-i18next';
2+
import React, { useEffect, useState } from 'react';
3+
import { useTranslation } from 'react-i18next';
4+
import { useSelector } from 'react-redux';
55

66
import dates from '../../../utils/formatDate';
7+
import useInterval from '../hooks/useInterval';
8+
import { getIsUserOwner } from '../selectors/users';
79

8-
class Timer extends React.Component {
9-
constructor(props) {
10-
super(props);
11-
this.showSavedTime = this.showSavedTime.bind(this);
12-
}
13-
14-
componentDidMount() {
15-
this.interval = setInterval(() => this.forceUpdate(), 10000);
16-
}
17-
18-
componentWillUnmount() {
19-
if (this.interval) {
20-
clearInterval(this.interval);
21-
}
22-
}
23-
24-
showSavedTime() {
25-
const timeAgo = dates.distanceInWordsToNow(this.props.projectSavedTime);
26-
return this.props.t('Timer.SavedAgo', { timeAgo });
27-
}
28-
29-
render() {
30-
const timerClass = classNames({
31-
'timer__saved-time': true,
32-
'timer__saved-time--notOwner': !this.props.isUserOwner
33-
});
34-
return (
35-
<span className={timerClass}>
36-
{this.props.projectSavedTime !== '' ? this.showSavedTime() : null}
37-
</span>
38-
);
39-
}
40-
}
10+
const Timer = () => {
11+
const projectSavedTime = useSelector((state) => state.project.updatedAt);
12+
const isUserOwner = useSelector(getIsUserOwner);
4113

42-
Timer.propTypes = {
43-
projectSavedTime: PropTypes.string.isRequired,
44-
isUserOwner: PropTypes.bool,
45-
t: PropTypes.func.isRequired
46-
};
14+
const { t } = useTranslation();
4715

48-
Timer.defaultProps = {
49-
isUserOwner: false
16+
const [timeAgo, setTimeAgo] = useState('');
17+
18+
// Update immediately upon saving.
19+
useEffect(() => {
20+
setTimeAgo(
21+
projectSavedTime ? dates.distanceInWordsToNow(projectSavedTime) : ''
22+
);
23+
}, [projectSavedTime]);
24+
25+
// Update every 10 seconds.
26+
useInterval(
27+
() =>
28+
setTimeAgo(
29+
projectSavedTime ? dates.distanceInWordsToNow(projectSavedTime) : ''
30+
),
31+
10000
32+
);
33+
34+
const timerClass = classNames({
35+
'timer__saved-time': true,
36+
'timer__saved-time--notOwner': !isUserOwner
37+
});
38+
39+
return (
40+
<span className={timerClass}>
41+
{timeAgo ? t('Timer.SavedAgo', { timeAgo }) : null}
42+
</span>
43+
);
5044
};
5145

52-
export default withTranslation()(Timer);
46+
export default Timer;

client/styles/components/_loader.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
display: flex;
55
justify-content: center;
66
align-items: center;
7+
@include themify() {
8+
background-color: getThemifyVariable('background-color');
9+
}
710
}
811

912

client/utils/p5-javascript.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
158158
} else if (wordRE.test(ch)) {
159159
stream.eatWhile(wordRE);
160160
var word = stream.current()
161-
if (state.lastType != ".") {
162-
if (keywords.propertyIsEnumerable(word)) {
163-
var kw = keywords[word]
164-
return ret(kw.type, kw.style, word)
165-
}
166-
if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
167-
return ret("async", "keyword", word)
161+
if (keywords.propertyIsEnumerable(word)) {
162+
var kw = keywords[word]
163+
return ret(kw.type, kw.style, word)
168164
}
165+
if (state.lastType != "." && word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
166+
return ret("async", "keyword", word)
169167
return ret("variable", "variable", word)
170168
}
171169
}
@@ -285,6 +283,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
285283
if (combinator(type, content)) {
286284
while(cc.length && cc[cc.length - 1].lex)
287285
cc.pop()();
286+
if (style?.slice(0, 2) === "p5") return style;
288287
if (cx.marked) return cx.marked;
289288
if (type == "variable" && inScope(state, content)) return "variable-2";
290289
return style;

server/controllers/project.controller.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,10 @@ function addFileToZip(file, files, zip, path = '') {
222222
const numChildFiles = file.children.filter((f) => f.fileType !== 'folder')
223223
.length;
224224
let childrenAdded = 0;
225-
225+
if (numChildFiles === 0) {
226+
zip.folder(file.name);
227+
resolve();
228+
}
226229
file.children.forEach(async (fileId) => {
227230
const childFile = files.find((f) => f.id === fileId);
228231

0 commit comments

Comments
 (0)