Accessibility (#361)
* add p5 interceptor submodule * update package * remoce interceptor * update interceptor; * merge scripts * change postinstall script * refactor interceptor files * remove merge conflicts * change source files * add registry class * provide seperate outputs for text and grid * switch textOutput to boolean * make both modules usable together * update interceptor for safari * fix grid label * add sound output as well * change file strucure * change constants * change input lables * switch submodule branch * change variable name * change grid to table * remove role from table elements * switch submodule branch
This commit is contained in:
parent
8e1a65daed
commit
82207a50d3
16 changed files with 261 additions and 122 deletions
|
@ -4,8 +4,8 @@ export const TOGGLE_SKETCH = 'TOGGLE_SKETCH';
|
||||||
export const START_SKETCH = 'START_SKETCH';
|
export const START_SKETCH = 'START_SKETCH';
|
||||||
export const STOP_SKETCH = 'STOP_SKETCH';
|
export const STOP_SKETCH = 'STOP_SKETCH';
|
||||||
|
|
||||||
export const START_TEXT_OUTPUT = 'START_TEXT_OUTPUT';
|
export const START_ACCESSIBLE_OUTPUT = 'START_ACCESSIBLE_OUTPUT';
|
||||||
export const STOP_TEXT_OUTPUT = 'STOP_TEXT_OUTPUT';
|
export const STOP_ACCESSIBLE_OUTPUT = 'STOP_ACCESSIBLE_OUTPUT';
|
||||||
|
|
||||||
export const OPEN_PREFERENCES = 'OPEN_PREFERENCES';
|
export const OPEN_PREFERENCES = 'OPEN_PREFERENCES';
|
||||||
export const CLOSE_PREFERENCES = 'CLOSE_PREFERENCES';
|
export const CLOSE_PREFERENCES = 'CLOSE_PREFERENCES';
|
||||||
|
@ -69,6 +69,8 @@ export const SET_AUTOSAVE = 'SET_AUTOSAVE';
|
||||||
export const SET_LINT_WARNING = 'SET_LINT_WARNING';
|
export const SET_LINT_WARNING = 'SET_LINT_WARNING';
|
||||||
export const SET_PREFERENCES = 'SET_PREFERENCES';
|
export const SET_PREFERENCES = 'SET_PREFERENCES';
|
||||||
export const SET_TEXT_OUTPUT = 'SET_TEXT_OUTPUT';
|
export const SET_TEXT_OUTPUT = 'SET_TEXT_OUTPUT';
|
||||||
|
export const SET_GRID_OUTPUT = 'SET_GRID_OUTPUT';
|
||||||
|
export const SET_SOUND_OUTPUT = 'SET_SOUND_OUTPUT';
|
||||||
|
|
||||||
export const OPEN_PROJECT_OPTIONS = 'OPEN_PROJECT_OPTIONS';
|
export const OPEN_PROJECT_OPTIONS = 'OPEN_PROJECT_OPTIONS';
|
||||||
export const CLOSE_PROJECT_OPTIONS = 'CLOSE_PROJECT_OPTIONS';
|
export const CLOSE_PROJECT_OPTIONS = 'CLOSE_PROJECT_OPTIONS';
|
||||||
|
|
|
@ -31,15 +31,15 @@ export function endSketchRefresh() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function startTextOutput() {
|
export function startAccessibleOutput() {
|
||||||
return {
|
return {
|
||||||
type: ActionTypes.START_TEXT_OUTPUT
|
type: ActionTypes.START_ACCESSIBLE_OUTPUT
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stopTextOutput() {
|
export function stopAccessibleOutput() {
|
||||||
return {
|
return {
|
||||||
type: ActionTypes.STOP_TEXT_OUTPUT
|
type: ActionTypes.STOP_ACCESSIBLE_OUTPUT
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,42 @@ export function setTextOutput(value) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setGridOutput(value) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({
|
||||||
|
type: ActionTypes.SET_GRID_OUTPUT,
|
||||||
|
value
|
||||||
|
});
|
||||||
|
const state = getState();
|
||||||
|
if (state.user.authenticated) {
|
||||||
|
const formParams = {
|
||||||
|
preferences: {
|
||||||
|
gridOutput: value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
updatePreferences(formParams, dispatch);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setSoundOutput(value) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({
|
||||||
|
type: ActionTypes.SET_SOUND_OUTPUT,
|
||||||
|
value
|
||||||
|
});
|
||||||
|
const state = getState();
|
||||||
|
if (state.user.authenticated) {
|
||||||
|
const formParams = {
|
||||||
|
preferences: {
|
||||||
|
soundOutput: value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
updatePreferences(formParams, dispatch);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function setTheme(value) {
|
export function setTheme(value) {
|
||||||
// return {
|
// return {
|
||||||
// type: ActionTypes.SET_THEME,
|
// type: ActionTypes.SET_THEME,
|
||||||
|
@ -180,4 +216,3 @@ export function setAutorefresh(value) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
51
client/modules/IDE/components/AccessibleOutput.jsx
Normal file
51
client/modules/IDE/components/AccessibleOutput.jsx
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import GridOutput from '../components/GridOutput';
|
||||||
|
import TextOutput from '../components/TextOutput';
|
||||||
|
|
||||||
|
class AccessibleOutput extends React.Component {
|
||||||
|
componentDidMount() {
|
||||||
|
this.accessibleOutputModal.focus();
|
||||||
|
}
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
// if the user explicitly clicks on the play button, want to refocus on the text output
|
||||||
|
if (this.props.isPlaying && this.props.previewIsRefreshing) {
|
||||||
|
this.accessibleOutputModal.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
className="accessible-output"
|
||||||
|
id="canvas-sub"
|
||||||
|
ref={(element) => { this.accessibleOutputModal = element; }}
|
||||||
|
tabIndex="0"
|
||||||
|
aria-label="accessible-output"
|
||||||
|
title="canvas text output"
|
||||||
|
>
|
||||||
|
{(() => { // eslint-disable-line
|
||||||
|
if (this.props.textOutput) {
|
||||||
|
return (
|
||||||
|
<TextOutput />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})()}
|
||||||
|
{(() => { // eslint-disable-line
|
||||||
|
if (this.props.gridOutput) {
|
||||||
|
return (
|
||||||
|
<GridOutput />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})()}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AccessibleOutput.propTypes = {
|
||||||
|
isPlaying: PropTypes.bool.isRequired,
|
||||||
|
previewIsRefreshing: PropTypes.bool.isRequired,
|
||||||
|
textOutput: PropTypes.bool.isRequired,
|
||||||
|
gridOutput: PropTypes.bool.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AccessibleOutput;
|
38
client/modules/IDE/components/GridOutput.jsx
Normal file
38
client/modules/IDE/components/GridOutput.jsx
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
|
||||||
|
class GridOutput extends React.Component {
|
||||||
|
componentDidMount() {
|
||||||
|
this.GridOutputModal.focus();
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
id="gridOutput-content"
|
||||||
|
ref={(element) => { this.GridOutputModal = element; }}
|
||||||
|
>
|
||||||
|
<h2> Grid Output </h2>
|
||||||
|
<p
|
||||||
|
tabIndex="0"
|
||||||
|
role="main"
|
||||||
|
id="gridOutput-content-summary"
|
||||||
|
aria-label="grid output summary"
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<table
|
||||||
|
id="gridOutput-content-table"
|
||||||
|
summary="grid output details"
|
||||||
|
>
|
||||||
|
</table>
|
||||||
|
<div
|
||||||
|
tabIndex="0"
|
||||||
|
role="main"
|
||||||
|
id="gridOutput-content-details"
|
||||||
|
aria-label="grid output details"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GridOutput;
|
|
@ -261,50 +261,41 @@ class Preferences extends React.Component {
|
||||||
|
|
||||||
<div className="preference__options">
|
<div className="preference__options">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="checkbox"
|
||||||
onChange={() => this.props.setTextOutput(1)}
|
onChange={(event) => {
|
||||||
|
this.props.setTextOutput(event.target.checked);
|
||||||
|
}}
|
||||||
aria-label="text output on"
|
aria-label="text output on"
|
||||||
name="text output"
|
name="text output"
|
||||||
id="text-output-on"
|
id="text-output-on"
|
||||||
className="preference__radio-button"
|
|
||||||
value="On"
|
value="On"
|
||||||
checked={Boolean(this.props.textOutput === 1)}
|
checked={(this.props.textOutput)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="text-output-on" className="preference__option preference__canvas">Plain-text</label>
|
<label htmlFor="text-output-on" className="preference__option preference__canvas">Plain-text</label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="checkbox"
|
||||||
onChange={() => this.props.setTextOutput(2)}
|
onChange={(event) => {
|
||||||
aria-label="table text output on"
|
this.props.setGridOutput(event.target.checked);
|
||||||
name="table text output"
|
}}
|
||||||
id="grid-output-on"
|
aria-label="table output on"
|
||||||
className="preference__radio-button"
|
name="table output"
|
||||||
value="Grid On"
|
id="table-output-on"
|
||||||
checked={Boolean(this.props.textOutput === 2)}
|
value="On"
|
||||||
|
checked={(this.props.gridOutput)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="grid-output-on" className="preference__option preference__canvas">Table-text</label>
|
<label htmlFor="table-output-on" className="preference__option preference__canvas">Table-text</label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="checkbox"
|
||||||
onChange={() => this.props.setTextOutput(3)}
|
onChange={(event) => {
|
||||||
|
this.props.setSoundOutput(event.target.checked);
|
||||||
|
}}
|
||||||
aria-label="sound output on"
|
aria-label="sound output on"
|
||||||
name="sound output"
|
name="sound output"
|
||||||
id="sound-output-on"
|
id="sound-output-on"
|
||||||
className="preference__radio-button"
|
|
||||||
value="On"
|
value="On"
|
||||||
checked={Boolean(this.props.textOutput === 3)}
|
checked={(this.props.soundOutput)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="sound-output-on" className="preference__option preference__canvas">Sound</label>
|
<label htmlFor="sound-output-on" className="preference__option preference__canvas">Sound</label>
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
onChange={() => this.props.setTextOutput(0)}
|
|
||||||
aria-label="text output off"
|
|
||||||
name="text output"
|
|
||||||
id="text-output-off"
|
|
||||||
className="preference__radio-button"
|
|
||||||
value="Off"
|
|
||||||
checked={!(this.props.textOutput)}
|
|
||||||
/>
|
|
||||||
<label htmlFor="text-output-off" className="preference__option preference__canvas">Off</label>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -324,8 +315,12 @@ Preferences.propTypes = {
|
||||||
setFontSize: PropTypes.func.isRequired,
|
setFontSize: PropTypes.func.isRequired,
|
||||||
autosave: PropTypes.bool.isRequired,
|
autosave: PropTypes.bool.isRequired,
|
||||||
setAutosave: PropTypes.func.isRequired,
|
setAutosave: PropTypes.func.isRequired,
|
||||||
textOutput: PropTypes.number.isRequired,
|
textOutput: PropTypes.bool.isRequired,
|
||||||
|
gridOutput: PropTypes.bool.isRequired,
|
||||||
|
soundOutput: PropTypes.bool.isRequired,
|
||||||
setTextOutput: PropTypes.func.isRequired,
|
setTextOutput: PropTypes.func.isRequired,
|
||||||
|
setGridOutput: PropTypes.func.isRequired,
|
||||||
|
setSoundOutput: PropTypes.func.isRequired,
|
||||||
lintWarning: PropTypes.bool.isRequired,
|
lintWarning: PropTypes.bool.isRequired,
|
||||||
setLintWarning: PropTypes.func.isRequired,
|
setLintWarning: PropTypes.func.isRequired,
|
||||||
theme: PropTypes.string.isRequired,
|
theme: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -114,7 +114,7 @@ class PreviewFrame extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if user switches textoutput preferences
|
// if user switches textoutput preferences
|
||||||
if (this.props.isTextOutputPlaying !== prevProps.isTextOutputPlaying) {
|
if (this.props.isAccessibleOutputPlaying !== prevProps.isAccessibleOutputPlaying) {
|
||||||
this.renderSketch();
|
this.renderSketch();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -124,6 +124,16 @@ class PreviewFrame extends React.Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.props.gridOutput !== prevProps.gridOutput) {
|
||||||
|
this.renderSketch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.props.soundOutput !== prevProps.soundOutput) {
|
||||||
|
this.renderSketch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.props.fullView && this.props.files[0].id !== prevProps.files[0].id) {
|
if (this.props.fullView && this.props.files[0].id !== prevProps.files[0].id) {
|
||||||
this.renderSketch();
|
this.renderSketch();
|
||||||
}
|
}
|
||||||
|
@ -165,38 +175,41 @@ class PreviewFrame extends React.Component {
|
||||||
'/loop-protect.min.js',
|
'/loop-protect.min.js',
|
||||||
'/hijackConsole.js'
|
'/hijackConsole.js'
|
||||||
];
|
];
|
||||||
if (this.props.isTextOutputPlaying || (this.props.textOutput !== 0 && this.props.isPlaying)) {
|
if (this.props.isAccessibleOutputPlaying || ((this.props.textOutput || this.props.gridOutput || this.props.soundOutput) && this.props.isPlaying)) {
|
||||||
let interceptorScripts = [];
|
let interceptorScripts = [];
|
||||||
if (this.props.textOutput === 0) {
|
interceptorScripts = [
|
||||||
this.props.setTextOutput(1);
|
'/p5-interceptor/registry.js',
|
||||||
|
'/p5-interceptor/loadData.js',
|
||||||
|
'/p5-interceptor/interceptorHelperFunctions.js',
|
||||||
|
'/p5-interceptor/baseInterceptor.js',
|
||||||
|
'/p5-interceptor/entities/entity.min.js',
|
||||||
|
'/p5-interceptor/ntc.min.js'
|
||||||
|
];
|
||||||
|
if (!this.props.textOutput && !this.props.gridOutput && !this.props.soundOutput) {
|
||||||
|
this.props.setTextOutput(true);
|
||||||
}
|
}
|
||||||
if (this.props.textOutput === 1) {
|
if (this.props.textOutput) {
|
||||||
interceptorScripts = [
|
let textInterceptorScripts = [];
|
||||||
'/p5-interceptor/registry.js',
|
textInterceptorScripts = [
|
||||||
'/p5-interceptor/loadData.js',
|
|
||||||
'/p5-interceptor/interceptorHelperFunctions.js',
|
|
||||||
'/p5-interceptor/baseInterceptor.js',
|
|
||||||
'/p5-interceptor/entities/entity.min.js',
|
|
||||||
'/p5-interceptor/textInterceptor/interceptorFunctions.js',
|
'/p5-interceptor/textInterceptor/interceptorFunctions.js',
|
||||||
'/p5-interceptor/textInterceptor/interceptorP5.js',
|
'/p5-interceptor/textInterceptor/interceptorP5.js'
|
||||||
'/p5-interceptor/ntc.min.js'
|
|
||||||
];
|
];
|
||||||
} else if (this.props.textOutput === 2) {
|
interceptorScripts = interceptorScripts.concat(textInterceptorScripts);
|
||||||
interceptorScripts = [
|
}
|
||||||
'/p5-interceptor/registry.js',
|
if (this.props.gridOutput) {
|
||||||
'/p5-interceptor/loadData.js',
|
let gridInterceptorScripts = [];
|
||||||
'/p5-interceptor/interceptorHelperFunctions.js',
|
gridInterceptorScripts = [
|
||||||
'/p5-interceptor/baseInterceptor.js',
|
|
||||||
'/p5-interceptor/entities/entity.min.js',
|
|
||||||
'/p5-interceptor/gridInterceptor/interceptorFunctions.js',
|
'/p5-interceptor/gridInterceptor/interceptorFunctions.js',
|
||||||
'/p5-interceptor/gridInterceptor/interceptorP5.js',
|
'/p5-interceptor/gridInterceptor/interceptorP5.js'
|
||||||
'/p5-interceptor/ntc.min.js'
|
|
||||||
];
|
];
|
||||||
} else if (this.props.textOutput === 3) {
|
interceptorScripts = interceptorScripts.concat(gridInterceptorScripts);
|
||||||
interceptorScripts = [
|
}
|
||||||
'/p5-interceptor/loadData.js',
|
if (this.props.soundOutput) {
|
||||||
|
let soundInterceptorScripts = [];
|
||||||
|
soundInterceptorScripts = [
|
||||||
'/p5-interceptor/soundInterceptor/interceptorP5.js'
|
'/p5-interceptor/soundInterceptor/interceptorP5.js'
|
||||||
];
|
];
|
||||||
|
interceptorScripts = interceptorScripts.concat(soundInterceptorScripts);
|
||||||
}
|
}
|
||||||
scriptsToInject = scriptsToInject.concat(interceptorScripts);
|
scriptsToInject = scriptsToInject.concat(interceptorScripts);
|
||||||
}
|
}
|
||||||
|
@ -373,8 +386,10 @@ class PreviewFrame extends React.Component {
|
||||||
|
|
||||||
PreviewFrame.propTypes = {
|
PreviewFrame.propTypes = {
|
||||||
isPlaying: PropTypes.bool.isRequired,
|
isPlaying: PropTypes.bool.isRequired,
|
||||||
isTextOutputPlaying: PropTypes.bool.isRequired,
|
isAccessibleOutputPlaying: PropTypes.bool.isRequired,
|
||||||
textOutput: PropTypes.number.isRequired,
|
textOutput: PropTypes.bool.isRequired,
|
||||||
|
gridOutput: PropTypes.bool.isRequired,
|
||||||
|
soundOutput: PropTypes.bool.isRequired,
|
||||||
setTextOutput: PropTypes.func.isRequired,
|
setTextOutput: PropTypes.func.isRequired,
|
||||||
htmlFile: PropTypes.shape({
|
htmlFile: PropTypes.shape({
|
||||||
content: PropTypes.string.isRequired
|
content: PropTypes.string.isRequired
|
||||||
|
|
|
@ -1,28 +1,16 @@
|
||||||
import React, { PropTypes } from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
class TextOutput extends React.Component {
|
class TextOutput extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.canvasTextOutput.focus();
|
this.TextOutputModal.focus();
|
||||||
}
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
// if the user explicitly clicks on the play button, want to refocus on the text output
|
|
||||||
if (this.props.isPlaying && this.props.previewIsRefreshing) {
|
|
||||||
this.canvasTextOutput.focus();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className="text-output"
|
id="textOutput-content"
|
||||||
id="canvas-sub"
|
ref={(element) => { this.TextOutputModal = element; }}
|
||||||
ref={(element) => { this.canvasTextOutput = element; }}
|
|
||||||
tabIndex="0"
|
|
||||||
aria-label="text-output"
|
|
||||||
title="canvas text output"
|
|
||||||
>
|
>
|
||||||
<h2> Output </h2>
|
<h2> Text Output </h2>
|
||||||
<section id="textOutput-content">
|
|
||||||
</section>
|
|
||||||
<p
|
<p
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
role="main"
|
role="main"
|
||||||
|
@ -31,10 +19,8 @@ class TextOutput extends React.Component {
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
<table
|
<table
|
||||||
tabIndex="0"
|
|
||||||
role="main"
|
|
||||||
id="textOutput-content-table"
|
id="textOutput-content-table"
|
||||||
aria-label="text output details"
|
summary="text output details"
|
||||||
>
|
>
|
||||||
</table>
|
</table>
|
||||||
<div
|
<div
|
||||||
|
@ -49,9 +35,4 @@ class TextOutput extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextOutput.propTypes = {
|
|
||||||
isPlaying: PropTypes.bool.isRequired,
|
|
||||||
previewIsRefreshing: PropTypes.bool.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TextOutput;
|
export default TextOutput;
|
||||||
|
|
|
@ -64,7 +64,7 @@ class Toolbar extends React.Component {
|
||||||
className="toolbar__play-sketch-button"
|
className="toolbar__play-sketch-button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.props.clearConsole();
|
this.props.clearConsole();
|
||||||
this.props.startTextOutput();
|
this.props.startAccessibleOutput();
|
||||||
this.props.startSketchAndRefresh();
|
this.props.startSketchAndRefresh();
|
||||||
}}
|
}}
|
||||||
aria-label="play sketch"
|
aria-label="play sketch"
|
||||||
|
@ -85,7 +85,7 @@ class Toolbar extends React.Component {
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={stopButtonClass}
|
className={stopButtonClass}
|
||||||
onClick={() => { this.props.stopTextOutput(); this.props.stopSketch(); }}
|
onClick={() => { this.props.stopAccessibleOutput(); this.props.stopSketch(); }}
|
||||||
aria-label="stop sketch"
|
aria-label="stop sketch"
|
||||||
>
|
>
|
||||||
<InlineSVG src={stopUrl} alt="Stop Sketch" />
|
<InlineSVG src={stopUrl} alt="Stop Sketch" />
|
||||||
|
@ -184,8 +184,8 @@ Toolbar.propTypes = {
|
||||||
isPlaying: PropTypes.bool.isRequired,
|
isPlaying: PropTypes.bool.isRequired,
|
||||||
preferencesIsVisible: PropTypes.bool.isRequired,
|
preferencesIsVisible: PropTypes.bool.isRequired,
|
||||||
stopSketch: PropTypes.func.isRequired,
|
stopSketch: PropTypes.func.isRequired,
|
||||||
startTextOutput: PropTypes.func.isRequired,
|
startAccessibleOutput: PropTypes.func.isRequired,
|
||||||
stopTextOutput: PropTypes.func.isRequired,
|
stopAccessibleOutput: PropTypes.func.isRequired,
|
||||||
setProjectName: PropTypes.func.isRequired,
|
setProjectName: PropTypes.func.isRequired,
|
||||||
openPreferences: PropTypes.func.isRequired,
|
openPreferences: PropTypes.func.isRequired,
|
||||||
owner: PropTypes.shape({
|
owner: PropTypes.shape({
|
||||||
|
|
|
@ -7,7 +7,7 @@ import Editor from '../components/Editor';
|
||||||
import Sidebar from '../components/Sidebar';
|
import Sidebar from '../components/Sidebar';
|
||||||
import PreviewFrame from '../components/PreviewFrame';
|
import PreviewFrame from '../components/PreviewFrame';
|
||||||
import Toolbar from '../components/Toolbar';
|
import Toolbar from '../components/Toolbar';
|
||||||
import TextOutput from '../components/TextOutput';
|
import AccessibleOutput from '../components/AccessibleOutput';
|
||||||
import Preferences from '../components/Preferences';
|
import Preferences from '../components/Preferences';
|
||||||
import NewFileModal from '../components/NewFileModal';
|
import NewFileModal from '../components/NewFileModal';
|
||||||
import NewFolderModal from '../components/NewFolderModal';
|
import NewFolderModal from '../components/NewFolderModal';
|
||||||
|
@ -165,15 +165,14 @@ class IDEView extends React.Component {
|
||||||
this.props.startSketchAndRefresh();
|
this.props.startSketchAndRefresh();
|
||||||
} else if (e.keyCode === 50 && ((e.metaKey && this.isMac) || (e.ctrlKey && !this.isMac)) && e.shiftKey) {
|
} else if (e.keyCode === 50 && ((e.metaKey && this.isMac) || (e.ctrlKey && !this.isMac)) && e.shiftKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.setTextOutput(0);
|
this.props.setTextOutput(false);
|
||||||
|
this.props.setGridOutput(false);
|
||||||
|
this.props.setSoundOutput(false);
|
||||||
} else if (e.keyCode === 49 && ((e.metaKey && this.isMac) || (e.ctrlKey && !this.isMac)) && e.shiftKey) {
|
} else if (e.keyCode === 49 && ((e.metaKey && this.isMac) || (e.ctrlKey && !this.isMac)) && e.shiftKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (this.props.preferences.textOutput === 3) {
|
this.props.setTextOutput(true);
|
||||||
this.props.preferences.textOutput = 1;
|
this.props.setGridOutput(true);
|
||||||
} else {
|
this.props.setSoundOutput(true);
|
||||||
this.props.preferences.textOutput += 1;
|
|
||||||
}
|
|
||||||
this.props.setTextOutput(this.props.preferences.textOutput);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,8 +216,8 @@ class IDEView extends React.Component {
|
||||||
className="Toolbar"
|
className="Toolbar"
|
||||||
isPlaying={this.props.ide.isPlaying}
|
isPlaying={this.props.ide.isPlaying}
|
||||||
stopSketch={this.props.stopSketch}
|
stopSketch={this.props.stopSketch}
|
||||||
startTextOutput={this.props.startTextOutput}
|
startAccessibleOutput={this.props.startAccessibleOutput}
|
||||||
stopTextOutput={this.props.stopTextOutput}
|
stopAccessibleOutput={this.props.stopAccessibleOutput}
|
||||||
projectName={this.props.project.name}
|
projectName={this.props.project.name}
|
||||||
setProjectName={this.props.setProjectName}
|
setProjectName={this.props.setProjectName}
|
||||||
showEditProjectName={this.props.showEditProjectName}
|
showEditProjectName={this.props.showEditProjectName}
|
||||||
|
@ -228,6 +227,8 @@ class IDEView extends React.Component {
|
||||||
serveSecure={this.props.project.serveSecure}
|
serveSecure={this.props.project.serveSecure}
|
||||||
setServeSecure={this.props.setServeSecure}
|
setServeSecure={this.props.setServeSecure}
|
||||||
setTextOutput={this.props.setTextOutput}
|
setTextOutput={this.props.setTextOutput}
|
||||||
|
setGridOutput={this.props.setGridOutput}
|
||||||
|
setSoundOutput={this.props.setSoundOutput}
|
||||||
owner={this.props.project.owner}
|
owner={this.props.project.owner}
|
||||||
project={this.props.project}
|
project={this.props.project}
|
||||||
infiniteLoop={this.props.ide.infiniteLoop}
|
infiniteLoop={this.props.ide.infiniteLoop}
|
||||||
|
@ -254,7 +255,10 @@ class IDEView extends React.Component {
|
||||||
lintWarning={this.props.preferences.lintWarning}
|
lintWarning={this.props.preferences.lintWarning}
|
||||||
setLintWarning={this.props.setLintWarning}
|
setLintWarning={this.props.setLintWarning}
|
||||||
textOutput={this.props.preferences.textOutput}
|
textOutput={this.props.preferences.textOutput}
|
||||||
|
gridOutput={this.props.preferences.gridOutput}
|
||||||
setTextOutput={this.props.setTextOutput}
|
setTextOutput={this.props.setTextOutput}
|
||||||
|
setGridOutput={this.props.setGridOutput}
|
||||||
|
setSoundOutput={this.props.setSoundOutput}
|
||||||
theme={this.props.preferences.theme}
|
theme={this.props.preferences.theme}
|
||||||
setTheme={this.props.setTheme}
|
setTheme={this.props.setTheme}
|
||||||
/>
|
/>
|
||||||
|
@ -346,11 +350,13 @@ class IDEView extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{(() => {
|
{(() => {
|
||||||
if ((this.props.preferences.textOutput && this.props.ide.isPlaying) || this.props.ide.isTextOutputPlaying) {
|
if (((this.props.preferences.textOutput || this.props.preferences.gridOutput || this.props.preferences.soundOutput) && this.props.ide.isPlaying) || this.props.ide.isAccessibleOutputPlaying) {
|
||||||
return (
|
return (
|
||||||
<TextOutput
|
<AccessibleOutput
|
||||||
isPlaying={this.props.ide.isPlaying}
|
isPlaying={this.props.ide.isPlaying}
|
||||||
previewIsRefreshing={this.props.ide.previewIsRefreshing}
|
previewIsRefreshing={this.props.ide.previewIsRefreshing}
|
||||||
|
textOutput={this.props.preferences.textOutput}
|
||||||
|
gridOutput={this.props.preferences.gridOutput}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -362,9 +368,13 @@ class IDEView extends React.Component {
|
||||||
files={this.props.files}
|
files={this.props.files}
|
||||||
content={this.props.selectedFile.content}
|
content={this.props.selectedFile.content}
|
||||||
isPlaying={this.props.ide.isPlaying}
|
isPlaying={this.props.ide.isPlaying}
|
||||||
isTextOutputPlaying={this.props.ide.isTextOutputPlaying}
|
isAccessibleOutputPlaying={this.props.ide.isAccessibleOutputPlaying}
|
||||||
textOutput={this.props.preferences.textOutput}
|
textOutput={this.props.preferences.textOutput}
|
||||||
|
gridOutput={this.props.preferences.gridOutput}
|
||||||
|
soundOutput={this.props.preferences.soundOutput}
|
||||||
setTextOutput={this.props.setTextOutput}
|
setTextOutput={this.props.setTextOutput}
|
||||||
|
setGridOutput={this.props.setGridOutput}
|
||||||
|
setSoundOutput={this.props.setSoundOutput}
|
||||||
dispatchConsoleEvent={this.props.dispatchConsoleEvent}
|
dispatchConsoleEvent={this.props.dispatchConsoleEvent}
|
||||||
autorefresh={this.props.preferences.autorefresh}
|
autorefresh={this.props.preferences.autorefresh}
|
||||||
previewIsRefreshing={this.props.ide.previewIsRefreshing}
|
previewIsRefreshing={this.props.ide.previewIsRefreshing}
|
||||||
|
@ -494,7 +504,7 @@ IDEView.propTypes = {
|
||||||
saveProject: PropTypes.func.isRequired,
|
saveProject: PropTypes.func.isRequired,
|
||||||
ide: PropTypes.shape({
|
ide: PropTypes.shape({
|
||||||
isPlaying: PropTypes.bool.isRequired,
|
isPlaying: PropTypes.bool.isRequired,
|
||||||
isTextOutputPlaying: PropTypes.bool.isRequired,
|
isAccessibleOutputPlaying: PropTypes.bool.isRequired,
|
||||||
consoleEvent: PropTypes.array,
|
consoleEvent: PropTypes.array,
|
||||||
modalIsVisible: PropTypes.bool.isRequired,
|
modalIsVisible: PropTypes.bool.isRequired,
|
||||||
sidebarIsExpanded: PropTypes.bool.isRequired,
|
sidebarIsExpanded: PropTypes.bool.isRequired,
|
||||||
|
@ -516,8 +526,8 @@ IDEView.propTypes = {
|
||||||
helpType: PropTypes.string
|
helpType: PropTypes.string
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
stopSketch: PropTypes.func.isRequired,
|
stopSketch: PropTypes.func.isRequired,
|
||||||
startTextOutput: PropTypes.func.isRequired,
|
startAccessibleOutput: PropTypes.func.isRequired,
|
||||||
stopTextOutput: PropTypes.func.isRequired,
|
stopAccessibleOutput: PropTypes.func.isRequired,
|
||||||
project: PropTypes.shape({
|
project: PropTypes.shape({
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
|
@ -542,7 +552,9 @@ IDEView.propTypes = {
|
||||||
isTabIndent: PropTypes.bool.isRequired,
|
isTabIndent: PropTypes.bool.isRequired,
|
||||||
autosave: PropTypes.bool.isRequired,
|
autosave: PropTypes.bool.isRequired,
|
||||||
lintWarning: PropTypes.bool.isRequired,
|
lintWarning: PropTypes.bool.isRequired,
|
||||||
textOutput: PropTypes.number.isRequired,
|
textOutput: PropTypes.bool.isRequired,
|
||||||
|
gridOutput: PropTypes.bool.isRequired,
|
||||||
|
soundOutput: PropTypes.bool.isRequired,
|
||||||
theme: PropTypes.string.isRequired,
|
theme: PropTypes.string.isRequired,
|
||||||
autorefresh: PropTypes.bool.isRequired
|
autorefresh: PropTypes.bool.isRequired
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
@ -554,6 +566,8 @@ IDEView.propTypes = {
|
||||||
setAutosave: PropTypes.func.isRequired,
|
setAutosave: PropTypes.func.isRequired,
|
||||||
setLintWarning: PropTypes.func.isRequired,
|
setLintWarning: PropTypes.func.isRequired,
|
||||||
setTextOutput: PropTypes.func.isRequired,
|
setTextOutput: PropTypes.func.isRequired,
|
||||||
|
setGridOutput: PropTypes.func.isRequired,
|
||||||
|
setSoundOutput: PropTypes.func.isRequired,
|
||||||
files: PropTypes.arrayOf(PropTypes.shape({
|
files: PropTypes.arrayOf(PropTypes.shape({
|
||||||
id: PropTypes.string.isRequired,
|
id: PropTypes.string.isRequired,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import * as ActionTypes from '../../../constants';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
isPlaying: false,
|
isPlaying: false,
|
||||||
isTextOutputPlaying: false,
|
isAccessibleOutputPlaying: false,
|
||||||
modalIsVisible: false,
|
modalIsVisible: false,
|
||||||
sidebarIsExpanded: false,
|
sidebarIsExpanded: false,
|
||||||
consoleIsExpanded: true,
|
consoleIsExpanded: true,
|
||||||
|
@ -27,10 +27,10 @@ const ide = (state = initialState, action) => {
|
||||||
return Object.assign({}, state, { isPlaying: true });
|
return Object.assign({}, state, { isPlaying: true });
|
||||||
case ActionTypes.STOP_SKETCH:
|
case ActionTypes.STOP_SKETCH:
|
||||||
return Object.assign({}, state, { isPlaying: false });
|
return Object.assign({}, state, { isPlaying: false });
|
||||||
case ActionTypes.START_TEXT_OUTPUT:
|
case ActionTypes.START_ACCESSIBLE_OUTPUT:
|
||||||
return Object.assign({}, state, { isTextOutputPlaying: true });
|
return Object.assign({}, state, { isAccessibleOutputPlaying: true });
|
||||||
case ActionTypes.STOP_TEXT_OUTPUT:
|
case ActionTypes.STOP_ACCESSIBLE_OUTPUT:
|
||||||
return Object.assign({}, state, { isTextOutputPlaying: false });
|
return Object.assign({}, state, { isAccessibleOutputPlaying: false });
|
||||||
case ActionTypes.CONSOLE_EVENT:
|
case ActionTypes.CONSOLE_EVENT:
|
||||||
return Object.assign({}, state, { consoleEvent: action.event });
|
return Object.assign({}, state, { consoleEvent: action.event });
|
||||||
case ActionTypes.SHOW_MODAL:
|
case ActionTypes.SHOW_MODAL:
|
||||||
|
|
|
@ -6,7 +6,9 @@ const initialState = {
|
||||||
isTabIndent: true,
|
isTabIndent: true,
|
||||||
autosave: true,
|
autosave: true,
|
||||||
lintWarning: false,
|
lintWarning: false,
|
||||||
textOutput: 0,
|
textOutput: false,
|
||||||
|
gridOutput: false,
|
||||||
|
soundOutput: false,
|
||||||
theme: 'light',
|
theme: 'light',
|
||||||
autorefresh: false
|
autorefresh: false
|
||||||
};
|
};
|
||||||
|
@ -31,6 +33,10 @@ const preferences = (state = initialState, action) => {
|
||||||
return Object.assign({}, state, { lintWarning: action.value });
|
return Object.assign({}, state, { lintWarning: action.value });
|
||||||
case ActionTypes.SET_TEXT_OUTPUT:
|
case ActionTypes.SET_TEXT_OUTPUT:
|
||||||
return Object.assign({}, state, { textOutput: action.value });
|
return Object.assign({}, state, { textOutput: action.value });
|
||||||
|
case ActionTypes.SET_GRID_OUTPUT:
|
||||||
|
return Object.assign({}, state, { gridOutput: action.value });
|
||||||
|
case ActionTypes.SET_SOUND_OUTPUT:
|
||||||
|
return Object.assign({}, state, { soundOutput: action.value });
|
||||||
case ActionTypes.SET_PREFERENCES:
|
case ActionTypes.SET_PREFERENCES:
|
||||||
return action.preferences;
|
return action.preferences;
|
||||||
case ActionTypes.SET_THEME:
|
case ActionTypes.SET_THEME:
|
||||||
|
|
|
@ -151,5 +151,5 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.preference__option.preference__canvas:not(:last-child) {
|
.preference__option.preference__canvas:not(:last-child) {
|
||||||
padding-right: #{20 / $base-font-size}rem;
|
padding-right: #{14 / $base-font-size}rem;
|
||||||
}
|
}
|
|
@ -31,7 +31,7 @@
|
||||||
@extend %hidden-element;
|
@extend %hidden-element;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-output {
|
.accessible-output {
|
||||||
@extend %hidden-element;
|
@extend %hidden-element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,9 @@ const userSchema = new Schema({
|
||||||
isTabIndent: { type: Boolean, default: false },
|
isTabIndent: { type: Boolean, default: false },
|
||||||
autosave: { type: Boolean, default: true },
|
autosave: { type: Boolean, default: true },
|
||||||
lintWarning: { type: Boolean, default: false },
|
lintWarning: { type: Boolean, default: false },
|
||||||
textOutput: { type: Number, default: 0 },
|
textOutput: { type: Boolean, default: false },
|
||||||
|
gridOutput: { type: Boolean, default: false },
|
||||||
|
soundOutput: { type: Boolean, default: false },
|
||||||
theme: { type: String, default: 'light' },
|
theme: { type: String, default: 'light' },
|
||||||
autorefresh: { type: Boolean, default: false }
|
autorefresh: { type: Boolean, default: false }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 344fedf8d868c62adc571bf4212c6bea3cd20247
|
Subproject commit 5b924f3460886b82d72d0ab0d709f323f8b9a588
|
Loading…
Reference in a new issue