✨ Navigation to Settings Screen
This commit is contained in:
parent
b27ee57aee
commit
167bbe88a0
5 changed files with 61 additions and 113 deletions
|
@ -1,13 +1,19 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const Screen = ({ children }) => (
|
const Screen = ({ children, fullscreen }) => (
|
||||||
<div className="fullscreen-preview">
|
<div className={fullscreen && 'fullscreen-preview'}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Screen.defaultProps = {
|
||||||
|
fullscreen: false
|
||||||
|
};
|
||||||
|
|
||||||
Screen.propTypes = {
|
Screen.propTypes = {
|
||||||
children: PropTypes.node.isRequired
|
children: PropTypes.node.isRequired,
|
||||||
|
fullscreen: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Screen;
|
export default Screen;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/* eslint-disable */
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
@ -50,7 +49,7 @@ const MobileIDEView = (props) => {
|
||||||
const [overlay, setOverlay] = useState(null);
|
const [overlay, setOverlay] = useState(null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Screen>
|
<Screen fullscreen>
|
||||||
<Header>
|
<Header>
|
||||||
<IconLinkWrapper to="/" aria-label="Return to original editor">
|
<IconLinkWrapper to="/" aria-label="Return to original editor">
|
||||||
<ExitIcon />
|
<ExitIcon />
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Link } from 'react-router';
|
import { Link, withRouter } from 'react-router';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import * as PreferencesActions from '../IDE/actions/preferences';
|
||||||
|
import * as IdeActions from '../IDE/actions/ide';
|
||||||
|
|
||||||
import Screen from '../../components/mobile/MobileScreen';
|
import Screen from '../../components/mobile/MobileScreen';
|
||||||
import Header from '../../components/mobile/Header';
|
import Header from '../../components/mobile/Header';
|
||||||
import { ExitIcon } from '../../common/icons';
|
import { ExitIcon } from '../../common/icons';
|
||||||
import { remSize } from '../../theme';
|
import { remSize } from '../../theme';
|
||||||
import * as PreferencesActions from '../IDE/actions/preferences';
|
|
||||||
import * as IdeActions from '../IDE/actions/ide';
|
|
||||||
|
|
||||||
const IconLinkWrapper = styled(Link)`
|
const IconLinkWrapper = styled(Link)`
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
|
@ -22,57 +24,25 @@ const Content = styled.div`
|
||||||
margin-top: ${remSize(68)};
|
margin-top: ${remSize(68)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
/*
|
|
||||||
<div className="preference">
|
|
||||||
<h4 className="preference__title">Word Wrap</h4>
|
|
||||||
<div className="preference__options">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
onChange={() => this.props.setLinewrap(true)}
|
|
||||||
aria-label="linewrap on"
|
|
||||||
name="linewrap"
|
|
||||||
id="linewrap-on"
|
|
||||||
className="preference__radio-button"
|
|
||||||
value="On"
|
|
||||||
checked={this.props.linewrap}
|
|
||||||
/>
|
|
||||||
<label htmlFor="linewrap-on" className="preference__option">On</label>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
onChange={() => this.props.setLinewrap(false)}
|
|
||||||
aria-label="linewrap off"
|
|
||||||
name="linewrap"
|
|
||||||
id="linewrap-off"
|
|
||||||
className="preference__radio-button"
|
|
||||||
value="Off"
|
|
||||||
checked={!this.props.linewrap}
|
|
||||||
/>
|
|
||||||
<label htmlFor="linewrap-off" className="preference__option">Off</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
*/
|
|
||||||
|
|
||||||
const Selector = ({
|
const Selector = ({
|
||||||
title, value, onSelect, ariaLabel, name, id, options,
|
title, value, onSelect, options,
|
||||||
}) => (
|
}) => (
|
||||||
<div className="preference">
|
<div className="preference">
|
||||||
<h4 className="preference__title">{title}</h4>
|
<h4 className="preference__title">{title}</h4>
|
||||||
{options.map(option => (
|
{options.map(option => (
|
||||||
<div className="preference__options">
|
<div className="preference__options" key={option.id}>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
|
|
||||||
onChange={() => onSelect(option.value)}
|
onChange={() => onSelect(option.value)}
|
||||||
aria-label={ariaLabel}
|
aria-label={option.ariaLabel}
|
||||||
name={name}
|
name={option.name}
|
||||||
id={id}
|
id={option.id}
|
||||||
className="preference__radio-button"
|
className="preference__radio-button"
|
||||||
value={option.value}
|
value={option.value}
|
||||||
checked={value === option.value}
|
checked={value === option.value}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={id} className="preference__option">{option.label}</label>
|
<label htmlFor={option.id} className="preference__option">{option.label}</label>
|
||||||
</div>))}
|
</div>))}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -82,12 +52,14 @@ Selector.defaultProps = {
|
||||||
|
|
||||||
Selector.propTypes = {
|
Selector.propTypes = {
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
value: PropTypes.string.isRequired,
|
value: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]).isRequired,
|
||||||
options: PropTypes.arrayOf(PropTypes.string),
|
options: PropTypes.arrayOf(PropTypes.shape({
|
||||||
ariaLabel: PropTypes.string.isRequired,
|
id: PropTypes.string,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string,
|
||||||
id: PropTypes.string.isRequired,
|
label: PropTypes.string,
|
||||||
onSelect: PropTypes.string.isRequired,
|
ariaLabel: PropTypes.string,
|
||||||
|
})),
|
||||||
|
onSelect: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SettingsHeader = styled(Header)`
|
const SettingsHeader = styled(Header)`
|
||||||
|
@ -96,11 +68,13 @@ const SettingsHeader = styled(Header)`
|
||||||
|
|
||||||
|
|
||||||
const MobilePreferences = (props) => {
|
const MobilePreferences = (props) => {
|
||||||
const { setTheme } = props;
|
const { setTheme, setAutosave, setLinewrap } = props;
|
||||||
|
const { theme, autosave, linewrap } = props;
|
||||||
|
|
||||||
const preferences = [
|
const preferences = [
|
||||||
{
|
{
|
||||||
title: 'Theme',
|
title: 'Theme',
|
||||||
value: 'light',
|
value: theme,
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
value: 'light', label: 'light', ariaLabel: 'light theme on', name: 'light theme', id: 'light-theme-on'
|
value: 'light', label: 'light', ariaLabel: 'light theme on', name: 'light theme', id: 'light-theme-on'
|
||||||
|
@ -112,44 +86,55 @@ const MobilePreferences = (props) => {
|
||||||
value: 'contrast', label: 'contrast', ariaLabel: 'contrast theme on', name: 'contrast theme', id: 'contrast-theme-on'
|
value: 'contrast', label: 'contrast', ariaLabel: 'contrast theme on', name: 'contrast theme', id: 'contrast-theme-on'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
onSelect: setTheme // setTheme
|
onSelect: x => setTheme(x) // setTheme
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: 'Autosave',
|
title: 'Autosave',
|
||||||
value: true,
|
value: autosave,
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
value: 'On', label: 'On', ariaLabel: 'autosave on', name: 'autosave', id: 'autosave-on'
|
value: true, label: 'On', ariaLabel: 'autosave on', name: 'autosave', id: 'autosave-on'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'Off', label: 'Off', ariaLabel: 'autosave off', name: 'autosave', id: 'autosave-off'
|
value: false, label: 'Off', ariaLabel: 'autosave off', name: 'autosave', id: 'autosave-off'
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
onSelect: () => {} // setAutosave
|
onSelect: x => setAutosave(x) // setAutosave
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: 'Word Wrap',
|
||||||
|
value: linewrap,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: true, label: 'On', ariaLabel: 'linewrap on', name: 'linewrap', id: 'linewrap-on'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: false, label: 'Off', ariaLabel: 'linewrap off', name: 'linewrap', id: 'linewrap-off'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onSelect: x => setLinewrap(x)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
useEffect(() => { });
|
// useEffect(() => { });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Screen>
|
<Screen>
|
||||||
<SettingsHeader>
|
<SettingsHeader>
|
||||||
<div>
|
<h1>Settings</h1>
|
||||||
<h1>Settings</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ marginLeft: '2rem' }}>
|
<div style={{ marginLeft: '2rem' }}>
|
||||||
|
<IconLinkWrapper to="/mobile" aria-label="Return to ide view">
|
||||||
<IconLinkWrapper to="/mobile" aria-label="Return to original editor">
|
|
||||||
<ExitIcon />
|
<ExitIcon />
|
||||||
</IconLinkWrapper>
|
</IconLinkWrapper>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
</SettingsHeader>
|
</SettingsHeader>
|
||||||
<section className="preferences">
|
<section className="preferences">
|
||||||
<Content>
|
<Content>
|
||||||
{ preferences.map(option => <Selector {...option} />) }
|
{ preferences.map(option => <Selector key={`${option.title}wrapper`} {...option} />) }
|
||||||
</Content>
|
</Content>
|
||||||
</section>
|
</section>
|
||||||
</Screen>);
|
</Screen>);
|
||||||
|
@ -176,52 +161,10 @@ MobilePreferences.propTypes = {
|
||||||
setTextOutput: PropTypes.func.isRequired,
|
setTextOutput: PropTypes.func.isRequired,
|
||||||
setGridOutput: PropTypes.func.isRequired,
|
setGridOutput: PropTypes.func.isRequired,
|
||||||
setSoundOutput: PropTypes.func.isRequired,
|
setSoundOutput: PropTypes.func.isRequired,
|
||||||
|
|
||||||
|
|
||||||
preferences: PropTypes.shape({
|
|
||||||
fontSize: PropTypes.number.isRequired,
|
|
||||||
autosave: PropTypes.bool.isRequired,
|
|
||||||
linewrap: PropTypes.bool.isRequired,
|
|
||||||
lineNumbers: PropTypes.bool.isRequired,
|
|
||||||
lintWarning: PropTypes.bool.isRequired,
|
|
||||||
textOutput: PropTypes.bool.isRequired,
|
|
||||||
gridOutput: PropTypes.bool.isRequired,
|
|
||||||
soundOutput: PropTypes.bool.isRequired,
|
|
||||||
theme: PropTypes.string.isRequired,
|
|
||||||
autorefreshIdeActions: PropTypes.bool.isRequired
|
|
||||||
}).isRequired,
|
|
||||||
|
|
||||||
ide: PropTypes.shape({
|
|
||||||
isPlaying: PropTypes.bool.isRequired,
|
|
||||||
isAccessibleOutputPlaying: PropTypes.bool.isRequired,
|
|
||||||
consoleEvent: PropTypes.array,
|
|
||||||
modalIsVisible: PropTypes.bool.isRequired,
|
|
||||||
sidebarIsExpanded: PropTypes.bool.isRequired,
|
|
||||||
consoleIsExpanded: PropTypes.bool.isRequired,
|
|
||||||
preferencesIsVisible: PropTypes.bool.isRequired,
|
|
||||||
projectOptionsVisible: PropTypes.bool.isRequired,
|
|
||||||
newFolderModalVisible: 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,
|
|
||||||
uploadFileModalVisible: PropTypes.bool.isRequired
|
|
||||||
}).isRequired,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
preferences: state.preferences,
|
...state.preferences,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => bindActionCreators({
|
const mapDispatchToProps = dispatch => bindActionCreators({
|
||||||
|
@ -230,4 +173,4 @@ const mapDispatchToProps = dispatch => bindActionCreators({
|
||||||
}, dispatch);
|
}, dispatch);
|
||||||
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(MobilePreferences);
|
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(MobilePreferences));
|
||||||
|
|
|
@ -59,7 +59,7 @@ const MobileSketchView = (props) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Screen>
|
<Screen fullscreen>
|
||||||
<Header>
|
<Header>
|
||||||
<IconLinkWrapper to="/mobile" aria-label="Return to original editor">
|
<IconLinkWrapper to="/mobile" aria-label="Return to original editor">
|
||||||
<ExitIcon viewBox="0 0 16 16" />
|
<ExitIcon viewBox="0 0 16 16" />
|
||||||
|
|
|
@ -123,7 +123,7 @@ if (process.env.MOBILE_ENABLED) {
|
||||||
res.send(renderIndex());
|
res.send(renderIndex());
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/mobile/*', (req, res) => {
|
router.get('/mobile/preferences', (req, res) => {
|
||||||
res.send(renderIndex());
|
res.send(renderIndex());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue