From 2de3720358818fbc027d96499b000006830cdd85 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Sat, 4 Aug 2018 17:17:11 +0800 Subject: [PATCH 01/45] init --- client/modules/IDE/components/Console.jsx | 60 +++++++++----- .../modules/IDE/components/ConsoleInput.jsx | 78 +++++++++++++++++++ .../modules/IDE/components/PreviewFrame.jsx | 31 +++++++- client/styles/abstracts/_variables.scss | 12 ++- client/styles/components/_console-input.scss | 39 ++++++++++ client/styles/components/_console.scss | 52 +++++++++++-- client/styles/main.scss | 1 + client/utils/createScopedEvaluationChain.js | 17 ++++ client/utils/evaluateConsole.js | 19 +++++ 9 files changed, 276 insertions(+), 33 deletions(-) create mode 100644 client/modules/IDE/components/ConsoleInput.jsx create mode 100644 client/styles/components/_console-input.scss create mode 100644 client/utils/createScopedEvaluationChain.js create mode 100644 client/utils/evaluateConsole.js diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index 997878ea82..6e86b40e04 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -12,9 +12,12 @@ import debugLightUrl from '../../../images/console-debug-light.svg'; import debugDarkUrl from '../../../images/console-debug-dark.svg'; import infoLightUrl from '../../../images/console-info-light.svg'; import infoDarkUrl from '../../../images/console-info-dark.svg'; +import ConsoleInput from './ConsoleInput'; const upArrowUrl = require('../../../images/up-arrow.svg'); const downArrowUrl = require('../../../images/down-arrow.svg'); +const leftArrowUrl = require('../../../images/left-arrow.svg'); +const rightArrowUrl = require('../../../images/right-arrow.svg'); class Console extends React.Component { componentDidUpdate(prevProps) { @@ -100,30 +103,45 @@ class Console extends React.Component { -
{ this.consoleMessages = element; }} className="preview-console__messages"> - {this.props.consoleEvents.map((consoleEvent) => { - const { arguments: args, method, times } = consoleEvent; - const { theme } = this.props; - Object.assign(consoleEvent, { data: this.formatData(args) }); - if (Object.keys(args).length === 0) { +
+ +
{ this.consoleMessages = element; }} className="preview-console__messages"> + {this.props.consoleEvents.map((consoleEvent) => { + const { arguments: args, method, times } = consoleEvent; + const { expression, source } = consoleEvent; + const { theme } = this.props; + Object.assign(consoleEvent, { data: this.formatData(args) }); + if (Object.keys(args).length === 0) { + return ( +
+ undefined +
+ ); + } return ( -
- undefined +
+ { expression && +
+ +
{expression}
+
+ } +
+ { source === 'console' && + + } + { times > 1 && +
{times}
+ } + +
); - } - return ( -
- { times > 1 && -
{times}
- } - -
- ); - })} + })} +
); diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx new file mode 100644 index 0000000000..b3a58b4c2f --- /dev/null +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -0,0 +1,78 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import bindAll from 'lodash/bindAll'; +import CodeMirror from 'codemirror'; +import beautifyJS from 'js-beautify'; +import InlineSVG from 'react-inlinesvg'; + +const rightArrowUrl = require('../../../images/right-arrow.svg'); + +class ConsoleInput extends React.Component { + componentDidMount() { + this._cm = CodeMirror(this.codemirrorContainer, { // eslint-disable-line + theme: 'p5-console', + scrollbarStyle: null, + keyMap: 'sublime' + }); + + this._cm.setOption('extraKeys', { + 'Up': cm => cm.undo(), + 'Down': cm => cm.redo() + }); + + this._cm.focus(); + this._cm.setCursor({ line: 1, ch: 5 }); + + this._cm.on('keydown', (cm, e) => { + if (e.keyCode === 13) { + const value = cm.getValue(); + if (value.trim(' ') === '') { + return false; + } + window.postMessage([{ + method: 'log', + arguments: value, + source: 'console' + }], '*'); + + cm.setValue(''); + } + return true; + }); + + this._cm.on('beforeChange', (cm, changeObj) => { + const typedNewLine = changeObj.origin === '+input' && changeObj.text.join('') === ''; + if (typedNewLine) { + return changeObj.cancel(); + } + + const pastedNewLine = changeObj.origin === 'paste' && changeObj.text.length > 1; + if (pastedNewLine) { + const newText = changeObj.text.join(' '); + return changeObj.update(null, null, [newText]); + } + + return null; + }); + } + + componentWillUnmount() { + this._cm = null; + } + + _cm: CodeMirror.Editor + + render() { + return ( +
+ +
{ this.codemirrorContainer = element; }} className="console__editor" /> +
+ ); + } +} + + +export default ConsoleInput; diff --git a/client/modules/IDE/components/PreviewFrame.jsx b/client/modules/IDE/components/PreviewFrame.jsx index 8e4f13508e..8d153eabd1 100644 --- a/client/modules/IDE/components/PreviewFrame.jsx +++ b/client/modules/IDE/components/PreviewFrame.jsx @@ -7,6 +7,7 @@ import srcDoc from 'srcdoc-polyfill'; import loopProtect from 'loop-protect'; import { JSHINT } from 'jshint'; import decomment from 'decomment'; +import { Hook, Unhook } from 'console-feed'; import { getBlobUrl } from '../actions/files'; import { resolvePathToFile } from '../../../../server/utils/filePath'; import { @@ -19,6 +20,7 @@ import { } from '../../../../server/utils/fileUtils'; import { hijackConsoleErrorsScript, startTag, getAllScriptOffsets } from '../../../utils/consoleUtils'; +import handleConsoleExpressions from '../../../utils/evaluateConsole'; class PreviewFrame extends React.Component { constructor(props) { @@ -80,7 +82,34 @@ class PreviewFrame extends React.Component { handleConsoleEvent(messageEvent) { if (Array.isArray(messageEvent.data)) { messageEvent.data.every((message, index, arr) => { - const { arguments: args } = message; + const { arguments: args, source } = message; + if (source === 'console') { + let consoleInfo = ''; + const consoleBuffer = []; + const LOGWAIT = 100; + Hook(window.console, (log) => { + const { method, data: arg } = log[0]; + consoleBuffer.push({ + method, + arguments: arg, + source: 'sketch' + }); + }); + setInterval(() => { + if (consoleBuffer.length > 0) { + window.postMessage(consoleBuffer, '*'); + consoleBuffer.length = 0; + } + }, LOGWAIT); + + consoleInfo = handleConsoleExpressions(args); + Unhook(window.console); + if (consoleInfo === '') { + return false; + } + + Object.assign(message, { expression: args, arguments: Array.of(consoleInfo) }); + } let hasInfiniteLoop = false; Object.keys(args).forEach((key) => { if (typeof args[key] === 'string' && args[key].includes('Exiting potential infinite loop')) { diff --git a/client/styles/abstracts/_variables.scss b/client/styles/abstracts/_variables.scss index 8c8eb6fbb7..659a9a0d58 100644 --- a/client/styles/abstracts/_variables.scss +++ b/client/styles/abstracts/_variables.scss @@ -41,7 +41,9 @@ $themes: ( icon-toast-hover-color: $white, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #eee, - console-color: $white, + console-logged-times-color: $white, + console-chevron-color: rgb(128,128,128), + console-active-chevron-color: #00b8ff, console-header-background-color: #d6d6d6, console-header-color: #b1b1b1, console-info-background-color: $lightsteelblue, @@ -87,7 +89,9 @@ $themes: ( icon-toast-hover-color: $white, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #4f4f4f, - console-color: $black, + console-logged-times-color: $black, + console-chevron-color: $white, + console-active-chevron-color: #40a9f3, console-header-background-color: #3f3f3f, console-header-color: #b5b5b5, console-info-background-color: $lightsteelblue, @@ -132,7 +136,9 @@ $themes: ( icon-toast-hover-color: $yellow, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #4f4f4f, - console-color: $black, + console-logged-times-color: $black, + console-chevron-color: $white, + console-active-chevron-color: #40a9f3, console-header-background-color: #3f3f3f, console-header-color: #b5b5b5, console-info-background-color: $lightsteelblue, diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss new file mode 100644 index 0000000000..5032358481 --- /dev/null +++ b/client/styles/components/_console-input.scss @@ -0,0 +1,39 @@ +.console__input { + padding-left: 20px; + position: relative; + height: 22px; +} + +.console__input .console-active__chevron { + left: 10px; + position: absolute; + top: 2px; + & svg { + width: 6px; + height: 10px; + } + & g { + @include themify() { + fill: getThemifyVariable('console-active-chevron-color'); + } + } +} + +.console__editor { + margin-left: 8px; + height: 20px; +} + +.console__editor .CodeMirror { + border: none; + font-family: Consolas,Lucida Console,Courier New,monospace; + @include themify() { + background-color: getThemifyVariable('console-background-color'); + } + + .CodeMirror-line { + @include themify() { + color: getThemifyVariable('primary-text-color'); + } + } +} \ No newline at end of file diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index 53048614e8..01b6c41bce 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -16,14 +16,6 @@ position:relative; text-align:left; } - - .preview-console__message { - @include themify() { - color: getThemifyVariable('console-color'); - } - flex: 1 0 auto; - position: relative; - } } .preview-console__header { @@ -117,3 +109,47 @@ } } } + +.preview-console__body { + display: flex; + flex-direction: column-reverse; + + .preview-console__output .preview-console__expression div { + margin-left: 35px; + line-height: 22px; + font-size: 12px; + font-family: Consolas,Lucida Console,Courier New,monospace; + @include themify() { + color: getThemifyVariable('console-color'); + } + } + + .preview-console__message, .preview-console__expression { + .console__chevron { + left: 10px; + position: absolute; + top: 2px; + & svg { + width: 6px; + height: 10px; + } + & g { + @include themify() { + fill: getThemifyVariable('console-chevron-color'); + } + } + } + flex: 1 0 auto; + position: relative; + } + + .preview-console__message { + @include themify() { + color: getThemifyVariable('console-logged-times-color'); + } + } + + .preview-console__expression { + height: 22px; + } +} diff --git a/client/styles/main.scss b/client/styles/main.scss index 01069b3e47..d16eaa6d7f 100644 --- a/client/styles/main.scss +++ b/client/styles/main.scss @@ -40,6 +40,7 @@ @import 'components/keyboard-shortcuts'; @import 'components/copyable-input'; @import 'components/feedback'; +@import 'components/console-input'; @import 'layout/ide'; @import 'layout/fullscreen'; diff --git a/client/utils/createScopedEvaluationChain.js b/client/utils/createScopedEvaluationChain.js new file mode 100644 index 0000000000..202b04e028 --- /dev/null +++ b/client/utils/createScopedEvaluationChain.js @@ -0,0 +1,17 @@ +// eslint-disable-next-line no-unused-vars +function createScopedEvaluationChain(__yieldScopedEval) { + function __makeEvaluateExpression(evalInClosure) { + return function (expr) { + return evalInClosure(` + __yieldScopedEval(__makeEvaluateExpression(function(expr) { + return eval(expr); + })); + ${expr} + `); + }; + } + // eslint-disable-next-line no-eval + return __makeEvaluateExpression(expr => eval(expr)); +} + +export default createScopedEvaluationChain; diff --git a/client/utils/evaluateConsole.js b/client/utils/evaluateConsole.js new file mode 100644 index 0000000000..cf0ccf5742 --- /dev/null +++ b/client/utils/evaluateConsole.js @@ -0,0 +1,19 @@ +import createScopedEvaluationChain from './createScopedEvaluationChain'; + +let evalNext = createScopedEvaluationChain((next) => { + evalNext = next; +}); + +export default function handleConsoleExpressions(expression) { + try { + return evalNext(expression); + } catch (e) { + const data = e.toString(); + window.postMessage([{ + method: 'error', + arguments: data, + source: 'sketch' + }], '*'); + } + return ''; +} From 66024eebf2b107579f2fc1c8e628d3b99a0287f6 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Sat, 4 Aug 2018 19:16:22 +0800 Subject: [PATCH 02/45] use rem in scss/remove require --- client/modules/IDE/components/Console.jsx | 9 ++++----- client/styles/components/_console-input.scss | 16 ++++++++-------- client/styles/components/_console.scss | 17 +++++++++-------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index 6e86b40e04..d59199e09d 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -12,13 +12,12 @@ import debugLightUrl from '../../../images/console-debug-light.svg'; import debugDarkUrl from '../../../images/console-debug-dark.svg'; import infoLightUrl from '../../../images/console-info-light.svg'; import infoDarkUrl from '../../../images/console-info-dark.svg'; +import upArrowUrl from '../../../images/up-arrow.svg'; +import downArrowUrl from '../../../images/down-arrow.svg'; +import leftArrowUrl from '../../../images/left-arrow.svg'; +import rightArrowUrl from '../../../images/right-arrow.svg'; import ConsoleInput from './ConsoleInput'; -const upArrowUrl = require('../../../images/up-arrow.svg'); -const downArrowUrl = require('../../../images/down-arrow.svg'); -const leftArrowUrl = require('../../../images/left-arrow.svg'); -const rightArrowUrl = require('../../../images/right-arrow.svg'); - class Console extends React.Component { componentDidUpdate(prevProps) { this.consoleMessages.scrollTop = this.consoleMessages.scrollHeight; diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss index 5032358481..cf0082566b 100644 --- a/client/styles/components/_console-input.scss +++ b/client/styles/components/_console-input.scss @@ -1,16 +1,16 @@ .console__input { - padding-left: 20px; + padding-left: #{20 / $base-font-size}rem; position: relative; - height: 22px; + height: #{22 / $base-font-size}rem; } .console__input .console-active__chevron { - left: 10px; + left: #{10 / $base-font-size}rem; position: absolute; - top: 2px; + top: #{2 / $base-font-size}rem; & svg { - width: 6px; - height: 10px; + width: #{6 / $base-font-size}rem; + height: #{10 / $base-font-size}rem; } & g { @include themify() { @@ -20,8 +20,8 @@ } .console__editor { - margin-left: 8px; - height: 20px; + margin-left: #{8 / $base-font-size}rem; + height: #{20 / $base-font-size}rem; } .console__editor .CodeMirror { diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index 01b6c41bce..1b2da5047d 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -83,6 +83,7 @@ font-weight: bold; margin: #{2 / $base-font-size}rem 0 0 #{8 / $base-font-size}rem; + border-radius: #{10 / $base-font-size}rem; padding: #{1 / $base-font-size}rem #{4 / $base-font-size}rem; z-index: 100; left: 0; @@ -115,9 +116,9 @@ flex-direction: column-reverse; .preview-console__output .preview-console__expression div { - margin-left: 35px; - line-height: 22px; - font-size: 12px; + margin-left: #{35 / $base-font-size}rem; + line-height: #{22 / $base-font-size}rem; + font-size: #{12 / $base-font-size}rem; font-family: Consolas,Lucida Console,Courier New,monospace; @include themify() { color: getThemifyVariable('console-color'); @@ -126,12 +127,12 @@ .preview-console__message, .preview-console__expression { .console__chevron { - left: 10px; + left: #{10 / $base-font-size}rem; position: absolute; - top: 2px; + top: #{2 / $base-font-size}rem; & svg { - width: 6px; - height: 10px; + width: #{6 / $base-font-size}rem; + height: #{10 / $base-font-size}rem; } & g { @include themify() { @@ -150,6 +151,6 @@ } .preview-console__expression { - height: 22px; + height: #{22 / $base-font-size}rem; } } From 5f98050272299e12f36d9cc77672831fcfccbb7a Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Sat, 4 Aug 2018 19:28:36 +0800 Subject: [PATCH 03/45] fix linting --- client/modules/IDE/components/ConsoleInput.jsx | 7 ++----- client/styles/components/_console.scss | 4 ++-- client/utils/createScopedEvaluationChain.js | 4 +--- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index b3a58b4c2f..d832100480 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -1,8 +1,5 @@ -import PropTypes from 'prop-types'; import React from 'react'; -import bindAll from 'lodash/bindAll'; import CodeMirror from 'codemirror'; -import beautifyJS from 'js-beautify'; import InlineSVG from 'react-inlinesvg'; const rightArrowUrl = require('../../../images/right-arrow.svg'); @@ -16,8 +13,8 @@ class ConsoleInput extends React.Component { }); this._cm.setOption('extraKeys', { - 'Up': cm => cm.undo(), - 'Down': cm => cm.redo() + Up: cm => cm.undo(), + Down: cm => cm.redo() }); this._cm.focus(); diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index 1b2da5047d..3b52f00703 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -3,8 +3,8 @@ background: getThemifyVariable('console-background-color'); border-color: getThemifyVariable('ide-border-color'); } - border-left: 1px solid; - border-right: 1px solid; + border-left: #{1 / $base-font-size}rem solid; + border-right: #{1 / $base-font-size}rem solid; width: 100%; height: 100%; z-index: 1000; diff --git a/client/utils/createScopedEvaluationChain.js b/client/utils/createScopedEvaluationChain.js index 202b04e028..808dcf8eed 100644 --- a/client/utils/createScopedEvaluationChain.js +++ b/client/utils/createScopedEvaluationChain.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line no-unused-vars function createScopedEvaluationChain(__yieldScopedEval) { function __makeEvaluateExpression(evalInClosure) { return function (expr) { @@ -10,8 +9,7 @@ function createScopedEvaluationChain(__yieldScopedEval) { `); }; } - // eslint-disable-next-line no-eval - return __makeEvaluateExpression(expr => eval(expr)); + return __makeEvaluateExpression(expr => eval(expr)); // eslint-disable-line } export default createScopedEvaluationChain; From d65f871cc584ff020c95eb0623de945c12303e41 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Sat, 4 Aug 2018 20:26:37 +0800 Subject: [PATCH 04/45] update style --- client/modules/IDE/components/Console.jsx | 4 ++-- client/modules/IDE/components/ConsoleInput.jsx | 2 +- client/styles/abstracts/_variables.scss | 15 +++++++++------ client/styles/components/_console-input.scss | 6 +++--- client/styles/components/_console.scss | 6 +++--- .../components/_p5-console-codemirror-theme.scss | 11 +++++++++++ client/styles/main.scss | 1 + client/utils/createScopedEvaluationChain.js | 9 +++------ 8 files changed, 33 insertions(+), 21 deletions(-) create mode 100644 client/styles/components/_p5-console-codemirror-theme.scss diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index d59199e09d..a4b58990a8 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -121,13 +121,13 @@ class Console extends React.Component {
{ expression &&
- +
{expression}
}
{ source === 'console' && - + } { times > 1 &&
{times}
diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index d832100480..51617ad9c8 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -64,7 +64,7 @@ class ConsoleInput extends React.Component {
- +
{ this.codemirrorContainer = element; }} className="console__editor" />
); diff --git a/client/styles/abstracts/_variables.scss b/client/styles/abstracts/_variables.scss index 659a9a0d58..d2a0dbbf25 100644 --- a/client/styles/abstracts/_variables.scss +++ b/client/styles/abstracts/_variables.scss @@ -41,9 +41,10 @@ $themes: ( icon-toast-hover-color: $white, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #eee, + console-color: $black, console-logged-times-color: $white, - console-chevron-color: rgb(128,128,128), - console-active-chevron-color: #00b8ff, + console-arrow-color: rgb(128,128,128), + console-active-arrow-color: #00b8ff, console-header-background-color: #d6d6d6, console-header-color: #b1b1b1, console-info-background-color: $lightsteelblue, @@ -89,9 +90,10 @@ $themes: ( icon-toast-hover-color: $white, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #4f4f4f, + console-color: $white, console-logged-times-color: $black, - console-chevron-color: $white, - console-active-chevron-color: #40a9f3, + console-arrow-color: $white, + console-active-arrow-color: #40a9f3, console-header-background-color: #3f3f3f, console-header-color: #b5b5b5, console-info-background-color: $lightsteelblue, @@ -136,9 +138,10 @@ $themes: ( icon-toast-hover-color: $yellow, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #4f4f4f, + console-color: $white, console-logged-times-color: $black, - console-chevron-color: $white, - console-active-chevron-color: #40a9f3, + console-arrow-color: $white, + console-active-arrow-color: #40a9f3, console-header-background-color: #3f3f3f, console-header-color: #b5b5b5, console-info-background-color: $lightsteelblue, diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss index cf0082566b..a1ee56b861 100644 --- a/client/styles/components/_console-input.scss +++ b/client/styles/components/_console-input.scss @@ -4,7 +4,7 @@ height: #{22 / $base-font-size}rem; } -.console__input .console-active__chevron { +.console__input .console-active__arrow { left: #{10 / $base-font-size}rem; position: absolute; top: #{2 / $base-font-size}rem; @@ -14,7 +14,7 @@ } & g { @include themify() { - fill: getThemifyVariable('console-active-chevron-color'); + fill: getThemifyVariable('console-active-arrow-color'); } } } @@ -33,7 +33,7 @@ .CodeMirror-line { @include themify() { - color: getThemifyVariable('primary-text-color'); + color: getThemifyVariable('console-color'); } } } \ No newline at end of file diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index 3b52f00703..64a6099ecd 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -119,14 +119,14 @@ margin-left: #{35 / $base-font-size}rem; line-height: #{22 / $base-font-size}rem; font-size: #{12 / $base-font-size}rem; - font-family: Consolas,Lucida Console,Courier New,monospace; + font-family: Consolas, Lucida Console, Courier New, monospace; @include themify() { color: getThemifyVariable('console-color'); } } .preview-console__message, .preview-console__expression { - .console__chevron { + .console__arrow { left: #{10 / $base-font-size}rem; position: absolute; top: #{2 / $base-font-size}rem; @@ -136,7 +136,7 @@ } & g { @include themify() { - fill: getThemifyVariable('console-chevron-color'); + fill: getThemifyVariable('console-arrow-color'); } } } diff --git a/client/styles/components/_p5-console-codemirror-theme.scss b/client/styles/components/_p5-console-codemirror-theme.scss new file mode 100644 index 0000000000..09a15ae6df --- /dev/null +++ b/client/styles/components/_p5-console-codemirror-theme.scss @@ -0,0 +1,11 @@ +.cm-s-p5-console .cm-number{ + @include themify() { + color: getThemifyVariable('console-color'); + } +} + +.cm-s-p5-console .cm-tag{ + @include themify() { + color: getThemifyVariable('console-color'); + } +} \ No newline at end of file diff --git a/client/styles/main.scss b/client/styles/main.scss index d16eaa6d7f..679a7e693e 100644 --- a/client/styles/main.scss +++ b/client/styles/main.scss @@ -14,6 +14,7 @@ @import 'components/p5-light-codemirror-theme'; @import 'components/p5-dark-codemirror-theme'; @import 'components/p5-contrast-codemirror-theme'; +@import 'components/p5-console-codemirror-theme'; @import 'components/editor'; @import 'components/nav'; @import 'components/toolbar'; diff --git a/client/utils/createScopedEvaluationChain.js b/client/utils/createScopedEvaluationChain.js index 808dcf8eed..bb8bda0b24 100644 --- a/client/utils/createScopedEvaluationChain.js +++ b/client/utils/createScopedEvaluationChain.js @@ -1,13 +1,10 @@ function createScopedEvaluationChain(__yieldScopedEval) { function __makeEvaluateExpression(evalInClosure) { - return function (expr) { - return evalInClosure(` + return expr => evalInClosure(` __yieldScopedEval(__makeEvaluateExpression(function(expr) { return eval(expr); - })); - ${expr} - `); - }; + })); + ${expr}`); } return __makeEvaluateExpression(expr => eval(expr)); // eslint-disable-line } From 94008721a018bd99552e336975b7a344679ae7f5 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Sat, 4 Aug 2018 21:22:38 +0800 Subject: [PATCH 05/45] add reference --- client/utils/createScopedEvaluationChain.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/utils/createScopedEvaluationChain.js b/client/utils/createScopedEvaluationChain.js index bb8bda0b24..6870ab0750 100644 --- a/client/utils/createScopedEvaluationChain.js +++ b/client/utils/createScopedEvaluationChain.js @@ -1,3 +1,4 @@ +// Reference: https://github.com/popcodeorg/popcode/blob/4885baee880a612d5a420427b207699ef790d6c4/src/previewSupport/createScopedEvaluationChain.js function createScopedEvaluationChain(__yieldScopedEval) { function __makeEvaluateExpression(evalInClosure) { return expr => evalInClosure(` From a79958af9d0b69f3fa8ab5b0c7f3250a46a52d28 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Fri, 31 Aug 2018 01:03:56 +0800 Subject: [PATCH 06/45] update --- client/utils/createScopedEvaluationChain.js | 13 ------------- client/utils/evaluateConsole.js | 8 ++------ client/utils/evaluateExpression.js | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+), 19 deletions(-) delete mode 100644 client/utils/createScopedEvaluationChain.js create mode 100644 client/utils/evaluateExpression.js diff --git a/client/utils/createScopedEvaluationChain.js b/client/utils/createScopedEvaluationChain.js deleted file mode 100644 index 6870ab0750..0000000000 --- a/client/utils/createScopedEvaluationChain.js +++ /dev/null @@ -1,13 +0,0 @@ -// Reference: https://github.com/popcodeorg/popcode/blob/4885baee880a612d5a420427b207699ef790d6c4/src/previewSupport/createScopedEvaluationChain.js -function createScopedEvaluationChain(__yieldScopedEval) { - function __makeEvaluateExpression(evalInClosure) { - return expr => evalInClosure(` - __yieldScopedEval(__makeEvaluateExpression(function(expr) { - return eval(expr); - })); - ${expr}`); - } - return __makeEvaluateExpression(expr => eval(expr)); // eslint-disable-line -} - -export default createScopedEvaluationChain; diff --git a/client/utils/evaluateConsole.js b/client/utils/evaluateConsole.js index cf0ccf5742..7dcefb4c26 100644 --- a/client/utils/evaluateConsole.js +++ b/client/utils/evaluateConsole.js @@ -1,12 +1,8 @@ -import createScopedEvaluationChain from './createScopedEvaluationChain'; - -let evalNext = createScopedEvaluationChain((next) => { - evalNext = next; -}); +import evaluateExpression from './evaluateExpression'; export default function handleConsoleExpressions(expression) { try { - return evalNext(expression); + return evaluateExpression()(expression); } catch (e) { const data = e.toString(); window.postMessage([{ diff --git a/client/utils/evaluateExpression.js b/client/utils/evaluateExpression.js new file mode 100644 index 0000000000..f9261c66e8 --- /dev/null +++ b/client/utils/evaluateExpression.js @@ -0,0 +1,21 @@ +function __makeEvaluateExpression(evalInClosure) { + return expr => evalInClosure(` + ${expr}`); +} + +function evaluateExpression() { + return __makeEvaluateExpression((expr) => { + let newExpr = expr; + try { + const wrapped = `(${expr})`; + const validate = new Function(wrapped); // eslint-disable-line + newExpr = wrapped; // eslint-disable-line + } catch (e) { + // We shouldn't wrap the expression + } + + return (0, eval)(newExpr); // eslint-disable-line + }); +} + +export default evaluateExpression; From fe70c202f4b400805dd0498554eceef8761c851d Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Tue, 4 Sep 2018 00:41:09 +0800 Subject: [PATCH 07/45] support syntax highlighting --- client/modules/IDE/components/Console.jsx | 2 +- client/modules/IDE/components/ConsoleInput.jsx | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index a4b58990a8..5cf455b69c 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -103,7 +103,7 @@ class Console extends React.Component {
- +
{ this.consoleMessages = element; }} className="preview-console__messages"> {this.props.consoleEvents.map((consoleEvent) => { const { arguments: args, method, times } = consoleEvent; diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 51617ad9c8..eea7a92740 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -1,3 +1,4 @@ +import PropTypes from 'prop-types'; import React from 'react'; import CodeMirror from 'codemirror'; import InlineSVG from 'react-inlinesvg'; @@ -7,9 +8,11 @@ const rightArrowUrl = require('../../../images/right-arrow.svg'); class ConsoleInput extends React.Component { componentDidMount() { this._cm = CodeMirror(this.codemirrorContainer, { // eslint-disable-line - theme: 'p5-console', + // theme: 'p5-console', + theme: `p5-${this.props.theme}`, scrollbarStyle: null, - keyMap: 'sublime' + keymap: 'sublime', + mode: 'javascript' }); this._cm.setOption('extraKeys', { @@ -17,7 +20,6 @@ class ConsoleInput extends React.Component { Down: cm => cm.redo() }); - this._cm.focus(); this._cm.setCursor({ line: 1, ch: 5 }); this._cm.on('keydown', (cm, e) => { @@ -53,6 +55,10 @@ class ConsoleInput extends React.Component { }); } + componentDidUpdate(prevProps) { + this._cm.setOption('theme', `p5-${this.props.theme}`); + } + componentWillUnmount() { this._cm = null; } @@ -71,5 +77,9 @@ class ConsoleInput extends React.Component { } } +ConsoleInput.propTypes = { + theme: PropTypes.string.isRequired +}; + export default ConsoleInput; From 13700dd7e1b10a7388638ef2150169fe6999939a Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Wed, 5 Sep 2018 00:36:58 +0800 Subject: [PATCH 08/45] update --- .../modules/IDE/components/ConsoleInput.jsx | 10 ++++- client/styles/components/_console.scss | 37 +++++++++++++++++++ .../_p5-console-codemirror-theme.scss | 11 ------ client/styles/main.scss | 1 - 4 files changed, 46 insertions(+), 13 deletions(-) delete mode 100644 client/styles/components/_p5-console-codemirror-theme.scss diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index eea7a92740..283b9be889 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -2,13 +2,14 @@ import PropTypes from 'prop-types'; import React from 'react'; import CodeMirror from 'codemirror'; import InlineSVG from 'react-inlinesvg'; +import 'codemirror/addon/hint/show-hint'; +import 'codemirror/addon/hint/javascript-hint'; const rightArrowUrl = require('../../../images/right-arrow.svg'); class ConsoleInput extends React.Component { componentDidMount() { this._cm = CodeMirror(this.codemirrorContainer, { // eslint-disable-line - // theme: 'p5-console', theme: `p5-${this.props.theme}`, scrollbarStyle: null, keymap: 'sublime', @@ -39,6 +40,13 @@ class ConsoleInput extends React.Component { return true; }); + this._cm.on('keyup', (cm, event) => { + if (!cm.state.completionActive && + event.keyCode !== 9) { + CodeMirror.commands.autocomplete(cm, null, { completeSingle: false }); + } + }); + this._cm.on('beforeChange', (cm, changeObj) => { const typedNewLine = changeObj.origin === '+input' && changeObj.text.join('') === ''; if (typedNewLine) { diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index 64a6099ecd..ad7d7e74fe 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -154,3 +154,40 @@ height: #{22 / $base-font-size}rem; } } + +.CodeMirror-hints { + position: absolute; + z-index: 10; + overflow: hidden; + list-style: none; + + margin: 0; + padding: 2px; + + -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2); + -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2); + box-shadow: 2px 3px 5px rgba(0,0,0,.2); + border-radius: 3px; + border: 1px solid silver; + + background: white; + font-size: 90%; + font-family: monospace; + + max-height: 20em; + overflow-y: auto; +} + +.CodeMirror-hint { + margin: 0; + padding: 0 4px; + border-radius: 2px; + white-space: pre; + color: black; + cursor: pointer; +} + +li.CodeMirror-hint-active { + background: #08f; + color: white; +} \ No newline at end of file diff --git a/client/styles/components/_p5-console-codemirror-theme.scss b/client/styles/components/_p5-console-codemirror-theme.scss deleted file mode 100644 index 09a15ae6df..0000000000 --- a/client/styles/components/_p5-console-codemirror-theme.scss +++ /dev/null @@ -1,11 +0,0 @@ -.cm-s-p5-console .cm-number{ - @include themify() { - color: getThemifyVariable('console-color'); - } -} - -.cm-s-p5-console .cm-tag{ - @include themify() { - color: getThemifyVariable('console-color'); - } -} \ No newline at end of file diff --git a/client/styles/main.scss b/client/styles/main.scss index 679a7e693e..d16eaa6d7f 100644 --- a/client/styles/main.scss +++ b/client/styles/main.scss @@ -14,7 +14,6 @@ @import 'components/p5-light-codemirror-theme'; @import 'components/p5-dark-codemirror-theme'; @import 'components/p5-contrast-codemirror-theme'; -@import 'components/p5-console-codemirror-theme'; @import 'components/editor'; @import 'components/nav'; @import 'components/toolbar'; From 17354a054e99682834fac0a133593a460f83f7dc Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Thu, 6 Sep 2018 00:05:14 +0800 Subject: [PATCH 09/45] remove autocomplete code --- .../modules/IDE/components/ConsoleInput.jsx | 9 ----- client/styles/components/_console.scss | 37 ------------------- 2 files changed, 46 deletions(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 283b9be889..510a164f43 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -2,8 +2,6 @@ import PropTypes from 'prop-types'; import React from 'react'; import CodeMirror from 'codemirror'; import InlineSVG from 'react-inlinesvg'; -import 'codemirror/addon/hint/show-hint'; -import 'codemirror/addon/hint/javascript-hint'; const rightArrowUrl = require('../../../images/right-arrow.svg'); @@ -40,13 +38,6 @@ class ConsoleInput extends React.Component { return true; }); - this._cm.on('keyup', (cm, event) => { - if (!cm.state.completionActive && - event.keyCode !== 9) { - CodeMirror.commands.autocomplete(cm, null, { completeSingle: false }); - } - }); - this._cm.on('beforeChange', (cm, changeObj) => { const typedNewLine = changeObj.origin === '+input' && changeObj.text.join('') === ''; if (typedNewLine) { diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index ad7d7e74fe..64a6099ecd 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -154,40 +154,3 @@ height: #{22 / $base-font-size}rem; } } - -.CodeMirror-hints { - position: absolute; - z-index: 10; - overflow: hidden; - list-style: none; - - margin: 0; - padding: 2px; - - -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2); - -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2); - box-shadow: 2px 3px 5px rgba(0,0,0,.2); - border-radius: 3px; - border: 1px solid silver; - - background: white; - font-size: 90%; - font-family: monospace; - - max-height: 20em; - overflow-y: auto; -} - -.CodeMirror-hint { - margin: 0; - padding: 0 4px; - border-radius: 2px; - white-space: pre; - color: black; - cursor: pointer; -} - -li.CodeMirror-hint-active { - background: #08f; - color: white; -} \ No newline at end of file From 99c1f0bb87055a09292e663f497319e67f5022a6 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Mon, 10 Sep 2018 21:38:02 +0800 Subject: [PATCH 10/45] update cursor color --- client/styles/components/_p5-contrast-codemirror-theme.scss | 4 ++++ client/styles/components/_p5-dark-codemirror-theme.scss | 4 ++++ client/styles/components/_p5-light-codemirror-theme.scss | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/client/styles/components/_p5-contrast-codemirror-theme.scss b/client/styles/components/_p5-contrast-codemirror-theme.scss index 6ddef26af5..aecc645ea0 100644 --- a/client/styles/components/_p5-contrast-codemirror-theme.scss +++ b/client/styles/components/_p5-contrast-codemirror-theme.scss @@ -130,3 +130,7 @@ $p5-contrast-activeline: #999999; background-color: white; color: #333; } + +.cm-s-p5-contrast .CodeMirror-cursor { + border-left: 1px solid $p5-contrast-white; +} \ No newline at end of file diff --git a/client/styles/components/_p5-dark-codemirror-theme.scss b/client/styles/components/_p5-dark-codemirror-theme.scss index 275d57ff99..baac5c551b 100644 --- a/client/styles/components/_p5-dark-codemirror-theme.scss +++ b/client/styles/components/_p5-dark-codemirror-theme.scss @@ -133,3 +133,7 @@ $p5-dark-activeline: rgb(207, 207, 207); background-color: white; color: #333; } + +.cm-s-p5-dark .CodeMirror-cursor { + border-left: 1px solid $p5-dark-white; +} \ No newline at end of file diff --git a/client/styles/components/_p5-light-codemirror-theme.scss b/client/styles/components/_p5-light-codemirror-theme.scss index dbb72dbd72..3a803dd7ec 100644 --- a/client/styles/components/_p5-light-codemirror-theme.scss +++ b/client/styles/components/_p5-light-codemirror-theme.scss @@ -131,3 +131,7 @@ $p5-light-activeline: rgb(207, 207, 207); background-color: #333; color: white; } + +.cm-s-p5-light .CodeMirror-cursor { + border-left: 1px solid $p5-light-black; +} \ No newline at end of file From 869737ee94c85e6a614ea5f62f43d4269554e774 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Thu, 27 Sep 2018 00:12:47 +0800 Subject: [PATCH 11/45] update styles --- client/modules/IDE/components/Console.jsx | 2 +- .../modules/IDE/components/ConsoleInput.jsx | 21 ++++++++++++------- client/styles/components/_console-input.scss | 3 ++- client/styles/components/_console.scss | 3 ++- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index 5cf455b69c..60eb9fbce3 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -103,7 +103,6 @@ class Console extends React.Component {
-
{ this.consoleMessages = element; }} className="preview-console__messages"> {this.props.consoleEvents.map((consoleEvent) => { const { arguments: args, method, times } = consoleEvent; @@ -141,6 +140,7 @@ class Console extends React.Component { ); })}
+
); diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 510a164f43..9c0f326310 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -11,7 +11,9 @@ class ConsoleInput extends React.Component { theme: `p5-${this.props.theme}`, scrollbarStyle: null, keymap: 'sublime', - mode: 'javascript' + mode: 'javascript', + styleActiveLine: true, + inputStyle: 'contenteditable' }); this._cm.setOption('extraKeys', { @@ -66,18 +68,23 @@ class ConsoleInput extends React.Component { render() { return ( -
- -
{ this.codemirrorContainer = element; }} className="console__editor" /> +
+ { this.props.isExpanded && +
+ +
{ this.codemirrorContainer = element; }} className="console__editor" /> +
+ }
); } } ConsoleInput.propTypes = { - theme: PropTypes.string.isRequired + theme: PropTypes.string.isRequired, + isExpanded: PropTypes.bool.isRequired }; diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss index a1ee56b861..3b9657a2cc 100644 --- a/client/styles/components/_console-input.scss +++ b/client/styles/components/_console-input.scss @@ -1,6 +1,7 @@ .console__input { padding-left: #{20 / $base-font-size}rem; - position: relative; + position: fixed; + bottom: 0; height: #{22 / $base-font-size}rem; } diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index 64a6099ecd..5176bddaba 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -42,7 +42,8 @@ .preview-console__messages { display: flex; flex-direction: column; - overflow-y: auto; + overflow-y: scroll; + margin-bottom: #{25 / $base-font-size}rem; } .preview-console__collapse { From deae15ebe0f80c860b8ea4a37d070b6566241746 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Thu, 27 Sep 2018 00:25:31 +0800 Subject: [PATCH 12/45] update --- client/styles/components/_console-input.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss index 3b9657a2cc..8ef0afa419 100644 --- a/client/styles/components/_console-input.scss +++ b/client/styles/components/_console-input.scss @@ -3,6 +3,7 @@ position: fixed; bottom: 0; height: #{22 / $base-font-size}rem; + width: 100%; } .console__input .console-active__arrow { From 993ad8f1eaa3c819327a00a2276cf194306c2d53 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Thu, 27 Sep 2018 00:27:37 +0800 Subject: [PATCH 13/45] update --- client/modules/IDE/components/ConsoleInput.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 9c0f326310..f372f4ea4e 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -12,7 +12,7 @@ class ConsoleInput extends React.Component { scrollbarStyle: null, keymap: 'sublime', mode: 'javascript', - styleActiveLine: true, + // styleActiveLine: true, inputStyle: 'contenteditable' }); From 746b90cb6415a120794c83bf6a239b66540a4e3a Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Thu, 27 Sep 2018 00:54:52 +0800 Subject: [PATCH 14/45] update --- client/modules/IDE/components/Console.jsx | 4 +++- client/modules/IDE/components/ConsoleInput.jsx | 18 ++++++------------ client/modules/IDE/components/Editor.jsx | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index 60eb9fbce3..c2aa36cac2 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -140,7 +140,9 @@ class Console extends React.Component { ); })}
- + { this.props.isExpanded && + + }
); diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index f372f4ea4e..c9a6b23ac9 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -12,7 +12,6 @@ class ConsoleInput extends React.Component { scrollbarStyle: null, keymap: 'sublime', mode: 'javascript', - // styleActiveLine: true, inputStyle: 'contenteditable' }); @@ -68,23 +67,18 @@ class ConsoleInput extends React.Component { render() { return ( -
- { this.props.isExpanded && -
- -
{ this.codemirrorContainer = element; }} className="console__editor" /> -
- } +
+ +
{ this.codemirrorContainer = element; }} className="console__editor" />
); } } ConsoleInput.propTypes = { - theme: PropTypes.string.isRequired, - isExpanded: PropTypes.bool.isRequired + theme: PropTypes.string.isRequired }; diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index 74bd6ceb5b..48cc08ace7 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -161,7 +161,7 @@ class Editor extends React.Component { this.props.file.content !== this._cm.getValue()) { const oldDoc = this._cm.swapDoc(this._docs[this.props.file.id]); this._docs[prevProps.file.id] = oldDoc; - this._cm.focus(); + if (!prevProps.unsavedChanges) { setTimeout(() => this.props.setUnsavedChanges(false), 400); } From f82039ed70ac2b5dbe8f9bc9bc6c330c990fad45 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Fri, 28 Sep 2018 00:14:39 +0800 Subject: [PATCH 15/45] update --- client/modules/IDE/components/Console.jsx | 3 ++- client/modules/IDE/pages/IDEView.jsx | 1 + client/styles/abstracts/_variables.scss | 3 +++ client/styles/components/_console-input.scss | 8 ++++++-- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index c2aa36cac2..fcbe7a3212 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -140,7 +140,7 @@ class Console extends React.Component { ); })}
- { this.props.isExpanded && + { this.props.isExpanded && this.props.isPlaying && }
@@ -155,6 +155,7 @@ Console.propTypes = { args: PropTypes.arrayOf(PropTypes.string) })), isExpanded: PropTypes.bool.isRequired, + isPlaying: PropTypes.bool.isRequired, collapseConsole: PropTypes.func.isRequired, expandConsole: PropTypes.func.isRequired, clearConsole: PropTypes.func.isRequired, diff --git a/client/modules/IDE/pages/IDEView.jsx b/client/modules/IDE/pages/IDEView.jsx index c2cd1a105c..2ea3662392 100644 --- a/client/modules/IDE/pages/IDEView.jsx +++ b/client/modules/IDE/pages/IDEView.jsx @@ -358,6 +358,7 @@ class IDEView extends React.Component { fontSize={this.props.preferences.fontSize} consoleEvents={this.props.console} isExpanded={this.props.ide.consoleIsExpanded} + isPlaying={this.props.ide.isPlaying} expandConsole={this.props.expandConsole} collapseConsole={this.props.collapseConsole} clearConsole={this.props.clearConsole} diff --git a/client/styles/abstracts/_variables.scss b/client/styles/abstracts/_variables.scss index d2a0dbbf25..7dc44a4169 100644 --- a/client/styles/abstracts/_variables.scss +++ b/client/styles/abstracts/_variables.scss @@ -41,6 +41,7 @@ $themes: ( icon-toast-hover-color: $white, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #eee, + console-input-background-color: rgb(232, 232, 232), console-color: $black, console-logged-times-color: $white, console-arrow-color: rgb(128,128,128), @@ -90,6 +91,7 @@ $themes: ( icon-toast-hover-color: $white, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #4f4f4f, + console-input-background-color: rgb(60, 60, 60), console-color: $white, console-logged-times-color: $black, console-arrow-color: $white, @@ -138,6 +140,7 @@ $themes: ( icon-toast-hover-color: $yellow, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #4f4f4f, + console-input-background-color: rgb(50, 50, 50), console-color: $white, console-logged-times-color: $black, console-arrow-color: $white, diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss index 8ef0afa419..85c7d96dd0 100644 --- a/client/styles/components/_console-input.scss +++ b/client/styles/components/_console-input.scss @@ -1,9 +1,12 @@ .console__input { padding-left: #{20 / $base-font-size}rem; - position: fixed; + position: absolute; bottom: 0; height: #{22 / $base-font-size}rem; width: 100%; + @include themify() { + background-color: getThemifyVariable('console-input-background-color'); + } } .console__input .console-active__arrow { @@ -24,13 +27,14 @@ .console__editor { margin-left: #{8 / $base-font-size}rem; height: #{20 / $base-font-size}rem; + line-height: #{20 / $base-font-size}rem; } .console__editor .CodeMirror { border: none; font-family: Consolas,Lucida Console,Courier New,monospace; @include themify() { - background-color: getThemifyVariable('console-background-color'); + background-color: getThemifyVariable('console-input-background-color'); } .CodeMirror-line { From d20c4f868b6e76badcb23311dbb654c64ca79e39 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Fri, 28 Sep 2018 00:21:30 +0800 Subject: [PATCH 16/45] update --- client/styles/abstracts/_variables.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/styles/abstracts/_variables.scss b/client/styles/abstracts/_variables.scss index 7dc44a4169..a06dc0f6b6 100644 --- a/client/styles/abstracts/_variables.scss +++ b/client/styles/abstracts/_variables.scss @@ -140,7 +140,7 @@ $themes: ( icon-toast-hover-color: $yellow, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #4f4f4f, - console-input-background-color: rgb(50, 50, 50), + console-input-background-color: rgb(60, 60, 60), console-color: $white, console-logged-times-color: $black, console-arrow-color: $white, From 5346da804f628d9fe49d74b6e948435a7875dc76 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Thu, 4 Oct 2018 17:06:57 +0800 Subject: [PATCH 17/45] update --- client/styles/abstracts/_variables.scss | 2 +- client/styles/components/_console-input.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/styles/abstracts/_variables.scss b/client/styles/abstracts/_variables.scss index a06dc0f6b6..dcf58234fc 100644 --- a/client/styles/abstracts/_variables.scss +++ b/client/styles/abstracts/_variables.scss @@ -41,7 +41,7 @@ $themes: ( icon-toast-hover-color: $white, shadow-color: rgba(0, 0, 0, 0.16), console-background-color: #eee, - console-input-background-color: rgb(232, 232, 232), + console-input-background-color: #f4f4f4, console-color: $black, console-logged-times-color: $white, console-arrow-color: rgb(128,128,128), diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss index 85c7d96dd0..a10f099fb3 100644 --- a/client/styles/components/_console-input.scss +++ b/client/styles/components/_console-input.scss @@ -12,7 +12,7 @@ .console__input .console-active__arrow { left: #{10 / $base-font-size}rem; position: absolute; - top: #{2 / $base-font-size}rem; + top: #{4 / $base-font-size}rem; & svg { width: #{6 / $base-font-size}rem; height: #{10 / $base-font-size}rem; From 163c6094ee3c50cf8bab462324174849a2a21a80 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Thu, 4 Oct 2018 20:23:02 +0800 Subject: [PATCH 18/45] adapt the console ouput and font --- client/modules/IDE/components/Console.jsx | 12 +------- .../modules/IDE/components/ConsoleInput.jsx | 2 +- .../modules/IDE/components/PreviewFrame.jsx | 8 +++-- client/styles/components/_console.scss | 30 +------------------ 4 files changed, 8 insertions(+), 44 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index fcbe7a3212..22b6bae699 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -106,7 +106,6 @@ class Console extends React.Component {
{ this.consoleMessages = element; }} className="preview-console__messages"> {this.props.consoleEvents.map((consoleEvent) => { const { arguments: args, method, times } = consoleEvent; - const { expression, source } = consoleEvent; const { theme } = this.props; Object.assign(consoleEvent, { data: this.formatData(args) }); if (Object.keys(args).length === 0) { @@ -118,18 +117,9 @@ class Console extends React.Component { } return (
- { expression && -
- -
{expression}
-
- }
- { source === 'console' && - - } { times > 1 && -
{times}
+
{times}
} { diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index 5176bddaba..0bdc6d90b2 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -116,31 +116,7 @@ display: flex; flex-direction: column-reverse; - .preview-console__output .preview-console__expression div { - margin-left: #{35 / $base-font-size}rem; - line-height: #{22 / $base-font-size}rem; - font-size: #{12 / $base-font-size}rem; - font-family: Consolas, Lucida Console, Courier New, monospace; - @include themify() { - color: getThemifyVariable('console-color'); - } - } - - .preview-console__message, .preview-console__expression { - .console__arrow { - left: #{10 / $base-font-size}rem; - position: absolute; - top: #{2 / $base-font-size}rem; - & svg { - width: #{6 / $base-font-size}rem; - height: #{10 / $base-font-size}rem; - } - & g { - @include themify() { - fill: getThemifyVariable('console-arrow-color'); - } - } - } + .preview-console__message { flex: 1 0 auto; position: relative; } @@ -150,8 +126,4 @@ color: getThemifyVariable('console-logged-times-color'); } } - - .preview-console__expression { - height: #{22 / $base-font-size}rem; - } } From c3f2a537fcedc840a44b40bf78e976820b90ee28 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Thu, 4 Oct 2018 21:06:55 +0800 Subject: [PATCH 19/45] update result/command icon --- client/modules/IDE/components/Console.jsx | 8 ++++++-- client/modules/IDE/components/Editor.jsx | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index 22b6bae699..05a89b2a9a 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -38,13 +38,17 @@ class Console extends React.Component { LOG_WARN_ICON: `url(${warnLightUrl})`, LOG_ERROR_ICON: `url(${errorLightUrl})`, LOG_DEBUG_ICON: `url(${debugLightUrl})`, - LOG_INFO_ICON: `url(${infoLightUrl})` + LOG_INFO_ICON: `url(${infoLightUrl})`, + LOG_COMMAND_ICON: `url(${leftArrowUrl})`, + LOG_RESULT_ICON: `url(${rightArrowUrl})` }; const CONSOLE_FEED_DARK_ICONS = { LOG_WARN_ICON: `url(${warnDarkUrl})`, LOG_ERROR_ICON: `url(${errorDarkUrl})`, LOG_DEBUG_ICON: `url(${debugDarkUrl})`, - LOG_INFO_ICON: `url(${infoDarkUrl})` + LOG_INFO_ICON: `url(${infoDarkUrl})`, + LOG_COMMAND_ICON: `url(${leftArrowUrl})`, + LOG_RESULT_ICON: `url(${rightArrowUrl})` }; const CONSOLE_FEED_SIZES = { TREENODE_LINE_HEIGHT: 1.2, diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index 48cc08ace7..54c106f007 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -161,6 +161,7 @@ class Editor extends React.Component { this.props.file.content !== this._cm.getValue()) { const oldDoc = this._cm.swapDoc(this._docs[this.props.file.id]); this._docs[prevProps.file.id] = oldDoc; + this._cm.focus(); if (!prevProps.unsavedChanges) { setTimeout(() => this.props.setUnsavedChanges(false), 400); From f43a28d1205011d40b331fa7926e5d9a40feb0c7 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Thu, 4 Oct 2018 22:47:39 +0800 Subject: [PATCH 20/45] update icons --- client/modules/IDE/components/Console.jsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index 05a89b2a9a..22b6bae699 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -38,17 +38,13 @@ class Console extends React.Component { LOG_WARN_ICON: `url(${warnLightUrl})`, LOG_ERROR_ICON: `url(${errorLightUrl})`, LOG_DEBUG_ICON: `url(${debugLightUrl})`, - LOG_INFO_ICON: `url(${infoLightUrl})`, - LOG_COMMAND_ICON: `url(${leftArrowUrl})`, - LOG_RESULT_ICON: `url(${rightArrowUrl})` + LOG_INFO_ICON: `url(${infoLightUrl})` }; const CONSOLE_FEED_DARK_ICONS = { LOG_WARN_ICON: `url(${warnDarkUrl})`, LOG_ERROR_ICON: `url(${errorDarkUrl})`, LOG_DEBUG_ICON: `url(${debugDarkUrl})`, - LOG_INFO_ICON: `url(${infoDarkUrl})`, - LOG_COMMAND_ICON: `url(${leftArrowUrl})`, - LOG_RESULT_ICON: `url(${rightArrowUrl})` + LOG_INFO_ICON: `url(${infoDarkUrl})` }; const CONSOLE_FEED_SIZES = { TREENODE_LINE_HEIGHT: 1.2, From 53f9b902403fcf0014728d6cdb2f18f25e11875e Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Thu, 8 Nov 2018 23:58:30 +0800 Subject: [PATCH 21/45] fix functions printing bug --- client/modules/IDE/components/PreviewFrame.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/modules/IDE/components/PreviewFrame.jsx b/client/modules/IDE/components/PreviewFrame.jsx index 130c15390f..bf1d5b7477 100644 --- a/client/modules/IDE/components/PreviewFrame.jsx +++ b/client/modules/IDE/components/PreviewFrame.jsx @@ -7,7 +7,7 @@ import srcDoc from 'srcdoc-polyfill'; import loopProtect from 'loop-protect'; import { JSHINT } from 'jshint'; import decomment from 'decomment'; -import { Hook, Unhook } from 'console-feed'; +import { Hook, Unhook, Encode } from 'console-feed'; import { getBlobUrl } from '../actions/files'; import { resolvePathToFile } from '../../../../server/utils/filePath'; import { @@ -108,7 +108,7 @@ class PreviewFrame extends React.Component { } window.postMessage([{ method: 'result', - arguments: Array.of(consoleInfo), + arguments: Encode(consoleInfo), source: 'sketch' }], '*'); } From f273394c0580dd79512bc2f9d006f8ca719be34e Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Fri, 9 Nov 2018 00:12:35 +0800 Subject: [PATCH 22/45] resume --- client/modules/IDE/components/Console.jsx | 4 +++- client/modules/IDE/components/ConsoleInput.jsx | 3 ++- client/styles/components/_console-input.scss | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index 22b6bae699..b496bccac3 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -33,7 +33,9 @@ class Console extends React.Component { } getConsoleFeedStyle(theme, times) { - const style = {}; + const style = { + BASE_FONT_FAMILY: 'Inconsolata, monospace', + }; const CONSOLE_FEED_LIGHT_ICONS = { LOG_WARN_ICON: `url(${warnLightUrl})`, LOG_ERROR_ICON: `url(${errorLightUrl})`, diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 4a26180d64..639e6efa30 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -2,6 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import CodeMirror from 'codemirror'; import InlineSVG from 'react-inlinesvg'; +import { Encode } from 'console-feed'; const rightArrowUrl = require('../../../images/right-arrow.svg'); @@ -30,7 +31,7 @@ class ConsoleInput extends React.Component { } window.postMessage([{ method: 'command', - arguments: value, + arguments: Encode(value), source: 'console' }], '*'); diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss index a10f099fb3..8ddcb1aa43 100644 --- a/client/styles/components/_console-input.scss +++ b/client/styles/components/_console-input.scss @@ -32,7 +32,7 @@ .console__editor .CodeMirror { border: none; - font-family: Consolas,Lucida Console,Courier New,monospace; + font-family: Inconsolata,monospace; @include themify() { background-color: getThemifyVariable('console-input-background-color'); } From 0d32ba28ade3eaf80fe6b6960e5bf3bf0794c6dd Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Fri, 9 Nov 2018 00:24:25 +0800 Subject: [PATCH 23/45] remove static file --- static/p5-interceptor | 1 - 1 file changed, 1 deletion(-) delete mode 160000 static/p5-interceptor diff --git a/static/p5-interceptor b/static/p5-interceptor deleted file mode 160000 index 62938f2e9c..0000000000 --- a/static/p5-interceptor +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 62938f2e9cbe1c83a9c1b702a9deccb11a452170 From 5e13be4fc7b87eb51dd8e31e15a04844c9aabbb4 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Fri, 9 Nov 2018 00:37:22 +0800 Subject: [PATCH 24/45] fix console function bug --- client/modules/IDE/components/PreviewFrame.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/modules/IDE/components/PreviewFrame.jsx b/client/modules/IDE/components/PreviewFrame.jsx index 532814b10b..0ced1f0998 100644 --- a/client/modules/IDE/components/PreviewFrame.jsx +++ b/client/modules/IDE/components/PreviewFrame.jsx @@ -109,7 +109,7 @@ class PreviewFrame extends React.Component { } window.postMessage([{ method: 'result', - arguments: Encode(consoleInfo), + arguments: consoleInfo ? Encode(consoleInfo) : Array.of(consoleInfo), source: 'sketch' }], '*'); } From 826350b19a56a3ab3bd7c6678ee174dffaed9833 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Mon, 3 Dec 2018 19:24:02 +0800 Subject: [PATCH 25/45] change console code to use Encode/Decode --- client/modules/IDE/components/ConsoleInput.jsx | 3 +-- client/modules/IDE/components/PreviewFrame.jsx | 13 ++++--------- client/utils/evaluateConsole.js | 5 ++--- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 639e6efa30..be4478d9e5 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -30,8 +30,7 @@ class ConsoleInput extends React.Component { return false; } window.postMessage([{ - method: 'command', - arguments: Encode(value), + log: Encode(Object.assign({}, { method: 'command', data: Encode(value) })), source: 'console' }], '*'); diff --git a/client/modules/IDE/components/PreviewFrame.jsx b/client/modules/IDE/components/PreviewFrame.jsx index 66574f8211..1bb59e42a5 100644 --- a/client/modules/IDE/components/PreviewFrame.jsx +++ b/client/modules/IDE/components/PreviewFrame.jsx @@ -7,9 +7,8 @@ import srcDoc from 'srcdoc-polyfill'; import loopProtect from 'loop-protect'; import { JSHINT } from 'jshint'; import decomment from 'decomment'; -import { Hook, Unhook, Encode } from 'console-feed'; +import { Hook, Unhook, Encode, Decode } from 'console-feed'; import classNames from 'classnames'; -import { Decode } from 'console-feed'; import { getBlobUrl } from '../actions/files'; import { resolvePathToFile } from '../../../../server/utils/filePath'; import { @@ -84,7 +83,6 @@ class PreviewFrame extends React.Component { handleConsoleEvent(messageEvent) { if (Array.isArray(messageEvent.data)) { const decodedMessages = messageEvent.data.map(message => Object.assign(Decode(message.log), { source: message.source })); - decodedMessages.every((message, index, arr) => { const { data: args, source } = message; if (source === 'console') { @@ -92,10 +90,8 @@ class PreviewFrame extends React.Component { const consoleBuffer = []; const LOGWAIT = 100; Hook(window.console, (log) => { - const { method, data: arg } = log[0]; consoleBuffer.push({ - method, - arguments: arg, + log, source: 'sketch' }); }); @@ -107,12 +103,11 @@ class PreviewFrame extends React.Component { }, LOGWAIT); consoleInfo = handleConsoleExpressions(args); Unhook(window.console); - if (consoleInfo === '') { + if (!consoleInfo) { return false; } window.postMessage([{ - method: 'result', - arguments: consoleInfo ? Encode(consoleInfo) : Array.of(consoleInfo), + log: Encode(Object.assign({}, { method: 'result', data: Encode(consoleInfo) })), source: 'sketch' }], '*'); } diff --git a/client/utils/evaluateConsole.js b/client/utils/evaluateConsole.js index 7dcefb4c26..717e50666d 100644 --- a/client/utils/evaluateConsole.js +++ b/client/utils/evaluateConsole.js @@ -4,10 +4,9 @@ export default function handleConsoleExpressions(expression) { try { return evaluateExpression()(expression); } catch (e) { - const data = e.toString(); + const data = [e.toString()]; window.postMessage([{ - method: 'error', - arguments: data, + log: Array.of(Object.assign({}, { method: 'error', data })), source: 'sketch' }], '*'); } From bfe905de7403cd9b7a11b171d7288d06edf81aa6 Mon Sep 17 00:00:00 2001 From: shinytang6 <1074461480@qq.com> Date: Mon, 3 Dec 2018 19:38:22 +0800 Subject: [PATCH 26/45] remove object.assign && fix lint warning --- client/modules/IDE/components/Console.jsx | 2 -- client/modules/IDE/components/ConsoleInput.jsx | 2 +- client/modules/IDE/components/PreviewFrame.jsx | 7 +++++-- client/utils/evaluateConsole.js | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index c39902d232..e3835721b5 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -17,8 +17,6 @@ import infoLightUrl from '../../../images/console-info-light.svg'; import infoDarkUrl from '../../../images/console-info-dark.svg'; import upArrowUrl from '../../../images/up-arrow.svg'; import downArrowUrl from '../../../images/down-arrow.svg'; -import leftArrowUrl from '../../../images/left-arrow.svg'; -import rightArrowUrl from '../../../images/right-arrow.svg'; import ConsoleInput from './ConsoleInput'; class Console extends React.Component { diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index be4478d9e5..7c585904ba 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -30,7 +30,7 @@ class ConsoleInput extends React.Component { return false; } window.postMessage([{ - log: Encode(Object.assign({}, { method: 'command', data: Encode(value) })), + log: Encode({ method: 'command', data: Encode(value) }), source: 'console' }], '*'); diff --git a/client/modules/IDE/components/PreviewFrame.jsx b/client/modules/IDE/components/PreviewFrame.jsx index 1bb59e42a5..03d915084d 100644 --- a/client/modules/IDE/components/PreviewFrame.jsx +++ b/client/modules/IDE/components/PreviewFrame.jsx @@ -82,7 +82,10 @@ class PreviewFrame extends React.Component { handleConsoleEvent(messageEvent) { if (Array.isArray(messageEvent.data)) { - const decodedMessages = messageEvent.data.map(message => Object.assign(Decode(message.log), { source: message.source })); + const decodedMessages = messageEvent.data.map(message => Object.assign( + Decode(message.log), + { source: message.source } + )); decodedMessages.every((message, index, arr) => { const { data: args, source } = message; if (source === 'console') { @@ -107,7 +110,7 @@ class PreviewFrame extends React.Component { return false; } window.postMessage([{ - log: Encode(Object.assign({}, { method: 'result', data: Encode(consoleInfo) })), + log: Encode({ method: 'result', data: Encode(consoleInfo) }), source: 'sketch' }], '*'); } diff --git a/client/utils/evaluateConsole.js b/client/utils/evaluateConsole.js index 717e50666d..b9276bb99f 100644 --- a/client/utils/evaluateConsole.js +++ b/client/utils/evaluateConsole.js @@ -6,7 +6,7 @@ export default function handleConsoleExpressions(expression) { } catch (e) { const data = [e.toString()]; window.postMessage([{ - log: Array.of(Object.assign({}, { method: 'error', data })), + log: Array.of({ method: 'error', data }), source: 'sketch' }], '*'); } From d5048648ad1f4144f80e7e29658e301c2a0256a4 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Thu, 30 Jul 2020 13:36:23 -0400 Subject: [PATCH 27/45] Check origin for postMessage --- client/modules/IDE/components/ConsoleInput.jsx | 3 +++ client/modules/IDE/components/PreviewFrame.jsx | 1 + client/utils/previewEntry.js | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 4bd591593a..7e46ea26eb 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -28,6 +28,9 @@ class ConsoleInput extends React.Component { if (value.trim(' ') === '') { return false; } + // need to get access to iframe here? + // could pass "evaluate console function" + // could make a component that handles all of this messaging window.postMessage([{ log: Encode({ method: 'command', data: Encode(value) }), source: 'console' diff --git a/client/modules/IDE/components/PreviewFrame.jsx b/client/modules/IDE/components/PreviewFrame.jsx index 2c6bb91a1b..3c3395b5fb 100644 --- a/client/modules/IDE/components/PreviewFrame.jsx +++ b/client/modules/IDE/components/PreviewFrame.jsx @@ -70,6 +70,7 @@ class PreviewFrame extends React.Component { } handleConsoleEvent(messageEvent) { + if (messageEvent.origin !== window.origin) return; if (Array.isArray(messageEvent.data)) { const decodedMessages = messageEvent.data.map(message => Object.assign( Decode(message.log), diff --git a/client/utils/previewEntry.js b/client/utils/previewEntry.js index 59858938b5..0556463b7e 100644 --- a/client/utils/previewEntry.js +++ b/client/utils/previewEntry.js @@ -13,7 +13,7 @@ Hook(window.console, (log) => { }); setInterval(() => { if (consoleBuffer.length > 0) { - window.parent.postMessage(consoleBuffer, '*'); + window.parent.postMessage(consoleBuffer, window.origin); consoleBuffer.length = 0; } }, LOGWAIT); From 921f13680abae9324f3caaad29ab2001e76af828 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Fri, 21 Aug 2020 17:31:40 -0400 Subject: [PATCH 28/45] Move window message handling to component --- .../modules/IDE/components/MessageHandler.jsx | 89 +++++++++++++++++++ .../modules/IDE/components/PreviewFrame.jsx | 86 ++---------------- client/modules/IDE/pages/IDEView.jsx | 9 +- 3 files changed, 103 insertions(+), 81 deletions(-) create mode 100644 client/modules/IDE/components/MessageHandler.jsx diff --git a/client/modules/IDE/components/MessageHandler.jsx b/client/modules/IDE/components/MessageHandler.jsx new file mode 100644 index 0000000000..45dd5dea5b --- /dev/null +++ b/client/modules/IDE/components/MessageHandler.jsx @@ -0,0 +1,89 @@ +import React, { useEffect, useCallback } from 'react'; +import { useDispatch } from 'react-redux'; +import { Decode, Encode, Hook, Unhook } from 'console-feed'; +import { isEqual } from 'lodash'; +import { dispatchConsoleEvent } from '../actions/console'; +import { stopSketch, expandConsole } from '../actions/console'; +import handleConsoleExpressions from '../../../utils/evaluateConsole'; + +function useMessageEvent(callback) { + useEffect(() => { + window.addEventListener('message', callback); + return () => window.removeEventListener('message', callback); + }, [callback]); +} + +function MessageHandler() { + const dispatch = useDispatch(); + + const handleMessageEvent = useCallback((messageEvent) => { + if (messageEvent.origin !== window.origin) return; + if (Array.isArray(messageEvent.data)) { + const decodedMessages = messageEvent.data.map(message => Object.assign( + Decode(message.log), + { source: message.source } + )); + decodedMessages.every((message, index, arr) => { + const { data: args, source } = message; + if (source === 'console') { + let consoleInfo = ''; + const consoleBuffer = []; + const LOGWAIT = 100; + Hook(window.console, (log) => { + consoleBuffer.push({ + log, + source: 'sketch' + }); + }); + setInterval(() => { + if (consoleBuffer.length > 0) { + window.postMessage(consoleBuffer, '*'); + consoleBuffer.length = 0; + } + }, LOGWAIT); + consoleInfo = handleConsoleExpressions(args); + Unhook(window.console); + if (!consoleInfo) { + return false; + } + window.postMessage([{ + log: Encode({ method: 'result', data: Encode(consoleInfo) }), + source: 'sketch' + }], '*'); + } + let hasInfiniteLoop = false; + Object.keys(args).forEach((key) => { + if (typeof args[key] === 'string' && args[key].includes('Exiting potential infinite loop')) { + dispatch(stopSketch()); + dispatch(expandConsole()); + hasInfiniteLoop = true; + } + }); + if (hasInfiniteLoop) { + return false; + } + if (index === arr.length - 1) { + Object.assign(message, { times: 1 }); + return false; + } + const cur = Object.assign(message, { times: 1 }); + const nextIndex = index + 1; + while (isEqual(cur.data, arr[nextIndex].data) && cur.method === arr[nextIndex].method) { + cur.times += 1; + arr.splice(nextIndex, 1); + if (nextIndex === arr.length) { + return false; + } + } + return true; + }); + + dispatch(dispatchConsoleEvent(decodedMessages)); + } + }); + + useMessageEvent(handleMessageEvent); + return null; +} + +export default MessageHandler; diff --git a/client/modules/IDE/components/PreviewFrame.jsx b/client/modules/IDE/components/PreviewFrame.jsx index 3c3395b5fb..66243b11aa 100644 --- a/client/modules/IDE/components/PreviewFrame.jsx +++ b/client/modules/IDE/components/PreviewFrame.jsx @@ -2,12 +2,10 @@ import PropTypes from 'prop-types'; import React from 'react'; import ReactDOM from 'react-dom'; // import escapeStringRegexp from 'escape-string-regexp'; -import { isEqual } from 'lodash'; import srcDoc from 'srcdoc-polyfill'; import loopProtect from 'loop-protect'; import { JSHINT } from 'jshint'; import decomment from 'decomment'; -import { Hook, Unhook, Encode, Decode } from 'console-feed'; import classNames from 'classnames'; import { getBlobUrl } from '../actions/files'; import { resolvePathToFile } from '../../../../server/utils/filePath'; @@ -21,7 +19,6 @@ import { } from '../../../../server/utils/fileUtils'; import { hijackConsoleErrorsScript, startTag, getAllScriptOffsets } from '../../../utils/consoleUtils'; -import handleConsoleExpressions from '../../../utils/evaluateConsole'; const shouldRenderSketch = (props, prevProps = undefined) => { @@ -43,12 +40,11 @@ const shouldRenderSketch = (props, prevProps = undefined) => { class PreviewFrame extends React.Component { constructor(props) { super(props); - this.handleConsoleEvent = this.handleConsoleEvent.bind(this); + + this.iframe = React.createRef(); } componentDidMount() { - window.addEventListener('message', this.handleConsoleEvent); - const props = { ...this.props, previewIsRefreshing: this.props.previewIsRefreshing, @@ -64,77 +60,10 @@ class PreviewFrame extends React.Component { } componentWillUnmount() { - window.removeEventListener('message', this.handleConsoleEvent); - const iframeBody = this.iframeElement.contentDocument.body; + const iframeBody = this.iframe.current.contentDocument.body; if (iframeBody) { ReactDOM.unmountComponentAtNode(iframeBody); } } - handleConsoleEvent(messageEvent) { - if (messageEvent.origin !== window.origin) return; - if (Array.isArray(messageEvent.data)) { - const decodedMessages = messageEvent.data.map(message => Object.assign( - Decode(message.log), - { source: message.source } - )); - decodedMessages.every((message, index, arr) => { - const { data: args, source } = message; - if (source === 'console') { - let consoleInfo = ''; - const consoleBuffer = []; - const LOGWAIT = 100; - Hook(window.console, (log) => { - consoleBuffer.push({ - log, - source: 'sketch' - }); - }); - setInterval(() => { - if (consoleBuffer.length > 0) { - window.postMessage(consoleBuffer, '*'); - consoleBuffer.length = 0; - } - }, LOGWAIT); - consoleInfo = handleConsoleExpressions(args); - Unhook(window.console); - if (!consoleInfo) { - return false; - } - window.postMessage([{ - log: Encode({ method: 'result', data: Encode(consoleInfo) }), - source: 'sketch' - }], '*'); - } - let hasInfiniteLoop = false; - Object.keys(args).forEach((key) => { - if (typeof args[key] === 'string' && args[key].includes('Exiting potential infinite loop')) { - this.props.stopSketch(); - this.props.expandConsole(); - hasInfiniteLoop = true; - } - }); - if (hasInfiniteLoop) { - return false; - } - if (index === arr.length - 1) { - Object.assign(message, { times: 1 }); - return false; - } - const cur = Object.assign(message, { times: 1 }); - const nextIndex = index + 1; - while (isEqual(cur.data, arr[nextIndex].data) && cur.method === arr[nextIndex].method) { - cur.times += 1; - arr.splice(nextIndex, 1); - if (nextIndex === arr.length) { - return false; - } - } - return true; - }); - - this.props.dispatchConsoleEvent(decodedMessages); - } - } - addLoopProtect(sketchDoc) { const scriptsInHTML = sketchDoc.getElementsByTagName('script'); const scriptsInHTMLArray = Array.prototype.slice.call(scriptsInHTML); @@ -353,7 +282,7 @@ class PreviewFrame extends React.Component { } renderSketch() { - const doc = this.iframeElement; + const doc = this.iframe.current; const localFiles = this.injectLocalFiles(); if (this.props.isPlaying) { this.props.clearConsole(); @@ -382,7 +311,7 @@ class PreviewFrame extends React.Component { role="main" frameBorder="0" title="sketch preview" - ref={(element) => { this.iframeElement = element; }} + ref={this.iframe} sandbox={sandboxAttributes} /> ); @@ -404,17 +333,14 @@ PreviewFrame.propTypes = { url: PropTypes.string, id: PropTypes.string.isRequired })).isRequired, - dispatchConsoleEvent: PropTypes.func.isRequired, endSketchRefresh: PropTypes.func.isRequired, previewIsRefreshing: PropTypes.bool.isRequired, fullView: PropTypes.bool, setBlobUrl: PropTypes.func.isRequired, - stopSketch: PropTypes.func.isRequired, - expandConsole: PropTypes.func.isRequired, clearConsole: PropTypes.func.isRequired, cmController: PropTypes.shape({ getContent: PropTypes.func - }), + }) }; PreviewFrame.defaultProps = { diff --git a/client/modules/IDE/pages/IDEView.jsx b/client/modules/IDE/pages/IDEView.jsx index 9f010c167d..ede3301621 100644 --- a/client/modules/IDE/pages/IDEView.jsx +++ b/client/modules/IDE/pages/IDEView.jsx @@ -34,6 +34,7 @@ import About from '../components/About'; import AddToCollectionList from '../components/AddToCollectionList'; import Feedback from '../components/Feedback'; import { CollectionSearchbar } from '../components/Searchbar'; +import MessageHandler from '../components/MessageHandler'; function getTitle(props) { @@ -83,6 +84,8 @@ class IDEView extends React.Component { consoleSize: props.ide.consoleIsExpanded ? 150 : 29, sidebarSize: props.ide.sidebarIsExpanded ? 160 : 20, }; + + this.previewFrame = React.createRef(); } componentDidMount() { @@ -259,6 +262,7 @@ class IDEView extends React.Component { {getTitle(this.props)} + {this.props.toast.isVisible && }
From dbaa8a5f0039ce72d5460d2c43bafa9fcf23ac3b Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Tue, 25 Aug 2020 18:35:21 -0400 Subject: [PATCH 29/45] Add dispatcher utility to handle message channel api --- client/modules/IDE/components/Console.jsx | 5 +- .../modules/IDE/components/ConsoleInput.jsx | 26 ++++--- .../modules/IDE/components/MessageHandler.jsx | 69 ++++++------------- .../modules/IDE/components/PreviewFrame.jsx | 2 + client/utils/dispatcher.js | 48 +++++++++++++ client/utils/previewEntry.js | 52 ++++++++++++-- 6 files changed, 141 insertions(+), 61 deletions(-) create mode 100644 client/utils/dispatcher.js diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index fbd70435bc..5a55dfb456 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -144,7 +144,10 @@ const Console = ({ t }) => { })}
{ isExpanded && isPlaying && - + }
diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 7e46ea26eb..a80ad40210 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -4,6 +4,7 @@ import CodeMirror from 'codemirror'; import { Encode } from 'console-feed'; import RightArrowIcon from '../../../images/right-arrow.svg'; +import { dispatch } from '../../../utils/dispatcher'; class ConsoleInput extends React.Component { componentDidMount() { @@ -28,13 +29,21 @@ class ConsoleInput extends React.Component { if (value.trim(' ') === '') { return false; } - // need to get access to iframe here? - // could pass "evaluate console function" - // could make a component that handles all of this messaging - window.postMessage([{ - log: Encode({ method: 'command', data: Encode(value) }), - source: 'console' - }], '*'); + const messages = [{ log: { method: 'command', data: Encode(value) } }]; + const consoleEvent = [{ method: 'command', data: Encode(value) }]; + dispatch({ + source: 'console', + messages + }); + this.props.dispatchConsoleEvent(consoleEvent); + + // // need to get access to iframe here? + // // could pass "evaluate console function" + // // could make a component that handles all of this messaging + // window.postMessage([{ + // log: Encode({ method: 'command', data: Encode(value) }), + // source: 'console' + // }], '*'); cm.setValue(''); } @@ -80,7 +89,8 @@ class ConsoleInput extends React.Component { } ConsoleInput.propTypes = { - theme: PropTypes.string.isRequired + theme: PropTypes.string.isRequired, + dispatchConsoleEvent: PropTypes.func.isRequired }; diff --git a/client/modules/IDE/components/MessageHandler.jsx b/client/modules/IDE/components/MessageHandler.jsx index 45dd5dea5b..5d747d4aec 100644 --- a/client/modules/IDE/components/MessageHandler.jsx +++ b/client/modules/IDE/components/MessageHandler.jsx @@ -1,56 +1,20 @@ -import React, { useEffect, useCallback } from 'react'; +import React, { useEffect } from 'react'; import { useDispatch } from 'react-redux'; -import { Decode, Encode, Hook, Unhook } from 'console-feed'; +import { Decode } from 'console-feed'; import { isEqual } from 'lodash'; import { dispatchConsoleEvent } from '../actions/console'; import { stopSketch, expandConsole } from '../actions/console'; -import handleConsoleExpressions from '../../../utils/evaluateConsole'; +import { listen } from '../../../utils/dispatcher'; -function useMessageEvent(callback) { - useEffect(() => { - window.addEventListener('message', callback); - return () => window.removeEventListener('message', callback); - }, [callback]); -} - -function MessageHandler() { +function useHandleMessageEvent() { const dispatch = useDispatch(); - const handleMessageEvent = useCallback((messageEvent) => { - if (messageEvent.origin !== window.origin) return; - if (Array.isArray(messageEvent.data)) { - const decodedMessages = messageEvent.data.map(message => Object.assign( - Decode(message.log), - { source: message.source } - )); + const handleMessageEvent = (data) => { + const { source, messages } = data; + if (source === 'sketch' && Array.isArray(messages)) { + const decodedMessages = messages.map(message => Decode(message.log)); decodedMessages.every((message, index, arr) => { - const { data: args, source } = message; - if (source === 'console') { - let consoleInfo = ''; - const consoleBuffer = []; - const LOGWAIT = 100; - Hook(window.console, (log) => { - consoleBuffer.push({ - log, - source: 'sketch' - }); - }); - setInterval(() => { - if (consoleBuffer.length > 0) { - window.postMessage(consoleBuffer, '*'); - consoleBuffer.length = 0; - } - }, LOGWAIT); - consoleInfo = handleConsoleExpressions(args); - Unhook(window.console); - if (!consoleInfo) { - return false; - } - window.postMessage([{ - log: Encode({ method: 'result', data: Encode(consoleInfo) }), - source: 'sketch' - }], '*'); - } + const { data: args } = message; let hasInfiniteLoop = false; Object.keys(args).forEach((key) => { if (typeof args[key] === 'string' && args[key].includes('Exiting potential infinite loop')) { @@ -66,6 +30,7 @@ function MessageHandler() { Object.assign(message, { times: 1 }); return false; } + // this should be done in the reducer probs const cur = Object.assign(message, { times: 1 }); const nextIndex = index + 1; while (isEqual(cur.data, arr[nextIndex].data) && cur.method === arr[nextIndex].method) { @@ -77,12 +42,20 @@ function MessageHandler() { } return true; }); - dispatch(dispatchConsoleEvent(decodedMessages)); } - }); + }; + return handleMessageEvent; +} - useMessageEvent(handleMessageEvent); +function MessageHandler() { + const handleMessageEvent = useHandleMessageEvent(); + useEffect(() => { + const unsubscribe = listen(handleMessageEvent); + return function cleanup() { + unsubscribe(); + }; + }); return null; } diff --git a/client/modules/IDE/components/PreviewFrame.jsx b/client/modules/IDE/components/PreviewFrame.jsx index 66243b11aa..1b20f23925 100644 --- a/client/modules/IDE/components/PreviewFrame.jsx +++ b/client/modules/IDE/components/PreviewFrame.jsx @@ -19,6 +19,7 @@ import { } from '../../../../server/utils/fileUtils'; import { hijackConsoleErrorsScript, startTag, getAllScriptOffsets } from '../../../utils/consoleUtils'; +import { registerFrame } from '../../../utils/dispatcher'; const shouldRenderSketch = (props, prevProps = undefined) => { @@ -51,6 +52,7 @@ class PreviewFrame extends React.Component { isAccessibleOutputPlaying: this.props.isAccessibleOutputPlaying }; if (shouldRenderSketch(props)) this.renderSketch(); + registerFrame(this.iframe.current); } componentDidUpdate(prevProps) { diff --git a/client/utils/dispatcher.js b/client/utils/dispatcher.js new file mode 100644 index 0000000000..6745840999 --- /dev/null +++ b/client/utils/dispatcher.js @@ -0,0 +1,48 @@ +// Inspired by +// https://github.com/codesandbox/codesandbox-client/blob/master/packages/codesandbox-api/src/dispatcher/index.ts + +let frame = null; +let listener = null; +const { origin } = window; + +export function registerFrame(newFrame) { + frame = newFrame; +} + +function notifyListener(message) { + if (listener) listener(message); +} + +function notifyFrame(message) { + const rawMessage = JSON.parse(JSON.stringify(message)); + if (frame && frame.postMessage) { + frame.postMessage(rawMessage, origin); + } +} + +export function dispatch(message) { + if (!message) return; + + notifyListener(message); + notifyFrame(message); +} + +/** + * Call callback to remove listener + */ +export function listen(callback) { + listener = callback; + return () => { + listener = null; + }; +} + +function eventListener(e) { + const { data } = e; + + if (data && e.origin === origin) { + notifyListener(data); + } +} + +window.addEventListener('message', eventListener); diff --git a/client/utils/previewEntry.js b/client/utils/previewEntry.js index 0556463b7e..5076a9b219 100644 --- a/client/utils/previewEntry.js +++ b/client/utils/previewEntry.js @@ -1,5 +1,6 @@ import loopProtect from 'loop-protect'; -import { Hook } from 'console-feed'; +import { Hook, Decode, Encode } from 'console-feed'; +import handleConsoleExpressions from './evaluateConsole'; window.loopProtect = loopProtect; @@ -7,13 +8,56 @@ const consoleBuffer = []; const LOGWAIT = 500; Hook(window.console, (log) => { consoleBuffer.push({ - log, - source: 'sketch' + log }); }); setInterval(() => { if (consoleBuffer.length > 0) { - window.parent.postMessage(consoleBuffer, window.origin); + const message = { + messages: consoleBuffer, + source: 'sketch' + }; + // this could import dispatch instead! wowowowow + window.parent.postMessage(message, window.origin); consoleBuffer.length = 0; } }, LOGWAIT); + +function handleMessageEvent(e) { + console.log('in preview entry handle message event'); + if (window.origin !== e.origin) return; + const { data } = e; + const { source, messages } = data; + if (source === 'console' && Array.isArray(messages)) { + const decodedMessages = messages.map(message => Decode(message.log)); + decodedMessages.forEach((message) => { + const { data: args } = message; + // let consoleInfo = ''; + // const consoleBuffer = []; + // const LOGWAIT = 100; + // Hook(window.console, (log) => { + // consoleBuffer.push({ + // log, + // source: 'sketch' + // }); + // }); + // setInterval(() => { + // if (consoleBuffer.length > 0) { + // window.postMessage(consoleBuffer, '*'); + // consoleBuffer.length = 0; + // } + // }, LOGWAIT); + const consoleInfo = handleConsoleExpressions(args); + // Unhook(window.console); + // if (!consoleInfo) { + // return false; + // } + window.postMessage([{ + log: Encode({ method: 'result', data: Encode(consoleInfo) }), + source: 'sketch' + }], window.origin); + }); + } +} + +window.addEventListener('message', handleMessageEvent); From f6aa546ae8a7eaf65bf3d79b7bbd1423903763ce Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Thu, 27 Aug 2020 17:46:52 -0400 Subject: [PATCH 30/45] Eval ConsoleInput command in preview frame --- client/modules/IDE/components/ConsoleInput.jsx | 2 +- client/modules/IDE/components/PreviewFrame.jsx | 2 +- client/utils/previewEntry.js | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index a80ad40210..a88582c2b6 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -29,7 +29,7 @@ class ConsoleInput extends React.Component { if (value.trim(' ') === '') { return false; } - const messages = [{ log: { method: 'command', data: Encode(value) } }]; + const messages = [{ log: Encode({ method: 'command', data: Encode(value) }) }]; const consoleEvent = [{ method: 'command', data: Encode(value) }]; dispatch({ source: 'console', diff --git a/client/modules/IDE/components/PreviewFrame.jsx b/client/modules/IDE/components/PreviewFrame.jsx index 1b20f23925..142cb5ece7 100644 --- a/client/modules/IDE/components/PreviewFrame.jsx +++ b/client/modules/IDE/components/PreviewFrame.jsx @@ -52,7 +52,7 @@ class PreviewFrame extends React.Component { isAccessibleOutputPlaying: this.props.isAccessibleOutputPlaying }; if (shouldRenderSketch(props)) this.renderSketch(); - registerFrame(this.iframe.current); + registerFrame(this.iframe.current.contentWindow); } componentDidUpdate(prevProps) { diff --git a/client/utils/previewEntry.js b/client/utils/previewEntry.js index 5076a9b219..9ce983d65a 100644 --- a/client/utils/previewEntry.js +++ b/client/utils/previewEntry.js @@ -24,7 +24,6 @@ setInterval(() => { }, LOGWAIT); function handleMessageEvent(e) { - console.log('in preview entry handle message event'); if (window.origin !== e.origin) return; const { data } = e; const { source, messages } = data; From 0daeea53d6d61154f98a48dd2d2cfa55fc41a365 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Thu, 27 Aug 2020 18:06:05 -0400 Subject: [PATCH 31/45] Remove commented-out code, fix console scrolling --- .../modules/IDE/components/ConsoleInput.jsx | 9 --------- client/styles/components/_console.scss | 4 +--- client/utils/previewEntry.js | 19 ------------------- 3 files changed, 1 insertion(+), 31 deletions(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index a88582c2b6..f9e9f6529b 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -36,15 +36,6 @@ class ConsoleInput extends React.Component { messages }); this.props.dispatchConsoleEvent(consoleEvent); - - // // need to get access to iframe here? - // // could pass "evaluate console function" - // // could make a component that handles all of this messaging - // window.postMessage([{ - // log: Encode({ method: 'command', data: Encode(value) }), - // source: 'console' - // }], '*'); - cm.setValue(''); } return true; diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index 078dabb9c1..3ff3fa4075 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -133,13 +133,11 @@ .preview-console__body { display: flex; flex-direction: column-reverse; + height: calc(100% - #{30 / $base-font-size}rem); .preview-console__message { flex: 1 0 auto; position: relative; - } - - .preview-console__message { @include themify() { color: getThemifyVariable('console-logged-times-color'); } diff --git a/client/utils/previewEntry.js b/client/utils/previewEntry.js index 9ce983d65a..9af80a34d7 100644 --- a/client/utils/previewEntry.js +++ b/client/utils/previewEntry.js @@ -31,26 +31,7 @@ function handleMessageEvent(e) { const decodedMessages = messages.map(message => Decode(message.log)); decodedMessages.forEach((message) => { const { data: args } = message; - // let consoleInfo = ''; - // const consoleBuffer = []; - // const LOGWAIT = 100; - // Hook(window.console, (log) => { - // consoleBuffer.push({ - // log, - // source: 'sketch' - // }); - // }); - // setInterval(() => { - // if (consoleBuffer.length > 0) { - // window.postMessage(consoleBuffer, '*'); - // consoleBuffer.length = 0; - // } - // }, LOGWAIT); const consoleInfo = handleConsoleExpressions(args); - // Unhook(window.console); - // if (!consoleInfo) { - // return false; - // } window.postMessage([{ log: Encode({ method: 'result', data: Encode(consoleInfo) }), source: 'sketch' From da9f8eca1078c0ac205c126b3bee02f58608dfeb Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Thu, 27 Aug 2020 18:19:48 -0400 Subject: [PATCH 32/45] Render return value from evaluating console input --- client/utils/previewEntry.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/utils/previewEntry.js b/client/utils/previewEntry.js index 9af80a34d7..3aee1cc466 100644 --- a/client/utils/previewEntry.js +++ b/client/utils/previewEntry.js @@ -32,10 +32,11 @@ function handleMessageEvent(e) { decodedMessages.forEach((message) => { const { data: args } = message; const consoleInfo = handleConsoleExpressions(args); - window.postMessage([{ - log: Encode({ method: 'result', data: Encode(consoleInfo) }), + const resultMessages = [{ log: Encode({ method: 'result', data: Encode(consoleInfo) }) }]; + window.parent.postMessage({ + messages: resultMessages, source: 'sketch' - }], window.origin); + }, window.origin); }); } } From 1c47498536dd44e32edf793348297cd490316cbf Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Thu, 27 Aug 2020 18:53:27 -0400 Subject: [PATCH 33/45] Fix encoding/decoding of messages --- client/utils/previewEntry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/utils/previewEntry.js b/client/utils/previewEntry.js index 3aee1cc466..b7c90fc212 100644 --- a/client/utils/previewEntry.js +++ b/client/utils/previewEntry.js @@ -32,7 +32,7 @@ function handleMessageEvent(e) { decodedMessages.forEach((message) => { const { data: args } = message; const consoleInfo = handleConsoleExpressions(args); - const resultMessages = [{ log: Encode({ method: 'result', data: Encode(consoleInfo) }) }]; + const resultMessages = [{ log: Encode({ method: 'result', data: [consoleInfo] }) }]; window.parent.postMessage({ messages: resultMessages, source: 'sketch' From 3d9a4fa5f4e9a527b2b82dbbf1900173f2155883 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Thu, 27 Aug 2020 19:14:20 -0400 Subject: [PATCH 34/45] Handle errors when evaluating expression in iframe --- .../modules/IDE/components/ConsoleInput.jsx | 4 ++-- client/utils/evaluateExpression.js | 19 +++++++++++++------ client/utils/previewEntry.js | 4 ++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index f9e9f6529b..bded1dbcd8 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -29,8 +29,8 @@ class ConsoleInput extends React.Component { if (value.trim(' ') === '') { return false; } - const messages = [{ log: Encode({ method: 'command', data: Encode(value) }) }]; - const consoleEvent = [{ method: 'command', data: Encode(value) }]; + const messages = [{ log: Encode({ method: 'command', data: [value] }) }]; + const consoleEvent = [{ method: 'command', data: [value] }]; dispatch({ source: 'console', messages diff --git a/client/utils/evaluateExpression.js b/client/utils/evaluateExpression.js index f9261c66e8..9f54d3e540 100644 --- a/client/utils/evaluateExpression.js +++ b/client/utils/evaluateExpression.js @@ -6,15 +6,22 @@ function __makeEvaluateExpression(evalInClosure) { function evaluateExpression() { return __makeEvaluateExpression((expr) => { let newExpr = expr; + let result = null; + let error = false; try { - const wrapped = `(${expr})`; - const validate = new Function(wrapped); // eslint-disable-line - newExpr = wrapped; // eslint-disable-line + try { + const wrapped = `(${expr})`; + const validate = new Function(wrapped); // eslint-disable-line + newExpr = wrapped; // eslint-disable-line + } catch (e) { + // We shouldn't wrap the expression + } + result = (0, eval)(newExpr); // eslint-disable-line } catch (e) { - // We shouldn't wrap the expression + result = e; + error = true; } - - return (0, eval)(newExpr); // eslint-disable-line + return { result, error }; }); } diff --git a/client/utils/previewEntry.js b/client/utils/previewEntry.js index b7c90fc212..843077528e 100644 --- a/client/utils/previewEntry.js +++ b/client/utils/previewEntry.js @@ -31,8 +31,8 @@ function handleMessageEvent(e) { const decodedMessages = messages.map(message => Decode(message.log)); decodedMessages.forEach((message) => { const { data: args } = message; - const consoleInfo = handleConsoleExpressions(args); - const resultMessages = [{ log: Encode({ method: 'result', data: [consoleInfo] }) }]; + const { result, error } = handleConsoleExpressions(args); + const resultMessages = [{ log: Encode({ method: error ? 'error' : 'result', data: [result] }) }]; window.parent.postMessage({ messages: resultMessages, source: 'sketch' From 12cb0a5d87ec315bb0eaca3878fc30a8e5e800d4 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Thu, 27 Aug 2020 19:29:42 -0400 Subject: [PATCH 35/45] Update Rendering errors to console from input --- client/utils/evaluateExpression.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/utils/evaluateExpression.js b/client/utils/evaluateExpression.js index 9f54d3e540..5d615b743a 100644 --- a/client/utils/evaluateExpression.js +++ b/client/utils/evaluateExpression.js @@ -18,7 +18,7 @@ function evaluateExpression() { } result = (0, eval)(newExpr); // eslint-disable-line } catch (e) { - result = e; + result = `${e.name}: ${e.message}`; error = true; } return { result, error }; From 5762c158f0136497f99ff010f3c0bec6ef0301ee Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Wed, 23 Sep 2020 18:36:12 -0400 Subject: [PATCH 36/45] Add ConsoleInput adjustment to font size --- client/modules/IDE/components/Console.jsx | 1 + .../modules/IDE/components/ConsoleInput.jsx | 16 +++++++-- client/styles/components/_console-input.scss | 34 +++++++++++-------- client/styles/components/_console.scss | 5 ++- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index 5a55dfb456..32a80bd171 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -147,6 +147,7 @@ const Console = ({ t }) => { }
diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index bded1dbcd8..8085788d9d 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -55,10 +55,14 @@ class ConsoleInput extends React.Component { return null; }); + + this._cm.getWrapperElement().style['font-size'] = `${this.props.fontSize}px`; } componentDidUpdate(prevProps) { this._cm.setOption('theme', `p5-${this.props.theme}`); + this._cm.getWrapperElement().style['font-size'] = `${this.props.fontSize}px`; + this._cm.refresh(); } componentWillUnmount() { @@ -72,7 +76,14 @@ class ConsoleInput extends React.Component {
-
); diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss index 385d4b6a03..7d2dd3bf64 100644 --- a/client/styles/components/_console-input.scss +++ b/client/styles/components/_console-input.scss @@ -9,10 +9,11 @@ .console__input .console-active__arrow { width: auto; - height: 55%; - & g { + height: 38%; + & path { @include themify() { - fill: getThemifyVariable('console-active-arrow-color'); + fill: getThemifyVariable('console-active-arrow-color'); + opacity: 1; } } } diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index a85dadcdec..e3854a6764 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -135,7 +135,6 @@ height: calc(100% - #{30 / $base-font-size}rem); .preview-console__message { - flex: 1 0 auto; position: relative; @include themify() { color: getThemifyVariable('console-logged-times-color'); From ae71067a1796a4de1b7f1b033468ec0772645176 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Fri, 25 Sep 2020 15:01:12 -0400 Subject: [PATCH 38/45] Add command/reesult icons for all themes --- client/images/console-command-contrast.svg | 13 ++++++++++ client/images/console-command-dark.svg | 13 ++++++++++ ...{command.svg => console-command-light.svg} | 0 ...result.svg => console-result-contrast.svg} | 4 ++-- client/images/console-result-dark.svg | 22 +++++++++++++++++ client/images/console-result-light.svg | 22 +++++++++++++++++ client/modules/IDE/components/Console.jsx | 24 ++++++++++++------- 7 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 client/images/console-command-contrast.svg create mode 100644 client/images/console-command-dark.svg rename client/images/{command.svg => console-command-light.svg} (100%) rename client/images/{result.svg => console-result-contrast.svg} (94%) create mode 100644 client/images/console-result-dark.svg create mode 100644 client/images/console-result-light.svg diff --git a/client/images/console-command-contrast.svg b/client/images/console-command-contrast.svg new file mode 100644 index 0000000000..a08ee8b0f7 --- /dev/null +++ b/client/images/console-command-contrast.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/client/images/console-command-dark.svg b/client/images/console-command-dark.svg new file mode 100644 index 0000000000..a08ee8b0f7 --- /dev/null +++ b/client/images/console-command-dark.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/client/images/command.svg b/client/images/console-command-light.svg similarity index 100% rename from client/images/command.svg rename to client/images/console-command-light.svg diff --git a/client/images/result.svg b/client/images/console-result-contrast.svg similarity index 94% rename from client/images/result.svg rename to client/images/console-result-contrast.svg index e323035856..36fa2e36d4 100644 --- a/client/images/result.svg +++ b/client/images/console-result-contrast.svg @@ -1,8 +1,8 @@ - - + + diff --git a/client/images/console-result-dark.svg b/client/images/console-result-dark.svg new file mode 100644 index 0000000000..7c5c5c9b27 --- /dev/null +++ b/client/images/console-result-dark.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/client/images/console-result-light.svg b/client/images/console-result-light.svg new file mode 100644 index 0000000000..a51506e00a --- /dev/null +++ b/client/images/console-result-light.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index 8cb69d936e..f2a117c079 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -25,8 +25,12 @@ import infoDarkUrl from '../../../images/console-info-dark.svg?byUrl'; import infoContrastUrl from '../../../images/console-info-contrast.svg?byUrl'; import ConsoleInput from './ConsoleInput'; -import commandIconUrl from '../../../images/command.svg?byUrl'; -import resultIconUrl from '../../../images/result.svg?byUrl'; +import commandLightUrl from '../../../images/console-command-light.svg?byUrl'; +import resultLightUrl from '../../../images/console-result-light.svg?byUrl'; +import commandDarkUrl from '../../../images/console-command-dark.svg?byUrl'; +import resultDarkUrl from '../../../images/console-result-dark.svg?byUrl'; +import commandContrastUrl from '../../../images/console-command-contrast.svg?byUrl'; +import resultContrastUrl from '../../../images/console-result-contrast.svg?byUrl'; import UpArrowIcon from '../../../images/up-arrow.svg'; import DownArrowIcon from '../../../images/down-arrow.svg'; @@ -43,28 +47,32 @@ const getConsoleFeedStyle = (theme, times, fontSize) => { LOG_WARN_ICON: `url(${warnLightUrl})`, LOG_ERROR_ICON: `url(${errorLightUrl})`, LOG_DEBUG_ICON: `url(${debugLightUrl})`, - LOG_INFO_ICON: `url(${infoLightUrl})` + LOG_INFO_ICON: `url(${infoLightUrl})`, + LOG_COMMAND_ICON: `url(${commandLightUrl})`, + LOG_RESULT_ICON: `url(${resultLightUrl})` }; const CONSOLE_FEED_DARK_ICONS = { LOG_WARN_ICON: `url(${warnDarkUrl})`, LOG_ERROR_ICON: `url(${errorDarkUrl})`, LOG_DEBUG_ICON: `url(${debugDarkUrl})`, - LOG_INFO_ICON: `url(${infoDarkUrl})` + LOG_INFO_ICON: `url(${infoDarkUrl})`, + LOG_COMMAND_ICON: `url(${commandDarkUrl})`, + LOG_RESULT_ICON: `url(${resultDarkUrl})` }; const CONSOLE_FEED_CONTRAST_ICONS = { LOG_WARN_ICON: `url(${warnContrastUrl})`, LOG_ERROR_ICON: `url(${errorContrastUrl})`, LOG_DEBUG_ICON: `url(${debugContrastUrl})`, - LOG_INFO_ICON: `url(${infoContrastUrl})` + LOG_INFO_ICON: `url(${infoContrastUrl})`, + LOG_COMMAND_ICON: `url(${commandContrastUrl})`, + LOG_RESULT_ICON: `url(${resultContrastUrl})` }; const CONSOLE_FEED_SIZES = { TREENODE_LINE_HEIGHT: 1.2, BASE_FONT_SIZE: fontSize, ARROW_FONT_SIZE: fontSize, LOG_ICON_WIDTH: fontSize, - LOG_ICON_HEIGHT: 1.45 * fontSize, - LOG_COMMAND_ICON: `url(${commandIconUrl})`, - LOG_RESULT_ICON: `url(${resultIconUrl})` + LOG_ICON_HEIGHT: 1.45 * fontSize }; if (times > 1) { From b10f4985679bdd327f2a8d22422f20f6b060f592 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Fri, 25 Sep 2020 16:22:44 -0400 Subject: [PATCH 39/45] Change code to force console rerender when changing theme and font size --- client/modules/IDE/components/Console.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index f2a117c079..d03682d32e 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -151,7 +151,7 @@ const Console = ({ t }) => {
); From d831513371b14eb41153800794ef7341a4fce8a1 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Fri, 25 Sep 2020 16:51:15 -0400 Subject: [PATCH 40/45] Move MesssageHandler to a custom hook, create hooks directory --- client/components/useAsModal.jsx | 2 +- client/modules/IDE/components/Console.jsx | 17 +++++++++++------ .../IDE/hooks}/custom-hooks.js | 0 .../useHandleMessageEvent.js} | 17 +---------------- client/modules/IDE/pages/IDEView.jsx | 2 -- client/modules/IDE/pages/MobileIDEView.jsx | 2 +- client/utils/previewEntry.js | 1 - 7 files changed, 14 insertions(+), 27 deletions(-) rename client/{utils => modules/IDE/hooks}/custom-hooks.js (100%) rename client/modules/IDE/{components/MessageHandler.jsx => hooks/useHandleMessageEvent.js} (80%) diff --git a/client/components/useAsModal.jsx b/client/components/useAsModal.jsx index 350d1de2ed..51373bb50e 100644 --- a/client/components/useAsModal.jsx +++ b/client/components/useAsModal.jsx @@ -1,6 +1,6 @@ import React from 'react'; import styled from 'styled-components'; -import { useModalBehavior } from '../utils/custom-hooks'; +import { useModalBehavior } from '../modules/IDE/hooks/custom-hooks'; const BackgroundOverlay = styled.div` position: fixed; diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index d03682d32e..2e7a2e9ead 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -37,7 +37,9 @@ import DownArrowIcon from '../../../images/down-arrow.svg'; import * as IDEActions from '../../IDE/actions/ide'; import * as ConsoleActions from '../../IDE/actions/console'; -import { useDidUpdate } from '../../../utils/custom-hooks'; +import { useDidUpdate } from '../hooks/custom-hooks'; +import useHandleMessageEvent from '../hooks/useHandleMessageEvent'; +import { listen } from '../../../utils/dispatcher'; const getConsoleFeedStyle = (theme, times, fontSize) => { const style = { @@ -100,15 +102,18 @@ const Console = ({ t }) => { collapseConsole, expandConsole, clearConsole, dispatchConsoleEvent } = bindActionCreators({ ...IDEActions, ...ConsoleActions }, useDispatch()); - // useEffect(() => { - // clearConsole(); - // dispatchConsoleEvent(consoleEvents); - // }, [theme, fontSize]); - const cm = useRef({}); useDidUpdate(() => { cm.current.scrollTop = cm.current.scrollHeight; }); + const handleMessageEvent = useHandleMessageEvent(); + useEffect(() => { + const unsubscribe = listen(handleMessageEvent); + return function cleanup() { + unsubscribe(); + }; + }); + const consoleClass = classNames({ 'preview-console': true, 'preview-console--collapsed': !isExpanded diff --git a/client/utils/custom-hooks.js b/client/modules/IDE/hooks/custom-hooks.js similarity index 100% rename from client/utils/custom-hooks.js rename to client/modules/IDE/hooks/custom-hooks.js diff --git a/client/modules/IDE/components/MessageHandler.jsx b/client/modules/IDE/hooks/useHandleMessageEvent.js similarity index 80% rename from client/modules/IDE/components/MessageHandler.jsx rename to client/modules/IDE/hooks/useHandleMessageEvent.js index 5d747d4aec..2bd22168b7 100644 --- a/client/modules/IDE/components/MessageHandler.jsx +++ b/client/modules/IDE/hooks/useHandleMessageEvent.js @@ -1,12 +1,10 @@ -import React, { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { Decode } from 'console-feed'; import { isEqual } from 'lodash'; import { dispatchConsoleEvent } from '../actions/console'; import { stopSketch, expandConsole } from '../actions/console'; -import { listen } from '../../../utils/dispatcher'; -function useHandleMessageEvent() { +export default function useHandleMessageEvent() { const dispatch = useDispatch(); const handleMessageEvent = (data) => { @@ -47,16 +45,3 @@ function useHandleMessageEvent() { }; return handleMessageEvent; } - -function MessageHandler() { - const handleMessageEvent = useHandleMessageEvent(); - useEffect(() => { - const unsubscribe = listen(handleMessageEvent); - return function cleanup() { - unsubscribe(); - }; - }); - return null; -} - -export default MessageHandler; diff --git a/client/modules/IDE/pages/IDEView.jsx b/client/modules/IDE/pages/IDEView.jsx index 0d0ff5255e..4ce446c810 100644 --- a/client/modules/IDE/pages/IDEView.jsx +++ b/client/modules/IDE/pages/IDEView.jsx @@ -34,7 +34,6 @@ import About from '../components/About'; import AddToCollectionList from '../components/AddToCollectionList'; import Feedback from '../components/Feedback'; import { CollectionSearchbar } from '../components/Searchbar'; -import MessageHandler from '../components/MessageHandler'; import { getIsUserOwner } from '../selectors/users'; @@ -258,7 +257,6 @@ class IDEView extends React.Component { {getTitle(this.props)} - {this.props.toast.isVisible && }
From 23d45d226a411d1117ec8e1813ccd84d39031464 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Mon, 28 Sep 2020 18:02:30 -0400 Subject: [PATCH 43/45] Add command history, not 100% finished --- .../modules/IDE/components/ConsoleInput.jsx | 82 +++++++++++++------ 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 8085788d9d..36fb8424b9 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -1,12 +1,23 @@ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useState, useEffect } from 'react'; import CodeMirror from 'codemirror'; import { Encode } from 'console-feed'; import RightArrowIcon from '../../../images/right-arrow.svg'; import { dispatch } from '../../../utils/dispatcher'; +// heavily inspired by +// https://github.com/codesandbox/codesandbox-client/blob/92a1131f4ded6f7d9c16945dc7c18aa97c8ada27/packages/app/src/app/components/Preview/DevTools/Console/Input/index.tsx + class ConsoleInput extends React.Component { + constructor(props) { + super(props); + this.state = { + commandHistory: [], + commandCursor: -1 + }; + } + componentDidMount() { this._cm = CodeMirror(this.codemirrorContainer, { // eslint-disable-line theme: `p5-${this.props.theme}`, @@ -16,15 +27,10 @@ class ConsoleInput extends React.Component { inputStyle: 'contenteditable' }); - this._cm.setOption('extraKeys', { - Up: cm => cm.undo(), - Down: cm => cm.redo() - }); - - this._cm.setCursor({ line: 1, ch: 5 }); - this._cm.on('keydown', (cm, e) => { - if (e.keyCode === 13) { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + e.stopPropagation(); const value = cm.getValue(); if (value.trim(' ') === '') { return false; @@ -37,23 +43,51 @@ class ConsoleInput extends React.Component { }); this.props.dispatchConsoleEvent(consoleEvent); cm.setValue(''); - } - return true; - }); + this.setState(state => ({ + commandCursor: -1, + commandHistory: [value, ...state.commandHistory], + })); + } else if (e.key === 'ArrowUp') { + const lineNumber = this._cm.getDoc().getCursor().line; + if (lineNumber !== 0) { + return false; + } - this._cm.on('beforeChange', (cm, changeObj) => { - const typedNewLine = changeObj.origin === '+input' && changeObj.text.join('') === ''; - if (typedNewLine) { - return changeObj.cancel(); - } + // also need to set cursor position + this.setState((state) => { + const newCursor = Math.min( + state.commandCursor + 1, + state.commandHistory.length - 1 + ); + this._cm + .getDoc() + .setValue(state.commandHistory[newCursor] || ''); + const cursorPos = this._cm.getDoc().getLine(0).length - 1; + console.log(cursorPos); + this._cm.setCursor({ line: 0, ch: cursorPos }); + return { commandCursor: newCursor }; + }); + } else if (e.key === 'ArrowDown') { + const lineNumber = this._cm.getDoc().getCursor().line; + const lineCount = this._cm.getValue().split('\n').length; + if (lineNumber + 1 !== lineCount) { + return false; + } - const pastedNewLine = changeObj.origin === 'paste' && changeObj.text.length > 1; - if (pastedNewLine) { - const newText = changeObj.text.join(' '); - return changeObj.update(null, null, [newText]); + // also need to set cursor position + this.setState((state) => { + const newCursor = Math.max(state.commandCursor - 1, -1); + this._cm + .getDoc() + .setValue(state.commandHistory[newCursor] || ''); + const newLineCount = this._cm.getValue().split('\n').length; + const newLine = this._cm.getDoc().getLine(newLineCount); + const cursorPos = newLine ? newLine.length - 1 : 1; + this._cm.setCursor({ line: lineCount, ch: cursorPos }); + return { commandCursor: newCursor }; + }); } - - return null; + return true; }); this._cm.getWrapperElement().style['font-size'] = `${this.props.fontSize}px`; @@ -69,8 +103,6 @@ class ConsoleInput extends React.Component { this._cm = null; } - // _cm: CodeMirror.Editor - render() { return (
Date: Tue, 29 Sep 2020 12:49:25 -0400 Subject: [PATCH 44/45] Update cursor size for multiline commands --- client/modules/IDE/components/ConsoleInput.jsx | 14 +++++++------- client/styles/components/_console-input.scss | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 36fb8424b9..9e779d5f5a 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -53,7 +53,6 @@ class ConsoleInput extends React.Component { return false; } - // also need to set cursor position this.setState((state) => { const newCursor = Math.min( state.commandCursor + 1, @@ -63,8 +62,7 @@ class ConsoleInput extends React.Component { .getDoc() .setValue(state.commandHistory[newCursor] || ''); const cursorPos = this._cm.getDoc().getLine(0).length - 1; - console.log(cursorPos); - this._cm.setCursor({ line: 0, ch: cursorPos }); + this._cm.getDoc().setCursor({ line: 0, ch: cursorPos }); return { commandCursor: newCursor }; }); } else if (e.key === 'ArrowDown') { @@ -74,7 +72,6 @@ class ConsoleInput extends React.Component { return false; } - // also need to set cursor position this.setState((state) => { const newCursor = Math.max(state.commandCursor - 1, -1); this._cm @@ -83,7 +80,7 @@ class ConsoleInput extends React.Component { const newLineCount = this._cm.getValue().split('\n').length; const newLine = this._cm.getDoc().getLine(newLineCount); const cursorPos = newLine ? newLine.length - 1 : 1; - this._cm.setCursor({ line: lineCount, ch: cursorPos }); + this._cm.getDoc().setCursor({ line: lineCount, ch: cursorPos }); return { commandCursor: newCursor }; }); } @@ -108,12 +105,15 @@ class ConsoleInput extends React.Component {
-
+
{ this.codemirrorContainer = element; }} className="console__editor" /> diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss index 7d2dd3bf64..84db1f3387 100644 --- a/client/styles/components/_console-input.scss +++ b/client/styles/components/_console-input.scss @@ -1,7 +1,7 @@ .console__input { width: 100%; display: flex; - align-items: center; + align-items: start; @include themify() { background-color: getThemifyVariable('console-input-background-color'); } From ac5c376500c20c5745c1ce9e45a373e8493c9e27 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Tue, 29 Sep 2020 13:09:53 -0400 Subject: [PATCH 45/45] Remove unused variables, add return at end of files --- client/modules/IDE/components/ConsoleInput.jsx | 2 +- client/styles/components/_p5-contrast-codemirror-theme.scss | 2 +- client/styles/components/_p5-dark-codemirror-theme.scss | 2 +- client/styles/components/_p5-light-codemirror-theme.scss | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 9e779d5f5a..274845192f 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import React, { useState, useEffect } from 'react'; +import React from 'react'; import CodeMirror from 'codemirror'; import { Encode } from 'console-feed'; diff --git a/client/styles/components/_p5-contrast-codemirror-theme.scss b/client/styles/components/_p5-contrast-codemirror-theme.scss index 15e98e64a1..b9f837cc15 100644 --- a/client/styles/components/_p5-contrast-codemirror-theme.scss +++ b/client/styles/components/_p5-contrast-codemirror-theme.scss @@ -134,4 +134,4 @@ $p5-contrast-activeline: #999999; .cm-s-p5-contrast .CodeMirror-cursor { border-left: 1px solid $p5-contrast-white; -} \ No newline at end of file +} diff --git a/client/styles/components/_p5-dark-codemirror-theme.scss b/client/styles/components/_p5-dark-codemirror-theme.scss index dc9759eb3f..51879fdfd9 100644 --- a/client/styles/components/_p5-dark-codemirror-theme.scss +++ b/client/styles/components/_p5-dark-codemirror-theme.scss @@ -141,4 +141,4 @@ $p5-dark-error: #df3a3d; .cm-s-p5-dark .CodeMirror-cursor { border-left: 1px solid $p5-dark-white; -} \ No newline at end of file +} diff --git a/client/styles/components/_p5-light-codemirror-theme.scss b/client/styles/components/_p5-light-codemirror-theme.scss index 9a9deee747..28345a34e0 100644 --- a/client/styles/components/_p5-light-codemirror-theme.scss +++ b/client/styles/components/_p5-light-codemirror-theme.scss @@ -134,4 +134,4 @@ $p5-light-activeline: rgb(207, 207, 207); .cm-s-p5-light .CodeMirror-cursor { border-left: 1px solid $p5-light-black; -} \ No newline at end of file +}