diff --git a/client/constants.js b/client/constants.js index f769c33e..82baab02 100644 --- a/client/constants.js +++ b/client/constants.js @@ -12,6 +12,7 @@ export const STOP_ACCESSIBLE_OUTPUT = 'STOP_ACCESSIBLE_OUTPUT'; export const OPEN_PREFERENCES = 'OPEN_PREFERENCES'; export const CLOSE_PREFERENCES = 'CLOSE_PREFERENCES'; export const SET_FONT_SIZE = 'SET_FONT_SIZE'; +export const SET_LINE_NUMBERS = 'SET_LINE_NUMBERS'; export const AUTH_USER = 'AUTH_USER'; export const UNAUTH_USER = 'UNAUTH_USER'; diff --git a/client/modules/IDE/actions/preferences.js b/client/modules/IDE/actions/preferences.js index 567425cc..ae8e2438 100644 --- a/client/modules/IDE/actions/preferences.js +++ b/client/modules/IDE/actions/preferences.js @@ -32,6 +32,24 @@ export function setFontSize(value) { }; } +export function setLineNumbers(value) { + return (dispatch, getState) => { + dispatch({ + type: ActionTypes.SET_LINE_NUMBERS, + value + }); + const state = getState(); + if (state.user.authenticated) { + const formParams = { + preferences: { + lineNumbers: value + } + }; + updatePreferences(formParams, dispatch); + } + }; +} + export function setAutosave(value) { return (dispatch, getState) => { dispatch({ diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index 9ce1b443..cb330b32 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -80,7 +80,7 @@ class Editor extends React.Component { this.widgets = []; this._cm = CodeMirror(this.codemirrorContainer, { // eslint-disable-line theme: `p5-${this.props.theme}`, - lineNumbers: true, + lineNumbers: this.props.lineNumbers, styleActiveLine: true, inputStyle: 'contenteditable', lineWrapping: this.props.linewrap, @@ -181,6 +181,9 @@ class Editor extends React.Component { if (this.props.theme !== prevProps.theme) { this._cm.setOption('theme', `p5-${this.props.theme}`); } + if (this.props.lineNumbers !== prevProps.lineNumbers) { + this._cm.setOption('lineNumbers', this.props.lineNumbers); + } if (prevProps.consoleEvents !== this.props.consoleEvents) { this.props.showRuntimeErrorWarning(); @@ -342,6 +345,7 @@ class Editor extends React.Component { } Editor.propTypes = { + lineNumbers: PropTypes.bool.isRequired, lintWarning: PropTypes.bool.isRequired, linewrap: PropTypes.bool.isRequired, lintMessages: PropTypes.arrayOf(PropTypes.shape({ diff --git a/client/modules/IDE/components/Preferences.jsx b/client/modules/IDE/components/Preferences.jsx index eb31ddc7..74fe2108 100644 --- a/client/modules/IDE/components/Preferences.jsx +++ b/client/modules/IDE/components/Preferences.jsx @@ -17,6 +17,7 @@ class Preferences extends React.Component { this.handleUpdateAutosave = this.handleUpdateAutosave.bind(this); this.handleUpdateLinewrap = this.handleUpdateLinewrap.bind(this); this.handleLintWarning = this.handleLintWarning.bind(this); + this.handleLineNumbers = this.handleLineNumbers.bind(this); this.onFontInputChange = this.onFontInputChange.bind(this); this.onFontInputSubmit = this.onFontInputSubmit.bind(this); this.increaseFontSize = this.increaseFontSize.bind(this); @@ -82,6 +83,11 @@ class Preferences extends React.Component { this.props.setLintWarning(value); } + handleLineNumbers(event) { + const value = event.target.value === 'true'; + this.props.setLineNumbers(value); + } + render() { const beep = new Audio(beepUrl); @@ -225,6 +231,33 @@ class Preferences extends React.Component { +
+

Line numbers

+
+ this.props.setLineNumbers(true)} + aria-label="line numbers on" + name="line numbers" + id="line-numbers-on" + className="preference__radio-button" + value="On" + checked={this.props.lineNumbers} + /> + + this.props.setLineNumbers(false)} + aria-label="line numbers off" + name="line numbers" + id="line-numbers-off" + className="preference__radio-button" + value="Off" + checked={!this.props.lineNumbers} + /> + +
+

Lint warning sound

@@ -311,9 +344,11 @@ class Preferences extends React.Component { Preferences.propTypes = { fontSize: PropTypes.number.isRequired, + lineNumbers: PropTypes.bool.isRequired, setFontSize: PropTypes.func.isRequired, autosave: PropTypes.bool.isRequired, linewrap: PropTypes.bool.isRequired, + setLineNumbers: PropTypes.func.isRequired, setAutosave: PropTypes.func.isRequired, setLinewrap: PropTypes.func.isRequired, textOutput: PropTypes.bool.isRequired, diff --git a/client/modules/IDE/pages/IDEView.jsx b/client/modules/IDE/pages/IDEView.jsx index 179c9739..072360ae 100644 --- a/client/modules/IDE/pages/IDEView.jsx +++ b/client/modules/IDE/pages/IDEView.jsx @@ -206,6 +206,8 @@ class IDEView extends React.Component { setFontSize={this.props.setFontSize} autosave={this.props.preferences.autosave} linewrap={this.props.preferences.linewrap} + lineNumbers={this.props.preferences.lineNumbers} + setLineNumbers={this.props.setLineNumbers} setAutosave={this.props.setAutosave} setLinewrap={this.props.setLinewrap} lintWarning={this.props.preferences.lintWarning} @@ -271,6 +273,7 @@ class IDEView extends React.Component { 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} @@ -518,6 +521,7 @@ IDEView.propTypes = { 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, @@ -528,6 +532,7 @@ IDEView.propTypes = { closePreferences: PropTypes.func.isRequired, setFontSize: PropTypes.func.isRequired, setAutosave: PropTypes.func.isRequired, + setLineNumbers: PropTypes.func.isRequired, setLinewrap: PropTypes.func.isRequired, setLintWarning: PropTypes.func.isRequired, setTextOutput: PropTypes.func.isRequired, diff --git a/client/modules/IDE/reducers/preferences.js b/client/modules/IDE/reducers/preferences.js index 738effa4..080a7343 100644 --- a/client/modules/IDE/reducers/preferences.js +++ b/client/modules/IDE/reducers/preferences.js @@ -4,6 +4,7 @@ const initialState = { fontSize: 18, autosave: true, linewrap: true, + lineNumbers: true, lintWarning: false, textOutput: false, gridOutput: false, @@ -34,6 +35,8 @@ const preferences = (state = initialState, action) => { return Object.assign({}, state, { theme: action.value }); case ActionTypes.SET_AUTOREFRESH: return Object.assign({}, state, { autorefresh: action.value }); + case ActionTypes.SET_LINE_NUMBERS: + return Object.assign({}, state, { lineNumbers: action.value }); default: return state; } diff --git a/server/models/user.js b/server/models/user.js index 5cbf12be..fe456435 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -24,6 +24,7 @@ const userSchema = new Schema({ tokens: Array, preferences: { fontSize: { type: Number, default: 18 }, + lineNumbers: { type: Boolean, default: true }, indentationAmount: { type: Number, default: 2 }, isTabIndent: { type: Boolean, default: false }, autosave: { type: Boolean, default: true },