diff --git a/.gitignore b/.gitignore index 4d29575d..86efbb56 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /node_modules /.pnp .pnp.js +*.wasm # testing /coverage diff --git a/package.json b/package.json index 0041dcce..1b26d161 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "xterm": "^4.4.0" }, "scripts": { + "prepare": "mkdir -p public/static/js && cp node_modules/@pybricks/mpy-cross/build-wasm/mpy-cross.wasm public/static/js/", "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", diff --git a/src/App.tsx b/src/App.tsx index 253e91b7..bc893ed5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,17 +3,15 @@ import AceEditor from 'react-ace'; import './App.css'; import { Connection } from './Connection'; import { Terminal } from './Terminal'; +import { Run } from './Run'; import 'ace-builds/src-noconflict/mode-python'; import 'ace-builds/src-noconflict/theme-github'; -function onChange(newValue: string): void { - console.log('change', newValue); -} - function App(): JSX.Element { const connection = React.createRef(); const terminal = React.createRef(); + const editor = React.createRef(); return (
@@ -21,18 +19,21 @@ function App(): JSX.Element { onData={(e): void => terminal.current?.write(e)} ref={connection} /> +
connection.current?.write(d)} + onData={(d): void => { + connection.current?.write(d); + }} ref={terminal} />
); diff --git a/src/Connection.tsx b/src/Connection.tsx index 735db252..b82a39a7 100644 --- a/src/Connection.tsx +++ b/src/Connection.tsx @@ -44,8 +44,19 @@ class Connection extends React.Component this.onConnectClicked = this.onConnectClicked.bind(this); } - public write(data: Uint8Array): void { - this.rxChar?.writeValue(data); + public write(data: BufferSource): Promise { + return this.rxChar?.writeValue(data) ?? Promise.reject('No rxChar'); + } + + public async downloadAndRun(data: Uint8Array): Promise { + const sizeData = new Uint8Array(4); + new DataView(sizeData.buffer).setUint32(0, data.length); + await this.write(sizeData); + const chunk = 20; + for (let i = 0; i < data.length; i += chunk) { + await this.write(data.slice(i, i + chunk)); + // TODO: wait for checksum response on every 5th write + } } private async connect(): Promise { diff --git a/src/Run.tsx b/src/Run.tsx new file mode 100644 index 00000000..2461e326 --- /dev/null +++ b/src/Run.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import AceEditor from 'react-ace'; +import MpyCross from '@pybricks/mpy-cross'; +import { Connection } from './Connection'; + +const mpy = MpyCross({ arguments: ['-mno-unicode'] }); + +interface RunProperties { + readonly editor: React.RefObject; + readonly connection: React.RefObject; +} + +class Run extends React.Component { + constructor(props: RunProperties) { + super(props); + this.onClick = this.onClick.bind(this); + } + private async onClick(): Promise { + try { + const session = this.props.editor.current?.editor.getSession(); + const document = session.getDocument(); + const data = mpy.compile(document.getValue()); + await this.props.connection.current?.downloadAndRun(data); + } catch (err) { + alert(err); + } + } + + render(): JSX.Element { + return ( + + ); + } +} + +export { Run };