Skip to content

Save Sketches on mobile #1544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Aug 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
214f5d6
:sparkles: make unsaved changes dot on project name
ghalestrilo Aug 12, 2020
7402a6b
:recycle: rename getTitle to withChangeDot
ghalestrilo Aug 12, 2020
682db4d
:recycle: connect <Editor />
ghalestrilo Aug 12, 2020
06f9050
:recycle: dry up <MobileIDEView /> imports
ghalestrilo Aug 12, 2020
f9fdadb
:recycle: dry up <MobileIDEView /> imports
ghalestrilo Aug 12, 2020
410ef1b
:recycle: dry up <IDEView />
ghalestrilo Aug 12, 2020
bbb6adf
Merge branch 'feature/mobile-examples' of https://github.com/ghalestr…
ghalestrilo Aug 12, 2020
dabd5e0
Merge branch 'feature/mobile-examples' of https://github.com/ghalestr…
ghalestrilo Aug 13, 2020
5da8b24
:lipstick: start with terinal collapsed
ghalestrilo Aug 13, 2020
955d8c2
:sparkles: create useEffectWithComparison hook
ghalestrilo Aug 13, 2020
99594a3
:sparkles: create autosave method / thunk
ghalestrilo Aug 13, 2020
53a5198
:sparkles: create useEventListener hook
ghalestrilo Aug 13, 2020
fac3f96
:construction: copy handleGlobalKeydown to MobileIDEView
ghalestrilo Aug 13, 2020
a0b302f
:construction: enable keyboard shortcuts on mobile
ghalestrilo Aug 13, 2020
074334e
:bug: fix hook not detecting user authenticated
ghalestrilo Aug 13, 2020
1503b1b
:twisted_rightwards_arrows: merge from mobile-examples
ghalestrilo Aug 17, 2020
6941e06
:construction: update saveProject action redirection
ghalestrilo Aug 17, 2020
e996d49
:construction: pass project and user to autosave
ghalestrilo Aug 17, 2020
100a6a0
:sparkles: add save button to bottom bar
ghalestrilo Aug 17, 2020
c0b9ae4
Merge branch 'feature/mobile-save-sketch' of https://github.com/ghale…
ghalestrilo Aug 17, 2020
54ae17f
:twisted_rightwards_arrows: pull from feature/mobile-files-tab
ghalestrilo Aug 17, 2020
379cb94
Merge branch 'develop' of https://github.com/processing/p5.js-web-edi…
ghalestrilo Aug 17, 2020
09c8f77
:lipstick: save icon
ghalestrilo Aug 17, 2020
33848e2
:bug: fix missing files on sidebar
ghalestrilo Aug 18, 2020
5f24a71
Merge branch 'develop' of https://github.com/processing/p5.js-web-edi…
ghalestrilo Aug 18, 2020
2349acc
Merge branch 'develop' into feature/mobile-save-sketch
ghalestrilo Aug 20, 2020
a3b3cd1
Merge branch 'develop' into feature/mobile-save-sketch
ghalestrilo Aug 21, 2020
384a185
:twisted_rightwards_arrows: merge from develop
ghalestrilo Aug 24, 2020
e78d2d9
Merge branch 'feature/mobile-save-sketch' of https://github.com/ghale…
ghalestrilo Aug 24, 2020
d7106fe
:twisted_rightwards_arrows: merge from develop
ghalestrilo Aug 28, 2020
8ec5ab9
:ok_hand: fix 0px, anonymous function and /mobile endpoint
ghalestrilo Aug 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/common/icons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Preferences from '../images/preferences.svg';
import Play from '../images/triangle-arrow-right.svg';
import More from '../images/more.svg';
import Code from '../images/code.svg';
import Save from '../images/save.svg';
import Terminal from '../images/terminal.svg';

import Folder from '../images/folder-padded.svg';
Expand Down Expand Up @@ -87,6 +88,7 @@ export const PlayIcon = withLabel(Play);
export const MoreIcon = withLabel(More);
export const TerminalIcon = withLabel(Terminal);
export const CodeIcon = withLabel(Code);
export const SaveIcon = withLabel(Save);

export const FolderIcon = withLabel(Folder);

Expand Down
64 changes: 23 additions & 41 deletions client/components/mobile/ActionStrip.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import React from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
import { remSize, prop } from '../../theme';
import IconButton from './IconButton';
import { TerminalIcon, FolderIcon } from '../../common/icons';
import * as IDEActions from '../../modules/IDE/actions/ide';

const BottomBarContent = styled.div`
padding: ${remSize(8)};
display: flex;
display: grid;
grid-template-columns: repeat(8,1fr);

svg {
max-height: ${remSize(32)};

}

path { fill: ${prop('primaryTextColor')} !important }
Expand All @@ -25,42 +21,28 @@ const BottomBarContent = styled.div`
}
`;

// Maybe this component shouldn't be connected, and instead just receive the `actions` prop
const ActionStrip = ({ toggleExplorer }) => {
const { expandConsole, collapseConsole } = bindActionCreators(IDEActions, useDispatch());
const { consoleIsExpanded } = useSelector(state => state.ide);

const actions = [
{
icon: TerminalIcon, inverted: true, aria: 'Open terminal console', action: consoleIsExpanded ? collapseConsole : expandConsole
},
{ icon: FolderIcon, aria: 'Open files explorer', action: toggleExplorer }
];

return (
<BottomBarContent>
{actions.map(({
icon, aria, action, inverted
}) =>
(
<IconButton
inverted={inverted}
className={inverted && 'inverted'}
icon={icon}
aria-label={aria}
key={`bottom-bar-${aria}`}
onClick={() => action()}
/>))}
</BottomBarContent>
);
};
const ActionStrip = ({ actions }) => (
<BottomBarContent>
{actions.map(({
icon, aria, action, inverted
}) =>
(<IconButton
inverted={inverted}
className={inverted && 'inverted'}
icon={icon}
aria-label={aria}
key={`bottom-bar-${aria}`}
onClick={action}
/>))}
</BottomBarContent>);

ActionStrip.propTypes = {
toggleExplorer: PropTypes.func
};

ActionStrip.defaultProps = {
toggleExplorer: () => {}
actions: PropTypes.arrayOf(PropTypes.shape({
icon: PropTypes.any,
aria: PropTypes.string.isRequired,
action: PropTypes.func.isRequired,
inverted: PropTypes.bool
})).isRequired
};

export default ActionStrip;
9 changes: 8 additions & 1 deletion client/components/mobile/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ const HeaderDiv = styled.div`
}

& svg path { fill: ${textColor} !important; }

.editor__unsaved-changes svg {
width: ${remSize(16)};
padding: 0;
vertical-align: top
}
`;

const IconContainer = styled.div`
Expand Down Expand Up @@ -71,8 +77,9 @@ const Header = ({
</HeaderDiv>
);


Header.propTypes = {
title: PropTypes.string,
title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
subtitle: PropTypes.string,
leftButton: PropTypes.element,
children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]),
Expand Down
3 changes: 3 additions & 0 deletions client/images/save.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 9 additions & 10 deletions client/modules/IDE/actions/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ function getSynchedProject(currentState, responseProject) {
};
}

export function saveProject(selectedFile = null, autosave = false) {
export function saveProject(selectedFile = null, autosave = false, mobile = false) {
return (dispatch, getState) => {
const state = getState();
if (state.project.isSaving) {
Expand Down Expand Up @@ -185,16 +185,15 @@ export function saveProject(selectedFile = null, autosave = false) {
.then((response) => {
dispatch(endSavingProject());
const { hasChanges, synchedProject } = getSynchedProject(getState(), response.data);

dispatch(setNewProject(synchedProject));
dispatch(setUnsavedChanges(false));
browserHistory.push(`/${response.data.user.username}/sketches/${response.data.id}`);

if (hasChanges) {
dispatch(setNewProject(synchedProject));
dispatch(setUnsavedChanges(false));
browserHistory.push(`/${response.data.user.username}/sketches/${response.data.id}`);
dispatch(setUnsavedChanges(true));
} else {
dispatch(setNewProject(synchedProject));
dispatch(setUnsavedChanges(false));
browserHistory.push(`/${response.data.user.username}/sketches/${response.data.id}`);
}

dispatch(projectSaveSuccess());
if (!autosave) {
if (state.preferences.autosave) {
Expand Down Expand Up @@ -222,9 +221,9 @@ export function saveProject(selectedFile = null, autosave = false) {
};
}

export function autosaveProject() {
export function autosaveProject(mobile = false) {
return (dispatch, getState) => {
saveProject(null, true)(dispatch, getState);
saveProject(null, true, mobile)(dispatch, getState);
};
}

Expand Down
57 changes: 56 additions & 1 deletion client/modules/IDE/components/Editor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import { CSSLint } from 'csslint';
import { HTMLHint } from 'htmlhint';
import classNames from 'classnames';
import { debounce } from 'lodash';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import '../../../utils/htmlmixed';
import '../../../utils/p5-javascript';
import '../../../utils/webGL-clike';
Expand All @@ -40,6 +42,16 @@ import beepUrl from '../../../sounds/audioAlert.mp3';
import UnsavedChangesDotIcon from '../../../images/unsaved-changes-dot.svg';
import RightArrowIcon from '../../../images/right-arrow.svg';
import LeftArrowIcon from '../../../images/left-arrow.svg';
import { getHTMLFile } from '../reducers/files';

import * as FileActions from '../actions/files';
import * as IDEActions from '../actions/ide';
import * as ProjectActions from '../actions/project';
import * as EditorAccessibilityActions from '../actions/editorAccessibility';
import * as PreferencesActions from '../actions/preferences';
import * as UserActions from '../../User/actions';
import * as ToastActions from '../actions/toast';
import * as ConsoleActions from '../actions/console';

search(CodeMirror);

Expand Down Expand Up @@ -413,4 +425,47 @@ Editor.defaultProps = {
consoleEvents: [],
};

export default withTranslation()(Editor);

function mapStateToProps(state) {
return {
files: state.files,
file:
state.files.find(file => file.isSelectedFile) ||
state.files.find(file => file.name === 'sketch.js') ||
state.files.find(file => file.name !== 'root'),
htmlFile: getHTMLFile(state.files),
ide: state.ide,
preferences: state.preferences,
editorAccessibility: state.editorAccessibility,
user: state.user,
project: state.project,
toast: state.toast,
console: state.console,

...state.preferences,
...state.ide,
...state.project,
...state.editorAccessibility,
isExpanded: state.ide.consoleIsExpanded,
projectSavedTime: state.project.updatedAt
};
}

function mapDispatchToProps(dispatch) {
return bindActionCreators(
Object.assign(
{},
EditorAccessibilityActions,
FileActions,
ProjectActions,
IDEActions,
PreferencesActions,
UserActions,
ToastActions,
ConsoleActions
),
dispatch
);
}

export default withTranslation()(connect(mapStateToProps, mapDispatchToProps)(Editor));
89 changes: 15 additions & 74 deletions client/modules/IDE/pages/IDEView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -343,46 +343,7 @@ class IDEView extends React.Component {
allowResize={this.props.ide.consoleIsExpanded}
className="editor-preview-subpanel"
>
<Editor
lintWarning={this.props.preferences.lintWarning}
linewrap={this.props.preferences.linewrap}
lintMessages={this.props.editorAccessibility.lintMessages}
updateLintMessage={this.props.updateLintMessage}
clearLintMessage={this.props.clearLintMessage}
file={this.props.selectedFile}
updateFileContent={this.props.updateFileContent}
fontSize={this.props.preferences.fontSize}
lineNumbers={this.props.preferences.lineNumbers}
files={this.props.files}
editorOptionsVisible={this.props.ide.editorOptionsVisible}
showEditorOptions={this.props.showEditorOptions}
closeEditorOptions={this.props.closeEditorOptions}
showKeyboardShortcutModal={
this.props.showKeyboardShortcutModal
}
setUnsavedChanges={this.props.setUnsavedChanges}
isPlaying={this.props.ide.isPlaying}
theme={this.props.preferences.theme}
startRefreshSketch={this.props.startRefreshSketch}
stopSketch={this.props.stopSketch}
autorefresh={this.props.preferences.autorefresh}
unsavedChanges={this.props.ide.unsavedChanges}
projectSavedTime={this.props.project.updatedAt}
isExpanded={this.props.ide.sidebarIsExpanded}
expandSidebar={this.props.expandSidebar}
collapseSidebar={this.props.collapseSidebar}
isUserOwner={isUserOwner(this.props)}
clearConsole={this.props.clearConsole}
consoleEvents={this.props.console}
showRuntimeErrorWarning={this.props.showRuntimeErrorWarning}
hideRuntimeErrorWarning={this.props.hideRuntimeErrorWarning}
runtimeErrorWarningVisible={
this.props.ide.runtimeErrorWarningVisible
}
provideController={(ctl) => {
this.cmController = ctl;
}}
/>
<Editor provideController={(ctl) => { this.cmController = ctl; }} />
<Console />
</SplitPane>
<section className="preview-frame-holder">
Expand Down Expand Up @@ -533,31 +494,25 @@ IDEView.propTypes = {
}).isRequired,
saveProject: PropTypes.func.isRequired,
ide: PropTypes.shape({
isPlaying: PropTypes.bool.isRequired,
isAccessibleOutputPlaying: PropTypes.bool.isRequired,
consoleEvent: PropTypes.array, // eslint-disable-line
modalIsVisible: PropTypes.bool.isRequired,
sidebarIsExpanded: PropTypes.bool.isRequired,
consoleIsExpanded: PropTypes.bool.isRequired,
preferencesIsVisible: PropTypes.bool.isRequired,
projectOptionsVisible: PropTypes.bool.isRequired,
newFolderModalVisible: PropTypes.bool.isRequired,
errorType: PropTypes.string,
keyboardShortcutVisible: PropTypes.bool.isRequired,
shareModalVisible: PropTypes.bool.isRequired,
shareModalProjectId: PropTypes.string.isRequired,
shareModalProjectName: PropTypes.string.isRequired,
shareModalProjectUsername: PropTypes.string.isRequired,
editorOptionsVisible: PropTypes.bool.isRequired,
keyboardShortcutVisible: PropTypes.bool.isRequired,
unsavedChanges: PropTypes.bool.isRequired,
infiniteLoop: PropTypes.bool.isRequired,
previewIsRefreshing: PropTypes.bool.isRequired,
infiniteLoopMessage: PropTypes.string.isRequired,
projectSavedTime: PropTypes.string,
previousPath: PropTypes.string.isRequired,
justOpenedProject: PropTypes.bool.isRequired,
errorType: PropTypes.string,
runtimeErrorWarningVisible: PropTypes.bool.isRequired,
previewIsRefreshing: PropTypes.bool.isRequired,
isPlaying: PropTypes.bool.isRequired,
isAccessibleOutputPlaying: PropTypes.bool.isRequired,
projectOptionsVisible: PropTypes.bool.isRequired,
preferencesIsVisible: PropTypes.bool.isRequired,
modalIsVisible: PropTypes.bool.isRequired,
uploadFileModalVisible: PropTypes.bool.isRequired,
newFolderModalVisible: PropTypes.bool.isRequired,
justOpenedProject: PropTypes.bool.isRequired,
sidebarIsExpanded: PropTypes.bool.isRequired,
consoleIsExpanded: PropTypes.bool.isRequired,
unsavedChanges: PropTypes.bool.isRequired,
}).isRequired,
stopSketch: PropTypes.func.isRequired,
project: PropTypes.shape({
Expand All @@ -572,11 +527,9 @@ IDEView.propTypes = {
editorAccessibility: PropTypes.shape({
lintMessages: PropTypes.array.isRequired, // eslint-disable-line
}).isRequired,
updateLintMessage: PropTypes.func.isRequired,
clearLintMessage: PropTypes.func.isRequired,
preferences: PropTypes.shape({
fontSize: PropTypes.number.isRequired,
autosave: PropTypes.bool.isRequired,
fontSize: PropTypes.number.isRequired,
linewrap: PropTypes.bool.isRequired,
lineNumbers: PropTypes.bool.isRequired,
lintWarning: PropTypes.bool.isRequired,
Expand All @@ -602,7 +555,6 @@ IDEView.propTypes = {
name: PropTypes.string.isRequired,
content: PropTypes.string.isRequired,
})).isRequired,
updateFileContent: PropTypes.func.isRequired,
selectedFile: PropTypes.shape({
id: PropTypes.string.isRequired,
content: PropTypes.string.isRequired,
Expand Down Expand Up @@ -630,9 +582,6 @@ IDEView.propTypes = {
closeNewFileModal: PropTypes.func.isRequired,
createFolder: PropTypes.func.isRequired,
closeShareModal: PropTypes.func.isRequired,
showEditorOptions: PropTypes.func.isRequired,
closeEditorOptions: PropTypes.func.isRequired,
showKeyboardShortcutModal: PropTypes.func.isRequired,
closeKeyboardShortcutModal: PropTypes.func.isRequired,
toast: PropTypes.shape({
isVisible: PropTypes.bool.isRequired,
Expand All @@ -642,22 +591,14 @@ IDEView.propTypes = {
setRouteLeaveHook: PropTypes.func,
}).isRequired,
route: PropTypes.oneOfType([PropTypes.object, PropTypes.element]).isRequired,
setUnsavedChanges: PropTypes.func.isRequired,
setTheme: PropTypes.func.isRequired,
endSketchRefresh: PropTypes.func.isRequired,
startRefreshSketch: PropTypes.func.isRequired,
setBlobUrl: PropTypes.func.isRequired,
setPreviousPath: PropTypes.func.isRequired,
console: PropTypes.arrayOf(PropTypes.shape({
method: PropTypes.string.isRequired,
args: PropTypes.arrayOf(PropTypes.string),
})).isRequired,
clearConsole: PropTypes.func.isRequired,
showErrorModal: PropTypes.func.isRequired,
hideErrorModal: PropTypes.func.isRequired,
clearPersistedState: PropTypes.func.isRequired,
showRuntimeErrorWarning: PropTypes.func.isRequired,
hideRuntimeErrorWarning: PropTypes.func.isRequired,
startSketch: PropTypes.func.isRequired,
openUploadFileModal: PropTypes.func.isRequired,
closeUploadFileModal: PropTypes.func.isRequired,
Expand Down
Loading