126 lines
3.2 KiB
TypeScript
126 lines
3.2 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2023 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
import * as Blockly from 'blockly';
|
|
import * as newBlocks from './blocks';
|
|
import { javascriptGenerator } from 'blockly/javascript';
|
|
import { save, load } from './serialization';
|
|
import { toolbox } from './toolbox';
|
|
import { registerContinuousToolbox } from '@blockly/continuous-toolbox';
|
|
import Cookies from 'js-cookie';
|
|
import * as nano from 'nano';
|
|
|
|
import './index.css';
|
|
|
|
function randomValueHex(length: number) {
|
|
let hex = '';
|
|
for (let i = 0; i < length; i++)
|
|
hex += Math.floor(Math.random() * 256).toString(16);
|
|
return hex;
|
|
}
|
|
|
|
let browserId = Cookies.get('id');
|
|
if (!browserId) {
|
|
browserId = randomValueHex(24);
|
|
if (!Cookies.get('id'))
|
|
Cookies.set('id', browserId);
|
|
}
|
|
|
|
const blocks = Object.values(newBlocks).reduce((acc, val) => {
|
|
acc = { ...acc, ...val.block };
|
|
return acc;
|
|
}, {});
|
|
|
|
const generators = Object.values(newBlocks).reduce((acc, val) => {
|
|
acc = { ...acc, [Object.keys(val.block)[0]]: val.toJS };
|
|
return acc;
|
|
}, {});
|
|
|
|
|
|
// Register the blocks and generator with Blockly
|
|
Blockly.common.defineBlocks(blocks);
|
|
Object.assign(javascriptGenerator.forBlock, generators);
|
|
|
|
registerContinuousToolbox();
|
|
|
|
// Set up UI elements and inject Blockly
|
|
const codeDiv = document.getElementById('outputDiv')?.firstChild;
|
|
const outputDiv = document.getElementById('output');
|
|
const blocklyDiv = document.getElementById('blocklyDiv');
|
|
|
|
if (!blocklyDiv) {
|
|
throw new Error(`div with id 'blocklyDiv' not found`);
|
|
}
|
|
const ws = Blockly.inject(
|
|
blocklyDiv,
|
|
{
|
|
toolbox,
|
|
plugins: {
|
|
flyoutsVerticalToolbox: 'ContinuousFlyout',
|
|
metricsManager: 'ContinuousMetrics',
|
|
toolbox: 'ContinuousToolbox',
|
|
},
|
|
},
|
|
);
|
|
|
|
// This function resets the code and output divs, shows the
|
|
// generated code from the workspace, and evals the code.
|
|
// In a real application, you probably shouldn't use `eval`.
|
|
const runCode = () => {
|
|
const code = javascriptGenerator.workspaceToCode(ws as Blockly.Workspace);
|
|
// console.dir(code);
|
|
|
|
try {
|
|
fetch(
|
|
'http://10.0.64.121:8081/set/' + browserId,
|
|
{
|
|
method: 'POST',
|
|
body: code,
|
|
}
|
|
);
|
|
}
|
|
catch (err) {
|
|
window.alert('Error');
|
|
}
|
|
|
|
if (codeDiv) codeDiv.textContent = code;
|
|
|
|
// if (outputDiv) outputDiv.innerHTML = '';
|
|
|
|
// eval(code);
|
|
};
|
|
|
|
if (ws) {
|
|
(window as any)['ws'] = ws;
|
|
(window as any)['save_ws'] = () => save(ws);
|
|
|
|
// Load the initial state from storage and run the code.
|
|
load(ws);
|
|
runCode();
|
|
|
|
// Every time the workspace changes state, save the changes to storage.
|
|
ws.addChangeListener((e: Blockly.Events.Abstract) => {
|
|
// UI events are things like scrolling, zooming, etc.
|
|
// No need to save after one of these.
|
|
if (e.isUiEvent) return;
|
|
save(ws);
|
|
});
|
|
|
|
// Whenever the workspace changes meaningfully, run the code again.
|
|
ws.addChangeListener((e: Blockly.Events.Abstract) => {
|
|
// Don't run the code when the workspace finishes loading; we're
|
|
// already running it once when the application starts.
|
|
// Don't run the code during drags; we might have invalid state.
|
|
if (
|
|
e.isUiEvent ||
|
|
e.type == Blockly.Events.FINISHED_LOADING ||
|
|
ws.isDragging()
|
|
) {
|
|
return;
|
|
}
|
|
runCode();
|
|
});
|
|
}
|