p5.js-web-editor/client/modules/IDE/components/Preferences/index.jsx

368 lines
15 KiB
React
Raw Normal View History

import PropTypes from 'prop-types';
import React from 'react';
import { Helmet } from 'react-helmet';
2017-08-09 17:34:59 +00:00
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import { withTranslation } from 'react-i18next';
// import { bindActionCreators } from 'redux';
// import { connect } from 'react-redux';
// import * as PreferencesActions from '../actions/preferences';
2016-06-23 22:29:55 +00:00
import PlusIcon from '../../../../images/plus.svg';
import MinusIcon from '../../../../images/minus.svg';
import beepUrl from '../../../../sounds/audioAlert.mp3';
2016-06-23 22:29:55 +00:00
class Preferences extends React.Component {
2016-08-09 20:15:28 +00:00
constructor(props) {
super(props);
this.handleUpdateAutosave = this.handleUpdateAutosave.bind(this);
this.handleUpdateLinewrap = this.handleUpdateLinewrap.bind(this);
this.handleLintWarning = this.handleLintWarning.bind(this);
this.handleLineNumbers = this.handleLineNumbers.bind(this);
2019-06-18 20:54:16 +00:00
this.onFontInputChange = this.onFontInputChange.bind(this);
this.onFontInputSubmit = this.onFontInputSubmit.bind(this);
this.increaseFontSize = this.increaseFontSize.bind(this);
this.decreaseFontSize = this.decreaseFontSize.bind(this);
this.setFontSize = this.setFontSize.bind(this);
this.state = {
fontSize: props.fontSize
};
}
onFontInputChange(event) {
const INTEGER_REGEX = /^[0-9\b]+$/;
if (event.target.value === '' || INTEGER_REGEX.test(event.target.value)) {
this.setState({
fontSize: event.target.value
});
}
2016-08-09 20:15:28 +00:00
}
2019-06-18 20:54:16 +00:00
onFontInputSubmit(event) {
event.preventDefault();
let value = parseInt(this.state.fontSize, 10);
2018-05-09 02:10:52 +00:00
if (Number.isNaN(value)) {
value = 16;
}
if (value > 36) {
value = 36;
}
if (value < 8) {
value = 8;
}
2019-06-18 20:54:16 +00:00
this.setFontSize(value);
}
setFontSize(value) {
this.setState({ fontSize: value });
this.props.setFontSize(value);
}
2016-07-06 15:27:39 +00:00
2019-06-18 20:54:16 +00:00
decreaseFontSize() {
const newValue = this.state.fontSize - 2;
this.setFontSize(newValue);
}
increaseFontSize() {
const newValue = this.state.fontSize + 2;
this.setFontSize(newValue);
}
2016-08-09 20:15:28 +00:00
handleUpdateAutosave(event) {
const value = event.target.value === 'true';
this.props.setAutosave(value);
}
handleUpdateLinewrap(event) {
const value = event.target.value === 'true';
this.props.setLinewrap(value);
}
2016-08-11 18:09:59 +00:00
handleLintWarning(event) {
const value = event.target.value === 'true';
this.props.setLintWarning(value);
}
handleLineNumbers(event) {
const value = event.target.value === 'true';
this.props.setLineNumbers(value);
}
render() {
2016-09-01 03:07:43 +00:00
const beep = new Audio(beepUrl);
2016-08-29 18:39:23 +00:00
return (
<section className="preferences">
<Helmet>
<title>p5.js Web Editor | Preferences</title>
</Helmet>
2017-08-09 17:34:59 +00:00
<Tabs>
<TabList>
2019-05-23 11:02:52 +00:00
<div className="tabs__titles">
<Tab><h4 className="tabs__title">{this.props.t('Preferences.GeneralSettings')}</h4></Tab>
<Tab><h4 className="tabs__title">{this.props.t('Preferences.Accessibility')}</h4></Tab>
2017-08-09 17:34:59 +00:00
</div>
</TabList>
<TabPanel>
<div className="preference">
<h4 className="preference__title">{this.props.t('Preferences.Theme')}</h4>
2017-08-09 17:34:59 +00:00
<div className="preference__options">
<input
type="radio"
onChange={() => this.props.setTheme('light')}
aria-label={this.props.t('Preferences.LightThemeARIA')}
2017-08-09 17:34:59 +00:00
name="light theme"
id="light-theme-on"
className="preference__radio-button"
value="light"
checked={this.props.theme === 'light'}
/>
<label htmlFor="light-theme-on" className="preference__option">{this.props.t('Preferences.LightTheme')}</label>
2017-08-09 17:34:59 +00:00
<input
type="radio"
onChange={() => this.props.setTheme('dark')}
aria-label={this.props.t('Preferences.DarkThemeARIA')}
2017-08-09 17:34:59 +00:00
name="dark theme"
id="dark-theme-on"
className="preference__radio-button"
value="dark"
checked={this.props.theme === 'dark'}
/>
<label htmlFor="dark-theme-on" className="preference__option">{this.props.t('Preferences.DarkTheme')}</label>
2017-11-14 20:27:00 +00:00
<input
type="radio"
onChange={() => this.props.setTheme('contrast')}
aria-label={this.props.t('Preferences.HighContrastThemeARIA')}
2017-11-14 20:27:00 +00:00
name="high contrast theme"
id="high-contrast-theme-on"
className="preference__radio-button"
value="contrast"
checked={this.props.theme === 'contrast'}
/>
<label htmlFor="high-contrast-theme-on" className="preference__option">{this.props.t('Preferences.HighContrastTheme')}</label>
2017-08-09 17:34:59 +00:00
</div>
</div>
<div className="preference">
<h4 className="preference__title">{this.props.t('Preferences.TextSize')}</h4>
2017-08-09 17:34:59 +00:00
<button
className="preference__minus-button"
2019-06-18 20:54:16 +00:00
onClick={this.decreaseFontSize}
aria-label={this.props.t('Preferences.DecreaseFontARIA')}
2019-06-18 20:54:16 +00:00
disabled={this.state.fontSize <= 8}
2017-08-09 17:34:59 +00:00
>
<MinusIcon focusable="false" aria-hidden="true" />
<h6 className="preference__label">{this.props.t('Preferences.DecreaseFont')}</h6>
2017-08-09 17:34:59 +00:00
</button>
2019-06-18 20:54:16 +00:00
<form onSubmit={this.onFontInputSubmit}>
<input
className="preference__value"
aria-live="polite"
aria-atomic="true"
value={this.state.fontSize}
onChange={this.onFontInputChange}
type="text"
2019-06-18 20:54:16 +00:00
ref={(element) => { this.fontSizeInput = element; }}
onClick={() => { this.fontSizeInput.select(); }}
2019-06-18 20:54:16 +00:00
/>
</form>
2017-08-09 17:34:59 +00:00
<button
className="preference__plus-button"
2019-06-18 20:54:16 +00:00
onClick={this.increaseFontSize}
aria-label={this.props.t('Preferences.IncreaseFontARIA')}
2019-06-18 20:54:16 +00:00
disabled={this.state.fontSize >= 36}
2017-08-09 17:34:59 +00:00
>
<PlusIcon focusable="false" aria-hidden="true" />
<h6 className="preference__label">{this.props.t('Preferences.IncreaseFont')}</h6>
2017-08-09 17:34:59 +00:00
</button>
</div>
<div className="preference">
<h4 className="preference__title">{this.props.t('Preferences.Autosave')}</h4>
2017-08-09 17:34:59 +00:00
<div className="preference__options">
<input
type="radio"
onChange={() => this.props.setAutosave(true)}
aria-label={this.props.t('Preferences.AutosaveOnARIA')}
2017-08-09 17:34:59 +00:00
name="autosave"
id="autosave-on"
className="preference__radio-button"
value="On"
checked={this.props.autosave}
/>
<label htmlFor="autosave-on" className="preference__option">{this.props.t('Preferences.On')}</label>
2017-08-09 17:34:59 +00:00
<input
type="radio"
onChange={() => this.props.setAutosave(false)}
aria-label={this.props.t('Preferences.AutosaveOffARIA')}
2017-08-09 17:34:59 +00:00
name="autosave"
id="autosave-off"
className="preference__radio-button"
value="Off"
checked={!this.props.autosave}
/>
<label htmlFor="autosave-off" className="preference__option">{this.props.t('Preferences.Off')}</label>
2017-08-09 17:34:59 +00:00
</div>
</div>
<div className="preference">
<h4 className="preference__title">{this.props.t('Preferences.WordWrap')}</h4>
<div className="preference__options">
<input
type="radio"
onChange={() => this.props.setLinewrap(true)}
aria-label={this.props.t('Preferences.LineWrapOnARIA')}
name="linewrap"
id="linewrap-on"
className="preference__radio-button"
value="On"
checked={this.props.linewrap}
/>
<label htmlFor="linewrap-on" className="preference__option">{this.props.t('Preferences.On')}</label>
<input
type="radio"
onChange={() => this.props.setLinewrap(false)}
aria-label={this.props.t('Preferences.LineWrapOffARIA')}
name="linewrap"
id="linewrap-off"
className="preference__radio-button"
value="Off"
checked={!this.props.linewrap}
/>
<label htmlFor="linewrap-off" className="preference__option">{this.props.t('Preferences.Off')}</label>
</div>
</div>
2017-08-09 17:34:59 +00:00
</TabPanel>
<TabPanel>
<div className="preference">
<h4 className="preference__title">{this.props.t('Preferences.LineNumbers')}</h4>
<div className="preference__options">
<input
type="radio"
onChange={() => this.props.setLineNumbers(true)}
aria-label={this.props.t('Preferences.LineNumbersOnARIA')}
name="line numbers"
id="line-numbers-on"
className="preference__radio-button"
value="On"
checked={this.props.lineNumbers}
/>
<label htmlFor="line-numbers-on" className="preference__option">{this.props.t('Preferences.On')}</label>
<input
type="radio"
onChange={() => this.props.setLineNumbers(false)}
aria-label={this.props.t('Preferences.LineNumbersOffARIA')}
name="line numbers"
id="line-numbers-off"
className="preference__radio-button"
value="Off"
checked={!this.props.lineNumbers}
/>
<label htmlFor="line-numbers-off" className="preference__option">{this.props.t('Preferences.Off')}</label>
</div>
</div>
2017-08-09 17:34:59 +00:00
<div className="preference">
<h4 className="preference__title">{this.props.t('Preferences.LintWarningSound')}</h4>
2017-08-09 17:34:59 +00:00
<div className="preference__options">
<input
2017-08-17 12:51:00 +00:00
type="radio"
onChange={() => this.props.setLintWarning(true)}
aria-label={this.props.t('Preferences.LintWarningOnARIA')}
name="lint warning"
id="lint-warning-on"
2017-08-17 12:51:00 +00:00
className="preference__radio-button"
2017-08-09 17:34:59 +00:00
value="On"
checked={this.props.lintWarning}
2017-08-09 17:34:59 +00:00
/>
<label htmlFor="lint-warning-on" className="preference__option">{this.props.t('Preferences.On')}</label>
2017-08-09 17:34:59 +00:00
<input
2017-08-17 12:51:00 +00:00
type="radio"
onChange={() => this.props.setLintWarning(false)}
aria-label={this.props.t('Preferences.LintWarningOffARIA')}
name="lint warning"
id="lint-warning-off"
2017-08-17 12:51:00 +00:00
className="preference__radio-button"
value="Off"
checked={!this.props.lintWarning}
2017-08-09 17:34:59 +00:00
/>
<label htmlFor="lint-warning-off" className="preference__option">{this.props.t('Preferences.Off')}</label>
2017-08-17 12:51:00 +00:00
<button
className="preference__preview-button"
onClick={() => beep.play()}
aria-label={this.props.t('Preferences.PreviewSoundARIA')}
2017-08-17 12:51:00 +00:00
>
{this.props.t('Preferences.PreviewSound')}
2017-08-17 12:51:00 +00:00
</button>
2017-08-09 17:34:59 +00:00
</div>
</div>
<div className="preference">
<h4 className="preference__title">{this.props.t('Preferences.AccessibleTextBasedCanvas')}</h4>
<h6 className="preference__subtitle">{this.props.t('Preferences.UsedScreenReader')}</h6>
2017-08-09 17:34:59 +00:00
<div className="preference__options">
<input
type="checkbox"
onChange={(event) => {
this.props.setTextOutput(event.target.checked);
}}
aria-label={this.props.t('Preferences.TextOutputARIA')}
name="text output"
id="text-output-on"
2017-08-09 17:34:59 +00:00
value="On"
checked={(this.props.textOutput)}
2017-08-09 17:34:59 +00:00
/>
<label htmlFor="text-output-on" className="preference__option preference__canvas">{this.props.t('Preferences.PlainText')}</label>
2017-08-09 17:34:59 +00:00
<input
type="checkbox"
onChange={(event) => {
this.props.setGridOutput(event.target.checked);
}}
aria-label={this.props.t('Preferences.TableOutputARIA')}
name="table output"
id="table-output-on"
value="On"
checked={(this.props.gridOutput)}
2017-08-09 17:34:59 +00:00
/>
<label htmlFor="table-output-on" className="preference__option preference__canvas">{this.props.t('Preferences.TableText')}</label>
<input
type="checkbox"
onChange={(event) => {
this.props.setSoundOutput(event.target.checked);
}}
aria-label={this.props.t('Preferences.SoundOutputARIA')}
name="sound output"
id="sound-output-on"
value="On"
checked={(this.props.soundOutput)}
/>
<label htmlFor="sound-output-on" className="preference__option preference__canvas">{this.props.t('Preferences.Sound')}</label>
2017-08-09 17:34:59 +00:00
</div>
</div>
</TabPanel>
</Tabs>
</section>
);
}
2016-06-23 22:29:55 +00:00
}
Preferences.propTypes = {
fontSize: PropTypes.number.isRequired,
lineNumbers: PropTypes.bool.isRequired,
2016-08-09 20:15:28 +00:00
setFontSize: PropTypes.func.isRequired,
autosave: PropTypes.bool.isRequired,
linewrap: PropTypes.bool.isRequired,
setLineNumbers: PropTypes.func.isRequired,
2016-08-11 18:09:59 +00:00
setAutosave: PropTypes.func.isRequired,
setLinewrap: PropTypes.func.isRequired,
textOutput: PropTypes.bool.isRequired,
gridOutput: PropTypes.bool.isRequired,
soundOutput: PropTypes.bool.isRequired,
2016-08-12 19:50:33 +00:00
setTextOutput: PropTypes.func.isRequired,
setGridOutput: PropTypes.func.isRequired,
setSoundOutput: PropTypes.func.isRequired,
2016-08-11 18:09:59 +00:00
lintWarning: PropTypes.bool.isRequired,
setLintWarning: PropTypes.func.isRequired,
theme: PropTypes.string.isRequired,
2018-05-09 02:10:52 +00:00
setTheme: PropTypes.func.isRequired,
t: PropTypes.func.isRequired,
};
export default withTranslation()(Preferences);