From 276caacfc9f571efd2c39f5a54598d5068a84433 Mon Sep 17 00:00:00 2001 From: Priit Haamer Date: Sun, 27 Nov 2016 13:27:04 +0200 Subject: [PATCH] Add basic console implementation See #5 --- App.css | 60 ++++++++++++++++++++-- main.js | 1 - package.json | 1 + preview.html | 6 ++- src/fiddlings/FiddlingContainer.js | 82 ++++++++++++++++++++++++++++-- yarn.lock | 4 ++ 6 files changed, 143 insertions(+), 11 deletions(-) diff --git a/App.css b/App.css index 6d6260b..8ed9235 100644 --- a/App.css +++ b/App.css @@ -15,22 +15,67 @@ body { .pane-editors, .pane-preview { + display: flex; flex-grow: 1; flex-shrink: 0; width: 50%; } .pane-editors { - display: flex; flex-direction: column; border-right: 1px solid rgba(0,0,0,0.15); box-sizing: border-box; } +.pane-preview { + display: flex; + flex-direction: column; +} + .preview-container { - display:inline-flex; + display: flex; + flex-direction: column; width: 100%; - height: 100vh; + flex-grow: 1; +} + +.preview-frame { + flex-grow: 1; +} + +.console-container { + display: none; + border-top: 1px solid rgba(0,0,0,0.15); + width: 100%; + height: 25vh; + font-size: 14px; + box-sizing: border-box; + overflow: auto; +} + +.console-container-visible { + display: block; +} + +.console-lines > div { + font-family: 'SF Mono', 'Inconsolata', 'Monaco', 'Consolas', monospace; + font-size: 12px; + box-sizing: border-box; + border-bottom: 1px solid rgba(0,0,0,0.05); + line-height: 1.5; + padding-left: 20px; +} + +.console-input { + width: 100%; + outline: none; + border: 0; + box-sizing: border-box; + font-family: 'SF Mono', 'Inconsolata', 'Monaco', 'Consolas', monospace; + font-size: 12px; + line-height: 1.5; + color: #094650; + padding: 2px 5px 2px 20px; } .editors-container { @@ -46,13 +91,20 @@ body { } .controls-container { + display: flex; + flex-direction: column; flex-grow: 0; flex-shrink: 0; border-top: 1px solid rgba(0,0,0,0.15); padding: 0.5em 1em; color: #094650; font-size: 10px; - user-select: none; + -webkit-user-select: none; + cursor: default; +} + +.controls-container-console { + align-self: flex-end; } .editor-name { diff --git a/main.js b/main.js index 8f14a1d..d6828d9 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,3 @@ -// @flow const electron = require('electron'); const {Menu, dialog} = require('electron'); // Module to control application life. diff --git a/package.json b/package.json index 720acb3..143c405 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "codemirror": "^5.20.2", "eslint-plugin-flowtype": "^2.25.0", "react": "^15.4.0", + "react-classset": "^0.0.2", "react-dom": "^15.4.0", "redux": "^3.6.0" }, diff --git a/preview.html b/preview.html index 380e0a9..5b171e2 100644 --- a/preview.html +++ b/preview.html @@ -9,7 +9,9 @@ diff --git a/src/fiddlings/FiddlingContainer.js b/src/fiddlings/FiddlingContainer.js index ae015d1..a96628b 100644 --- a/src/fiddlings/FiddlingContainer.js +++ b/src/fiddlings/FiddlingContainer.js @@ -1,5 +1,6 @@ // @flow import React from 'react'; +import ClassSet from 'react-classset'; import CodeMirror from '../lib/components/CodeMirror'; @@ -32,17 +33,32 @@ export default class FiddlingContainer extends React.Component { webView: any; + state: { + consoleVisible: boolean, + consoleInputValue: string, + consoleLines: Array + } + + constructor() { + super(); + this.state = { + consoleVisible: false, + consoleInputValue: '', + consoleLines: [] + }; + } + componentDidMount() { const webViewContainer = this.refs.webViewContainer; this.webView = document.createElement('webview'); - this.webView.setAttribute('class', 'preview-container'); + this.webView.setAttribute('class', 'preview-frame'); this.webView.setAttribute('id', 'preview'); this.webView.setAttribute('src', './preview.html'); this.webView.setAttribute('nodeintegration', 'true'); this.webView.addEventListener('console-message', e => { - console.log('Preview pane log:', e.message); + this.appendToConsoleLog(e.message); }); this.webView.addEventListener('dom-ready', () => { @@ -58,6 +74,14 @@ export default class FiddlingContainer extends React.Component { this.webView.send('updater', kind, value); } + appendToConsoleLog(...lines: Array) { + this.setState({ + consoleLines: [...this.state.consoleLines, ...lines] + }, () => { + this.refs.consoleInput.scrollIntoView(); + }); + } + handleHtmlChanged(value: string) { this.updatePreview('html', value); } @@ -70,6 +94,36 @@ export default class FiddlingContainer extends React.Component { this.updatePreview('javascript', value); } + handleConsoleToggleClick() { + this.setState({ + consoleVisible: !this.state.consoleVisible + }); + } + + handleConsoleInputChange(event: Event) { + if (event.target instanceof HTMLInputElement) { + const value = event.target.value; + this.setState({consoleInputValue: value}); + } + } + + handleConsoleKeyup(event: KeyboardEvent) { + if (event.key === 'Enter' && event.target instanceof HTMLInputElement) { + const input = event.target; + const inputValue = input.value; + + this.webView.executeJavaScript(inputValue, false, (result) => { + this.appendToConsoleLog(inputValue, JSON.stringify(result)); + }); + + this.setState({ + consoleInputValue: '' + }, () => { + input.focus(); + }); + } + } + render() { return (
@@ -104,10 +158,30 @@ export default class FiddlingContainer extends React.Component {
-
Controls
+
+ Console +
+
+ +
+
+
+
+ {this.state.consoleLines.map((line, idx) => (
{line}
))} +
+
-
); } diff --git a/yarn.lock b/yarn.lock index 9e9e8f9..22fe779 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2930,6 +2930,10 @@ rc@^1.0.1, rc@^1.1.2, rc@^1.1.6, rc@~1.1.6: minimist "^1.2.0" strip-json-comments "~1.0.4" +react-classset@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/react-classset/-/react-classset-0.0.2.tgz#adc62798acba8c0b2290506c190ea092a59c1f53" + react-dom@^15.4.0: version "15.4.1" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.4.1.tgz#d54c913261aaedb17adc20410d029dcc18a1344a"