mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 01:23:52 +00:00
terminal resizing
This commit is contained in:
+3
-2
@@ -18,7 +18,6 @@
|
||||
"@types/web-bluetooth": "^0.0.5",
|
||||
"ace-builds": "^1.4.9",
|
||||
"bootstrap": "^4.4.1",
|
||||
"bootswatch": "^4.4.1",
|
||||
"jszip": "^3.4.0",
|
||||
"node-sass": "^4.13.1",
|
||||
"react": "^16.13.1",
|
||||
@@ -27,6 +26,7 @@
|
||||
"react-dom": "^16.13.1",
|
||||
"react-dropzone": "^10.2.2",
|
||||
"react-redux": "^7.2.0",
|
||||
"react-resize-observer": "^1.1.1",
|
||||
"react-scripts": "3.4.1",
|
||||
"react-transition-group": "^4.3.0",
|
||||
"redux": "^4.0.5",
|
||||
@@ -35,7 +35,8 @@
|
||||
"redux-saga": "^1.1.3",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"typescript": "~3.7.2",
|
||||
"xterm": "^4.5.0"
|
||||
"xterm": "^4.5.0",
|
||||
"xterm-addon-fit": "^0.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "mkdir -p public/static/js && cp node_modules/@pybricks/mpy-cross-4/build-wasm/mpy-cross.wasm public/static/js/",
|
||||
|
||||
@@ -31,7 +31,7 @@ class ActionButton<T = undefined> extends React.Component<ActionButtonProps<T>>
|
||||
}
|
||||
>
|
||||
<Button
|
||||
variant="primary"
|
||||
variant="light"
|
||||
onClick={(): void => this.props.onAction(this.props.context)}
|
||||
disabled={this.props.enabled === false}
|
||||
style={
|
||||
|
||||
+28
-6
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import Container from 'react-bootstrap/Container';
|
||||
import Editor from './Editor';
|
||||
import StatusBar from './Statusbar';
|
||||
@@ -7,12 +8,33 @@ import Toolbar from './Toolbar';
|
||||
|
||||
function App(): JSX.Element {
|
||||
return (
|
||||
<Container fluid>
|
||||
<Toolbar />
|
||||
<Editor />
|
||||
<Terminal />
|
||||
<StatusBar />
|
||||
</Container>
|
||||
<div
|
||||
className="position-fixed"
|
||||
style={{ width: '100%', height: 'calc(100% - 0px)' }}
|
||||
>
|
||||
<Container>
|
||||
<Row>
|
||||
<Col>
|
||||
<Toolbar />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col className="py-2">
|
||||
<Editor />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col style={{ height: '25vh' }} className="py-2">
|
||||
<Terminal />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="mt-2">
|
||||
<Col>
|
||||
<StatusBar />
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+22
-32
@@ -1,7 +1,5 @@
|
||||
import React, { ReactElement } from 'react';
|
||||
import AceEditor from 'react-ace';
|
||||
import Col from 'react-bootstrap/Col';
|
||||
import Row from 'react-bootstrap/Row';
|
||||
import { ReactReduxContext } from 'react-redux';
|
||||
import { setEditSession } from '../actions/editor';
|
||||
|
||||
@@ -13,36 +11,28 @@ import 'ace-builds/src-min-noconflict/ext-language_tools';
|
||||
class Editor extends React.Component {
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<Row className="px-2 py-4 bg-primary">
|
||||
<Col>
|
||||
<ReactReduxContext.Consumer>
|
||||
{({ store }): ReactElement => (
|
||||
<AceEditor
|
||||
mode="python"
|
||||
theme="xcode"
|
||||
fontSize="16pt"
|
||||
width="100"
|
||||
focus={true}
|
||||
placeholder="Write your program here..."
|
||||
defaultValue={
|
||||
localStorage.getItem('program') || undefined
|
||||
}
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
setOptions={{
|
||||
enableBasicAutocompletion: true,
|
||||
enableLiveAutocompletion: true,
|
||||
}}
|
||||
onFocus={(_, e): void => {
|
||||
store.dispatch(setEditSession(e?.session));
|
||||
}}
|
||||
onChange={(v): void =>
|
||||
localStorage.setItem('program', v)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</ReactReduxContext.Consumer>
|
||||
</Col>
|
||||
</Row>
|
||||
<ReactReduxContext.Consumer>
|
||||
{({ store }): ReactElement => (
|
||||
<AceEditor
|
||||
mode="python"
|
||||
theme="xcode"
|
||||
fontSize="16pt"
|
||||
width="100"
|
||||
focus={true}
|
||||
placeholder="Write your program here..."
|
||||
defaultValue={localStorage.getItem('program') || undefined}
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
setOptions={{
|
||||
enableBasicAutocompletion: true,
|
||||
enableLiveAutocompletion: true,
|
||||
}}
|
||||
onFocus={(_, e): void => {
|
||||
store.dispatch(setEditSession(e?.session));
|
||||
}}
|
||||
onChange={(v): void => localStorage.setItem('program', v)}
|
||||
/>
|
||||
)}
|
||||
</ReactReduxContext.Consumer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class OpenFileButton extends React.Component<OpenFileButtonProps> {
|
||||
>
|
||||
<Button
|
||||
{...getRootProps()}
|
||||
variant="primary"
|
||||
variant="light"
|
||||
disabled={this.props.enabled === false}
|
||||
style={
|
||||
this.props.enabled === false
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import React from 'react';
|
||||
import Col from 'react-bootstrap/Col';
|
||||
import ProgressBar from 'react-bootstrap/ProgressBar';
|
||||
import Row from 'react-bootstrap/Row';
|
||||
import { BLEConnectionState } from '../reducers/ble';
|
||||
|
||||
interface StatusBarState {
|
||||
@@ -25,11 +23,9 @@ class StatusBar extends React.Component<{}, StatusBarState> {
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<Row className="bg-info p-2">
|
||||
<Col className="col-2">
|
||||
<ProgressBar></ProgressBar>
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="bg-info p-2">
|
||||
<ProgressBar className="w-25"></ProgressBar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import Col from 'react-bootstrap/Col';
|
||||
import Row from 'react-bootstrap/Row';
|
||||
import { connect } from 'react-redux';
|
||||
import ResizeObserver from 'react-resize-observer';
|
||||
import { Dispatch } from 'redux';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Terminal as XTerm } from 'xterm';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { receiveData } from '../actions/terminal';
|
||||
import { terminalOutput } from '../epics/terminal';
|
||||
|
||||
@@ -18,6 +18,7 @@ type TerminalProps = DispatchProps;
|
||||
|
||||
class Terminal extends React.Component<TerminalProps> {
|
||||
private xterm: XTerm;
|
||||
private fitAddon: FitAddon;
|
||||
private terminalRef: React.RefObject<HTMLDivElement>;
|
||||
private subscription?: Subscription;
|
||||
|
||||
@@ -27,7 +28,6 @@ class Terminal extends React.Component<TerminalProps> {
|
||||
cursorBlink: true,
|
||||
cursorStyle: 'underline',
|
||||
fontSize: 18,
|
||||
rows: 8,
|
||||
theme: {
|
||||
background: 'white',
|
||||
foreground: 'black',
|
||||
@@ -36,6 +36,8 @@ class Terminal extends React.Component<TerminalProps> {
|
||||
selection: 'rgba(181,213,255,0.5)', // this should match AceEditor theme
|
||||
},
|
||||
});
|
||||
this.fitAddon = new FitAddon();
|
||||
this.xterm.loadAddon(this.fitAddon);
|
||||
this.xterm.onData((d) => this.props.onData(d));
|
||||
this.terminalRef = React.createRef();
|
||||
}
|
||||
@@ -46,6 +48,7 @@ class Terminal extends React.Component<TerminalProps> {
|
||||
return;
|
||||
}
|
||||
this.xterm.open(this.terminalRef.current);
|
||||
this.fitAddon.fit();
|
||||
this.subscription = terminalOutput.subscribe((v) => this.xterm.write(v));
|
||||
}
|
||||
|
||||
@@ -56,11 +59,13 @@ class Terminal extends React.Component<TerminalProps> {
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<Row className="px-2 py-4 bg-secondary">
|
||||
<Col>
|
||||
<div id="terminal" ref={this.terminalRef}></div>
|
||||
</Col>
|
||||
</Row>
|
||||
<div
|
||||
id="terminal"
|
||||
ref={this.terminalRef}
|
||||
style={{ height: 'inherit', width: 'inherit' }}
|
||||
>
|
||||
<ResizeObserver onResize={(): void => this.fitAddon.fit()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-17
@@ -1,8 +1,6 @@
|
||||
import React from 'react';
|
||||
import ButtonGroup from 'react-bootstrap/ButtonGroup';
|
||||
import ButtonToolbar from 'react-bootstrap/ButtonToolbar';
|
||||
import Col from 'react-bootstrap/Col';
|
||||
import Row from 'react-bootstrap/Row';
|
||||
import BluetoothButton from './BluetoothButton';
|
||||
import FlashButton from './FlashButton';
|
||||
import ReplButton from './ReplButton';
|
||||
@@ -12,21 +10,17 @@ import StopButton from './StopButton';
|
||||
class Toolbar extends React.Component {
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<Row>
|
||||
<Col>
|
||||
<ButtonToolbar className="m-2">
|
||||
<ButtonGroup className="mr-2" size="lg">
|
||||
<BluetoothButton id="bluetooth" />
|
||||
<RunButton id="run" />
|
||||
<StopButton id="stop" />
|
||||
</ButtonGroup>
|
||||
<ButtonGroup className="mr-2" size="lg">
|
||||
<ReplButton id="repl" />
|
||||
<FlashButton id="flash" />
|
||||
</ButtonGroup>
|
||||
</ButtonToolbar>
|
||||
</Col>
|
||||
</Row>
|
||||
<ButtonToolbar className="m-2">
|
||||
<ButtonGroup className="mr-2" size="lg">
|
||||
<BluetoothButton id="bluetooth" />
|
||||
<RunButton id="run" />
|
||||
<StopButton id="stop" />
|
||||
</ButtonGroup>
|
||||
<ButtonGroup className="mr-2" size="lg">
|
||||
<ReplButton id="repl" />
|
||||
<FlashButton id="flash" />
|
||||
</ButtonGroup>
|
||||
</ButtonToolbar>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-15
@@ -1,19 +1,5 @@
|
||||
// Override default variables before the import
|
||||
// $body-bg: #000;
|
||||
$body-bg: #0088ce;
|
||||
|
||||
// Import Bootstrap and its default variables
|
||||
@import '~bootswatch/dist/lumen/variables';
|
||||
@import '~bootstrap/scss/bootstrap';
|
||||
@import '~bootswatch/dist/lumen/bootswatch';
|
||||
|
||||
// TODO: this can be removed if bootswatch package is updated with this fix
|
||||
.toast {
|
||||
.close {
|
||||
color: $black;
|
||||
|
||||
&:not(:disabled):not(.disabled):hover,
|
||||
&:not(:disabled):not(.disabled):focus {
|
||||
color: $black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2581,11 +2581,6 @@ bootstrap@^4.4.1:
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.4.1.tgz#8582960eea0c5cd2bede84d8b0baf3789c3e8b01"
|
||||
integrity sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==
|
||||
|
||||
bootswatch@^4.4.1:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/bootswatch/-/bootswatch-4.4.1.tgz#f270618b4ebe07de8e1748acd88f104cc31bfec3"
|
||||
integrity sha512-Kx3z6+3Jpg9g6l/xZBCnc8d6KeJK0QawxCZWOomdcI5AuSZLZb+DoH5X9RJH+cOcSeMAxyzdIjkVUR01+Db5bQ==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
@@ -9240,6 +9235,11 @@ react-redux@^7.2.0:
|
||||
prop-types "^15.7.2"
|
||||
react-is "^16.9.0"
|
||||
|
||||
react-resize-observer@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-resize-observer/-/react-resize-observer-1.1.1.tgz#641dfa2e0f4bd2549a8ab4bbbaf43b68f3dcaf76"
|
||||
integrity sha512-3R+90Hou90Mr3wJYc+unsySC8Pn91V4nmjO32NKvUvjphRUbq9HisyLg7bDyGBE7xlMrrM6Fax7iNQaFdc/FYA==
|
||||
|
||||
react-scripts@3.4.1:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.4.1.tgz#f551298b5c71985cc491b9acf3c8e8c0ae3ada0a"
|
||||
@@ -11671,6 +11671,11 @@ xtend@^4.0.0, xtend@~4.0.1:
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
||||
xterm-addon-fit@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.3.0.tgz#341710741027de9d648a9f84415a01ddfdbbe715"
|
||||
integrity sha512-kvkiqHVrnMXgyCH9Xn0BOBJ7XaWC/4BgpSWQy3SueqximgW630t/QOankgqkvk11iTOCwWdAY9DTyQBXUMN3lw==
|
||||
|
||||
xterm@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.5.0.tgz#c7fd145c6cf91c9f2ef07011a9b35026cf4bfecc"
|
||||
|
||||
Reference in New Issue
Block a user