Skip to content

Commit 62df487

Browse files
authored
Merge pull request #2387 from dewanshDT/dewanshmobile/ide
Useable Mobile Editor 🎉
2 parents f7ace88 + 3fed465 commit 62df487

File tree

13 files changed

+522
-460
lines changed

13 files changed

+522
-460
lines changed

client/components/RootPage.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@ import { prop } from '../theme';
44
const RootPage = styled.div`
55
min-height: 100%;
66
display: flex;
7+
justify-content: start;
78
flex-direction: column;
89
color: ${prop('primaryTextColor')};
910
background-color: ${prop('backgroundColor')};
1011
height: ${({ fixedHeight }) => fixedHeight || 'initial'};
12+
13+
@media (max-width: 770px) {
14+
height: 100%;
15+
overflow: hidden;
16+
}
1117
`;
1218

1319
export default RootPage;

client/images/plus-icon.svg

Lines changed: 2 additions & 11 deletions
Loading

client/index.integration.test.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ describe('index.jsx integration', () => {
5959
// spy on this function and wait for it to be called before making assertions
6060
const spy = jest.spyOn(Actions, 'getUser');
6161

62+
window.process.env.PREVIEW_URL = 'http://localhost:8002';
6263
beforeEach(async () => {
6364
act(() => {
6465
subject();

client/modules/IDE/components/Editor.unit.test.jsx renamed to client/modules/IDE/components/Editor/Editor.unit.test.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import React from 'react';
22
import configureStore from 'redux-mock-store';
33
import thunk from 'redux-thunk';
44
import { act } from 'react-dom/test-utils';
5-
import Editor from './Editor';
6-
import { reduxRender } from '../../../test-utils';
7-
import { initialTestState } from '../../../testData/testReduxStore';
5+
import Editor from '.';
6+
import { reduxRender } from '../../../../test-utils';
7+
import { initialTestState } from '../../../../testData/testReduxStore';
88

9-
jest.mock('../../../i18n');
9+
jest.mock('../../../../i18n');
1010

1111
describe('<Editor />', () => {
1212
const mockStore = configureStore([thunk]);
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import styled from 'styled-components';
2+
import { prop, remSize } from '../../../../theme';
3+
4+
export const EditorContainer = styled.div`
5+
display: flex;
6+
flex-direction: column;
7+
height: 100%;
8+
padding-bottom: 5rem;
9+
transform: ${(props) =>
10+
props.expanded ? 'translateX(50%)' : 'translateX(0)'};
11+
12+
> header {
13+
display: flex;
14+
${prop('MobilePanel.secondary')}
15+
> span {
16+
display: flex;
17+
justify-content: center;
18+
align-items: center;
19+
padding: ${remSize(10)};
20+
font-weight: bold;
21+
${prop('MobilePanel.default')}
22+
}
23+
}
24+
25+
> section {
26+
display: flex;
27+
flex-direction: column;
28+
height: 100%;
29+
width: 100vw;
30+
overflow-y: auto;
31+
}
32+
`;
33+
34+
export const EditorHolder = styled.div`
35+
min-height: 100%;
36+
`;
37+
38+
export const PreviewWrapper = styled.div`
39+
display: ${(props) => (props.show ? 'block' : 'none')};
40+
position: relative;
41+
height: 100vh;
42+
min-width: 100%;
43+
44+
.preview-console {
45+
z-index: 1;
46+
}
47+
`;
48+
49+
export const EditorSidebarWrapper = styled.div`
50+
display: ${(props) => (props.show ? 'block' : 'none')};
51+
height: 100%;
52+
position: relative;
53+
`;
54+
55+
export const FileDrawer = styled.div`
56+
height: 100%;
57+
width: 50vw;
58+
display: flex;
59+
flex-direction: column;
60+
position: absolute;
61+
/* z-index: 10; */
62+
background: ${prop('backgroundColor')};
63+
64+
> button[data-backdrop='filedrawer'] {
65+
position: absolute;
66+
background-color: #0005;
67+
height: 100%;
68+
width: 100%;
69+
z-index: 2;
70+
transform: translateX(100%);
71+
}
72+
73+
@media (min-width: 770px) {
74+
width: 100%;
75+
> button[data-backdrop='filedrawer'] {
76+
display: none;
77+
}
78+
}
79+
`;

client/modules/IDE/components/Editor.jsx renamed to client/modules/IDE/components/Editor/index.jsx

Lines changed: 111 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// TODO: convert to functional component
2+
13
import PropTypes from 'prop-types';
24
import React from 'react';
35
import CodeMirror from 'codemirror';
@@ -40,32 +42,35 @@ import classNames from 'classnames';
4042
import { debounce } from 'lodash';
4143
import { connect } from 'react-redux';
4244
import { bindActionCreators } from 'redux';
43-
import '../../../utils/htmlmixed';
44-
import '../../../utils/p5-javascript';
45-
import Timer from '../components/Timer';
46-
import EditorAccessibility from '../components/EditorAccessibility';
47-
import { selectActiveFile } from '../selectors/files';
48-
import AssetPreview from './AssetPreview';
49-
import { metaKey } from '../../../utils/metaKey';
50-
import './show-hint';
51-
import * as hinter from '../../../utils/p5-hinter';
52-
53-
import '../../../utils/codemirror-search';
54-
55-
import beepUrl from '../../../sounds/audioAlert.mp3';
56-
import UnsavedChangesDotIcon from '../../../images/unsaved-changes-dot.svg';
57-
import RightArrowIcon from '../../../images/right-arrow.svg';
58-
import LeftArrowIcon from '../../../images/left-arrow.svg';
59-
import { getHTMLFile } from '../reducers/files';
60-
61-
import * as FileActions from '../actions/files';
62-
import * as IDEActions from '../actions/ide';
63-
import * as ProjectActions from '../actions/project';
64-
import * as EditorAccessibilityActions from '../actions/editorAccessibility';
65-
import * as PreferencesActions from '../actions/preferences';
66-
import * as UserActions from '../../User/actions';
67-
import * as ToastActions from '../actions/toast';
68-
import * as ConsoleActions from '../actions/console';
45+
import MediaQuery from 'react-responsive';
46+
import '../../../../utils/htmlmixed';
47+
import '../../../../utils/p5-javascript';
48+
import { metaKey } from '../../../../utils/metaKey';
49+
import '../show-hint';
50+
import * as hinter from '../../../../utils/p5-hinter';
51+
import '../../../../utils/codemirror-search';
52+
53+
import beepUrl from '../../../../sounds/audioAlert.mp3';
54+
import RightArrowIcon from '../../../../images/right-arrow.svg';
55+
import LeftArrowIcon from '../../../../images/left-arrow.svg';
56+
import { getHTMLFile } from '../../reducers/files';
57+
import { selectActiveFile } from '../../selectors/files';
58+
59+
import * as FileActions from '../../actions/files';
60+
import * as IDEActions from '../../actions/ide';
61+
import * as ProjectActions from '../../actions/project';
62+
import * as EditorAccessibilityActions from '../../actions/editorAccessibility';
63+
import * as PreferencesActions from '../../actions/preferences';
64+
import * as UserActions from '../../../User/actions';
65+
import * as ConsoleActions from '../../actions/console';
66+
67+
import AssetPreview from '../AssetPreview';
68+
import Timer from '../Timer';
69+
import EditorAccessibility from '../EditorAccessibility';
70+
import UnsavedChangesIndicator from '../UnsavedChangesIndicator';
71+
import { EditorContainer, EditorHolder } from './MobileEditor';
72+
import { FolderIcon } from '../../../../common/icons';
73+
import IconButton from '../../../../components/mobile/IconButton';
6974

7075
emmet(CodeMirror);
7176

@@ -98,7 +103,7 @@ class Editor extends React.Component {
98103

99104
componentDidMount() {
100105
this.beep = new Audio(beepUrl);
101-
this.widgets = [];
106+
// this.widgets = [];
102107
this._cm = CodeMirror(this.codemirrorContainer, {
103108
theme: `p5-${this.props.theme}`,
104109
lineNumbers: this.props.lineNumbers,
@@ -306,6 +311,13 @@ class Editor extends React.Component {
306311
this._cm.removeLineClass(i, 'background', 'line-runtime-error');
307312
}
308313
}
314+
315+
this.props.provideController({
316+
tidyCode: this.tidyCode,
317+
showFind: this.showFind,
318+
showReplace: this.showReplace,
319+
getContent: this.getContent
320+
});
309321
}
310322

311323
componentWillUnmount() {
@@ -496,52 +508,80 @@ class Editor extends React.Component {
496508
});
497509

498510
return (
499-
<section className={editorSectionClass}>
500-
<header className="editor__header">
501-
<button
502-
aria-label={this.props.t('Editor.OpenSketchARIA')}
503-
className="sidebar__contract"
504-
onClick={() => {
505-
this.props.collapseSidebar();
506-
this.props.closeProjectOptions();
507-
}}
508-
>
509-
<LeftArrowIcon focusable="false" aria-hidden="true" />
510-
</button>
511-
<button
512-
aria-label={this.props.t('Editor.CloseSketchARIA')}
513-
className="sidebar__expand"
514-
onClick={this.props.expandSidebar}
515-
>
516-
<RightArrowIcon focusable="false" aria-hidden="true" />
517-
</button>
518-
<div className="editor__file-name">
519-
<span>
520-
{this.props.file.name}
521-
<span className="editor__unsaved-changes">
522-
{this.props.unsavedChanges ? (
523-
<UnsavedChangesDotIcon
524-
role="img"
525-
aria-label={this.props.t('Editor.UnsavedChangesARIA')}
526-
focusable="false"
511+
<MediaQuery minWidth={770}>
512+
{(matches) =>
513+
matches ? (
514+
<section className={editorSectionClass}>
515+
<header className="editor__header">
516+
<button
517+
aria-label={this.props.t('Editor.OpenSketchARIA')}
518+
className="sidebar__contract"
519+
onClick={() => {
520+
this.props.collapseSidebar();
521+
this.props.closeProjectOptions();
522+
}}
523+
>
524+
<LeftArrowIcon focusable="false" aria-hidden="true" />
525+
</button>
526+
<button
527+
aria-label={this.props.t('Editor.CloseSketchARIA')}
528+
className="sidebar__expand"
529+
onClick={this.props.expandSidebar}
530+
>
531+
<RightArrowIcon focusable="false" aria-hidden="true" />
532+
</button>
533+
<div className="editor__file-name">
534+
<span>
535+
{this.props.file.name}
536+
<UnsavedChangesIndicator />
537+
</span>
538+
<Timer />
539+
</div>
540+
</header>
541+
<article
542+
ref={(element) => {
543+
this.codemirrorContainer = element;
544+
}}
545+
className={editorHolderClass}
546+
/>
547+
{this.props.file.url ? (
548+
<AssetPreview
549+
url={this.props.file.url}
550+
name={this.props.file.name}
551+
/>
552+
) : null}
553+
<EditorAccessibility lintMessages={this.props.lintMessages} />
554+
</section>
555+
) : (
556+
<EditorContainer expanded={this.props.isExpanded}>
557+
<header>
558+
<IconButton
559+
onClick={this.props.expandSidebar}
560+
icon={FolderIcon}
561+
/>
562+
<span>
563+
{this.props.file.name}
564+
<UnsavedChangesIndicator />
565+
</span>
566+
</header>
567+
<section>
568+
<EditorHolder
569+
ref={(element) => {
570+
this.codemirrorContainer = element;
571+
}}
572+
/>
573+
{this.props.file.url ? (
574+
<AssetPreview
575+
url={this.props.file.url}
576+
name={this.props.file.name}
527577
/>
528578
) : null}
529-
</span>
530-
</span>
531-
<Timer />
532-
</div>
533-
</header>
534-
<article
535-
ref={(element) => {
536-
this.codemirrorContainer = element;
537-
}}
538-
className={editorHolderClass}
539-
/>
540-
{this.props.file.url ? (
541-
<AssetPreview url={this.props.file.url} name={this.props.file.name} />
542-
) : null}
543-
<EditorAccessibility lintMessages={this.props.lintMessages} />
544-
</section>
579+
<EditorAccessibility lintMessages={this.props.lintMessages} />
580+
</section>
581+
</EditorContainer>
582+
)
583+
}
584+
</MediaQuery>
545585
);
546586
}
547587
}
@@ -613,7 +653,6 @@ function mapStateToProps(state) {
613653
editorAccessibility: state.editorAccessibility,
614654
user: state.user,
615655
project: state.project,
616-
toast: state.toast,
617656
consoleEvents: state.console,
618657

619658
...state.preferences,
@@ -634,7 +673,6 @@ function mapDispatchToProps(dispatch) {
634673
IDEActions,
635674
PreferencesActions,
636675
UserActions,
637-
ToastActions,
638676
ConsoleActions
639677
),
640678
dispatch

client/modules/IDE/components/Header/MobileNav.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ const MobileNav = () => {
224224
}
225225
}
226226

227-
const title = useMemo(resolveTitle, [pageName]);
227+
const title = useMemo(resolveTitle, [pageName, project.name]);
228228

229229
const Logo = AsteriskIcon;
230230
return (
@@ -261,7 +261,7 @@ const MobileNav = () => {
261261
</Link>
262262
</div>
263263
)}
264-
{title === project.name ? (
264+
{pageName === 'home' ? (
265265
<MoreMenu />
266266
) : (
267267
<div>

0 commit comments

Comments
 (0)