Skip to content

Mobile Preferences Screen Prototype #1472

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
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c8b3da9
:recycle: rename IDEViewMobile to MobileIDEView
ghalestrilo Jun 22, 2020
b27ee57
:construction: connect MobileSettings
ghalestrilo Jun 23, 2020
167bbe8
:sparkles: Navigation to Settings Screen
ghalestrilo Jun 23, 2020
ad3db32
:bug: fix settings text color
ghalestrilo Jun 23, 2020
181e832
:lipstick: fix options styling
ghalestrilo Jun 23, 2020
a9c17b5
:sparkles: create settings section header component
ghalestrilo Jun 23, 2020
1f69786
:sparkles: add accessible output settings
ghalestrilo Jun 23, 2020
3ba1b26
:sparkles: add accessibility settings
ghalestrilo Jun 23, 2020
d43fae5
:twisted_rightwards_arrows: merging from mobile-sketch-view
ghalestrilo Jun 30, 2020
b96b9d3
:ok_hand: use remSize on IconButton
ghalestrilo Jun 30, 2020
30c47d6
:ok_hand: rename <Selector /> to <PreferencePicker />
ghalestrilo Jun 30, 2020
1c1ea98
:ok_hand: unimplement canvas stretching behavior
ghalestrilo Jun 30, 2020
24a72da
:lipstick: improve <Header /> component structure and layout
ghalestrilo Jun 30, 2020
e8b2515
:lipstick: change screen header title to Preferences
ghalestrilo Jun 30, 2020
c88bf44
:twisted_rightwards_arrows: merging from mobile-sketch-view
ghalestrilo Jul 1, 2020
3ce0a51
:ok_hand: increase option label size
ghalestrilo Jul 1, 2020
82ec520
:ok_hand: fixed warnings
ghalestrilo Jul 1, 2020
58d8fc1
:ok_hand: fixed warnings on MobileSketchView and MobilePreferences
ghalestrilo Jul 1, 2020
7d6ba6f
Merge branch 'develop' into feature/mobile-settings-screen
catarak Jul 1, 2020
88ebe9e
Re-add Redux DevTools to App.jsx
catarak Jul 1, 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
12 changes: 9 additions & 3 deletions client/components/mobile/MobileScreen.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import React from 'react';
import PropTypes from 'prop-types';

const Screen = ({ children }) => (
<div className="fullscreen-preview">
const Screen = ({ children, fullscreen }) => (
<div className={fullscreen && 'fullscreen-preview'}>
{children}
</div>
);

Screen.defaultProps = {
fullscreen: false
};

Screen.propTypes = {
children: PropTypes.node.isRequired
children: PropTypes.node.isRequired,
fullscreen: PropTypes.bool
};

export default Screen;
57 changes: 57 additions & 0 deletions client/components/mobile/Selector.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this file could have a more descriptive/specific name since "Selector" feels pretty generic, where this component is specifically being used for a Preference selection.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. I renamed it to <PreferencePicker /> to be more descriptive

import PropTypes from 'prop-types';
import styled from 'styled-components';
import { prop } from '../../theme';


const PreferenceTitle = styled.h4.attrs(props => ({ ...props, className: 'preference__title' }))`
color: ${prop('primaryTextColor')};
`;

const Preference = styled.div.attrs(props => ({ ...props, className: 'preference' }))`
flex-wrap: nowrap !important;
align-items: baseline !important;
justify-items: space-between
`;


const Selector = ({
title, value, onSelect, options,
}) => (
<Preference>
<PreferenceTitle>{title}</PreferenceTitle>
<div className="preference__options">
{options.map(option => (
<React.Fragment><input
type="radio"
onChange={() => onSelect(option.value)}
aria-label={option.ariaLabel}
name={option.name}
key={option.id}
id={option.id}
className="preference__radio-button"
value={option.value}
checked={value === option.value}
/><label htmlFor={option.id} className="preference__option">{option.label}</label>
</React.Fragment>))}
</div>
</Preference>
);

Selector.defaultProps = {
options: []
};

Selector.propTypes = {
title: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]).isRequired,
options: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string,
name: PropTypes.string,
label: PropTypes.string,
ariaLabel: PropTypes.string,
})),
onSelect: PropTypes.func.isRequired,
};

export default Selector;
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable */
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
Expand Down Expand Up @@ -40,7 +39,7 @@ const IconLinkWrapper = styled(Link)`

const isUserOwner = ({ project, user }) => (project.owner && project.owner.id === user.id);

const IDEViewMobile = (props) => {
const MobileIDEView = (props) => {
const {
preferences, ide, editorAccessibility, project, updateLintMessage, clearLintMessage, selectedFile, updateFileContent, files, closeEditorOptions, showEditorOptions, showKeyboardShortcutModal, setUnsavedChanges, startRefreshSketch, stopSketch, expandSidebar, collapseSidebar, clearConsole, console, showRuntimeErrorWarning, hideRuntimeErrorWarning, startSketch
} = props;
Expand All @@ -50,7 +49,7 @@ const IDEViewMobile = (props) => {
const [overlay, setOverlay] = useState(null);

return (
<Screen>
<Screen fullscreen>
<Header>
<IconLinkWrapper to="/" aria-label="Return to original editor">
<ExitIcon />
Expand All @@ -61,16 +60,13 @@ const IDEViewMobile = (props) => {
</div>

<div style={{ marginLeft: '2rem' }}>
<IconButton onClick={() => setOverlay('preferences')}>
<PreferencesIcon focusable="false" aria-hidden="true" />
</IconButton>
<Link
to="/mobile/preview"
onClick={() => {
// alert('starting sketch');
startSketch();
}}
>
<Link to="/mobile/preferences">
<IconButton onClick={() => setOverlay('preferences')}>
<PreferencesIcon focusable="false" aria-hidden="true" />
</IconButton>
</Link>

<Link to="/mobile/preview" onClick={() => startSketch()}>
<IconButton>
<PlayIcon viewBox="-1 -1 7 7" focusable="false" aria-hidden="true" />
</IconButton>
Expand Down Expand Up @@ -120,7 +116,7 @@ const IDEViewMobile = (props) => {
};


IDEViewMobile.propTypes = {
MobileIDEView.propTypes = {

preferences: PropTypes.shape({
fontSize: PropTypes.number.isRequired,
Expand Down Expand Up @@ -267,4 +263,4 @@ function mapDispatchToProps(dispatch) {
}


export default withRouter(connect(mapStateToProps, mapDispatchToProps)(IDEViewMobile));
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(MobileIDEView));
231 changes: 231 additions & 0 deletions client/modules/Mobile/MobilePreferences.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
import React, { useEffect } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Link, withRouter } from 'react-router';
import PropTypes from 'prop-types';
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 Header from '../../components/mobile/Header';
import Selector from '../../components/mobile/Selector';
import { ExitIcon } from '../../common/icons';
import { remSize, prop } from '../../theme';

const IconLinkWrapper = styled(Link)`
width: 3rem;
margin-right: 1.25rem;
margin-left: none;
`;

const Content = styled.div`
z-index: 0;
margin-top: ${remSize(68)};
`;


const SettingsHeader = styled(Header)`
background: transparent
`;

const SectionHeader = styled.h2`
color: ${prop('primaryTextColor')};
padding-top: 2rem
`;


const MobilePreferences = (props) => {
const {
setTheme, setAutosave, setLinewrap, setTextOutput, setGridOutput, setSoundOutput, lineNumbers, lintWarning
} = props;
const {
theme, autosave, linewrap, textOutput, gridOutput, soundOutput, setLineNumbers, setLintWarning
} = props;

const generalSettings = [
{
title: 'Theme',
value: theme,
options: [
{
value: 'light', label: 'light', ariaLabel: 'light theme on', name: 'light theme', id: 'light-theme-on'
},
{
value: 'dark', label: 'dark', ariaLabel: 'dark theme on', name: 'dark theme', id: 'dark-theme-on'
},
{
value: 'contrast', label: 'contrast', ariaLabel: 'contrast theme on', name: 'contrast theme', id: 'contrast-theme-on'
}
],
onSelect: x => setTheme(x) // setTheme
},

{
title: 'Autosave',
value: autosave,
options: [
{
value: true, label: 'On', ariaLabel: 'autosave on', name: 'autosave', id: 'autosave-on'
},
{
value: false, label: 'Off', ariaLabel: 'autosave off', name: 'autosave', id: 'autosave-off'
},
],
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)
}
];

const outputSettings = [
{
title: 'Plain-text',
value: textOutput,
options: [
{
value: true, label: 'On', ariaLabel: 'text output on', name: 'text output', id: 'text-output-on'
},
{
value: false, label: 'Off', ariaLabel: 'text output off', name: 'text output', id: 'text-output-off'
},
],
onSelect: x => setTextOutput(x)
},
{
title: 'Table-text',
value: gridOutput,
options: [
{
value: true, label: 'On', ariaLabel: 'table output on', name: 'table output', id: 'table-output-on'
},
{
value: false, label: 'Off', ariaLabel: 'table output off', name: 'table output', id: 'table-output-off'
},
],
onSelect: x => setGridOutput(x)
},
{
title: 'Sound',
value: soundOutput,
options: [
{
value: true, label: 'On', ariaLabel: 'sound output on', name: 'sound output', id: 'sound-output-on'
},
{
value: false, label: 'Off', ariaLabel: 'sound output off', name: 'sound output', id: 'sound-output-off'
},
],
onSelect: x => setSoundOutput(x)
},
];

const accessibilitySettings = [
{
title: 'Line Numbers',
value: lineNumbers,
options: [
{
value: true, label: 'On', ariaLabel: 'line numbers on', name: 'line numbers', id: 'line-numbers-on'
},
{
value: false, label: 'Off', ariaLabel: 'line numbers off', name: 'line numbers', id: 'line-numbers-off'
},
],
onSelect: x => setLineNumbers(x)
},
{
title: 'Lint Warning Sound',
value: lintWarning,
options: [
{
value: true, label: 'On', ariaLabel: 'lint warning on', name: 'lint warning', id: 'lint-warning-on'
},
{
value: false, label: 'Off', ariaLabel: 'lint warning off', name: 'lint warning', id: 'lint-warning-off'
},
],
onSelect: x => setLintWarning(x)
},
];

// useEffect(() => { });

return (
<Screen fullscreen>
<section>

<SettingsHeader>
<h1>Settings</h1>

<div style={{ marginLeft: '2rem' }}>
<IconLinkWrapper to="/mobile" aria-label="Return to ide view">
<ExitIcon />
</IconLinkWrapper>
</div>
</SettingsHeader>
<section className="preferences">
<Content>
<SectionHeader>General Settings</SectionHeader>
{ generalSettings.map(option => <Selector key={`${option.title}wrapper`} {...option} />) }

<SectionHeader>Accessibility</SectionHeader>
{ accessibilitySettings.map(option => <Selector key={`${option.title}wrapper`} {...option} />) }

<SectionHeader>Accessible Output</SectionHeader>
<h3>Used with screen reader</h3>
{ outputSettings.map(option => <Selector key={`${option.title}wrapper`} {...option} />) }

</Content>
</section>
</section>
</Screen>);
};


MobilePreferences.propTypes = {
fontSize: PropTypes.number.isRequired,
lineNumbers: PropTypes.bool.isRequired,
autosave: PropTypes.bool.isRequired,
linewrap: PropTypes.bool.isRequired,
textOutput: PropTypes.bool.isRequired,
gridOutput: PropTypes.bool.isRequired,
soundOutput: PropTypes.bool.isRequired,
lintWarning: PropTypes.bool.isRequired,
theme: PropTypes.string.isRequired,

setLinewrap: PropTypes.func.isRequired,
setLintWarning: PropTypes.func.isRequired,
setTheme: PropTypes.func.isRequired,
setFontSize: PropTypes.func.isRequired,
setLineNumbers: PropTypes.func.isRequired,
setAutosave: PropTypes.func.isRequired,
setTextOutput: PropTypes.func.isRequired,
setGridOutput: PropTypes.func.isRequired,
setSoundOutput: PropTypes.func.isRequired,
};

const mapStateToProps = state => ({
...state.preferences,
});

const mapDispatchToProps = dispatch => bindActionCreators({
...PreferencesActions,
...IdeActions
}, dispatch);


export default withRouter(connect(mapStateToProps, mapDispatchToProps)(MobilePreferences));
2 changes: 1 addition & 1 deletion client/modules/Mobile/MobileSketchView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const MobileSketchView = (props) => {
});

return (
<Screen>
<Screen fullscreen>
<Header>
<IconLinkWrapper to="/mobile" aria-label="Return to original editor">
<ExitIcon viewBox="0 0 16 16" />
Expand Down
Loading