diff --git a/assets/noimagefallback.png b/assets/noimagefallback.png new file mode 100644 index 0000000..32b2e33 Binary files /dev/null and b/assets/noimagefallback.png differ diff --git a/assets/organization-logo.png b/assets/organization-logo.png new file mode 100644 index 0000000..6d52394 Binary files /dev/null and b/assets/organization-logo.png differ diff --git a/blocks/IDE/generator.js b/blocks/IDE/generator.js index b5050a5..4266691 100644 --- a/blocks/IDE/generator.js +++ b/blocks/IDE/generator.js @@ -11,5 +11,5 @@ luaGenerator.forBlock['ide_addcode'] = function(block, generator) { // Remove all occurrences of the matched characters const cleanedStr = codefromuser.replace(/[']/g, ''); - return cleanedStr; + return cleanedStr+"\n"; }; diff --git a/blocks/IDE/index.json b/blocks/IDE/index.json index 6f4e377..744bbbe 100644 --- a/blocks/IDE/index.json +++ b/blocks/IDE/index.json @@ -9,6 +9,7 @@ "peripherals": false, "library": false, "turtle": false, + "pocket": false, "require_network": false, "dependencies": {} } \ No newline at end of file diff --git a/blocks/Template/block_design.json b/blocks/Template/block_design.json new file mode 100644 index 0000000..cc5463c --- /dev/null +++ b/blocks/Template/block_design.json @@ -0,0 +1,87 @@ +{ + "math_operation": { + "message0": "args %1 %2 %3", + "args0": [ + { + "type": "field_dropdown", + "name": "OPERATOR", + "options": [ + ["+", "ADD"], + ["-", "SUBTRACT"], + ["*", "MULTIPLY"], + ["/", "DIVIDE"] + ] + }, + { + "type": "input_value", + "name": "NUM1", + "check": "Number" + }, + { + "type": "input_value", + "name": "NUM2", + "check": "Number" + } + ], + "inputsInline": true, + "output": "Number", + "colour": 230, + "tooltip": "Perform a mathematical operation", + "helpUrl": "" + }, + "text_print": { + "message0": "print %1", + "args0": [ + { + "type": "input_value", + "name": "TEXT" + } + ], + "previousStatement": null, + "nextStatement": null, + "colour": 160, + "tooltip": "Print text", + "helpUrl": "" + }, + "controls_if": { + "message0": "if %1 then", + "args0": [ + { + "type": "input_value", + "name": "IF0", + "check": "Boolean" + } + ], + "message1": "do %1", + "args1": [ + { + "type": "input_statement", + "name": "DO0" + } + ], + "previousStatement": null, + "nextStatement": null, + "colour": 210, + "tooltip": "If condition", + "helpUrl": "" + }, + "variables_set": { + "message0": "set %1 to %2", + "args0": [ + { + "type": "field_variable", + "name": "VAR", + "variable": "item" + }, + { + "type": "input_value", + "name": "VALUE" + } + ], + "previousStatement": null, + "nextStatement": null, + "colour": 330, + "tooltip": "Set variable", + "helpUrl": "" + } +} diff --git a/blocks/Template/generator.js b/blocks/Template/generator.js new file mode 100644 index 0000000..6cfab87 --- /dev/null +++ b/blocks/Template/generator.js @@ -0,0 +1,58 @@ +const { luaGenerator } = require('blockly/lua'); + +// Check if luaGenerator.forBlock is defined and initialize if necessary +if (!luaGenerator.forBlock) { + luaGenerator.forBlock = {}; +} + +// Math operation block +luaGenerator.forBlock['math_operation'] = function(block, generator) { + var operator = block.getFieldValue('OPERATOR'); + var num1 = generator.valueToCode(block, 'NUM1', generator.ORDER_ATOMIC); + var num2 = generator.valueToCode(block, 'NUM2', generator.ORDER_ATOMIC); + + var operatorSymbol = ''; + switch (operator) { + case 'ADD': + operatorSymbol = '+'; + break; + case 'SUBTRACT': + operatorSymbol = '-'; + break; + case 'MULTIPLY': + operatorSymbol = '*'; + break; + case 'DIVIDE': + operatorSymbol = '/'; + break; + default: + operatorSymbol = '+'; + break; + } + + var code = `${num1} ${operatorSymbol} ${num2}`; + return [code, generator.ORDER_ATOMIC]; +}; + +// Print text block +luaGenerator.forBlock['text_print'] = function(block, generator) { + var text = generator.valueToCode(block, 'TEXT', generator.ORDER_NONE) || '\'\''; + var code = `print(${text})\n`; + return code; +}; + +// If condition block +luaGenerator.forBlock['controls_if'] = function(block, generator) { + var condition = generator.valueToCode(block, 'IF0', generator.ORDER_NONE) || 'false'; + var branch = generator.statementToCode(block, 'DO0'); + var code = `if ${condition} then\n${branch}\nend\n`; + return code; +}; + +// Set variable block +luaGenerator.forBlock['variables_set'] = function(block, generator) { + var variable = generator.nameDB_.getName(block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + var value = generator.valueToCode(block, 'VALUE', generator.ORDER_NONE) || '0'; + var code = `${variable} = ${value}\n`; + return code; +}; diff --git a/blocks/test/index.json b/blocks/Template/index.json similarity index 54% rename from blocks/test/index.json rename to blocks/Template/index.json index cf8a6e2..c23bd58 100644 --- a/blocks/test/index.json +++ b/blocks/Template/index.json @@ -1,14 +1,15 @@ { - "name": "Test Peripheral", + "name": "Template", "author": "DPSoftware Foundation", - "description": "Test Peripheral", + "description": "Template for creating custom blocks in ccIDE", "version": "1.0.0", - "category": "Blockly Extensions", - "keyword": "test", + "category": "", + "keyword": "template, custom block, ccIDE", "license": "GPL-3.0-or-later", "peripherals": false, "library": false, "turtle": false, + "pocket": false, "require_network": false, "dependencies": {} -} \ No newline at end of file +} diff --git a/blocks/Template/toolbox.xml b/blocks/Template/toolbox.xml new file mode 100644 index 0000000..5e48d4d --- /dev/null +++ b/blocks/Template/toolbox.xml @@ -0,0 +1,44 @@ + diff --git a/blocks/test/block_design.json b/blocks/test/block_design.json deleted file mode 100644 index 39518d5..0000000 --- a/blocks/test/block_design.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "custom_math_operation": { - "message0": "%1 %2 %3", - "args0": [ - { - "type": "field_dropdown", - "name": "OPERATOR", - "options": [ - ["+", "ADD"], - ["-", "SUBTRACT"], - ["*", "MULTIPLY"], - ["/", "DIVIDE"] - ] - }, - { - "type": "input_value", - "name": "NUM1", - "check": "Number" - }, - { - "type": "input_value", - "name": "NUM2", - "check": "Number" - } - ], - "inputsInline": true, - "output": "Number", - "colour": 230, - "tooltip": "Perform a mathematical operation", - "helpUrl": "" - } -} diff --git a/blocks/test/generator.js b/blocks/test/generator.js deleted file mode 100644 index 82e434d..0000000 --- a/blocks/test/generator.js +++ /dev/null @@ -1,35 +0,0 @@ -const { luaGenerator } = require('blockly/lua'); - -// Check if luaGenerator.forBlock is defined and initialize if necessary- -if (!luaGenerator.forBlock) { - luaGenerator.forBlock = {}; -} - -// Define your custom block handler -luaGenerator.forBlock['custom_math_operation'] = function(block, generator) { - var operator = block.getFieldValue('OPERATOR'); - var num1 = generator.valueToCode(block, 'NUM1', generator.ORDER_ATOMIC); - var num2 = generator.valueToCode(block, 'NUM2', generator.ORDER_ATOMIC); - - var operatorSymbol = ''; - switch (operator) { - case 'ADD': - operatorSymbol = '+'; - break; - case 'SUBTRACT': - operatorSymbol = '-'; - break; - case 'MULTIPLY': - operatorSymbol = '*'; - break; - case 'DIVIDE': - operatorSymbol = '/'; - break; - default: - operatorSymbol = '+'; - break; - } - - var code = `${num1} ${operatorSymbol} ${num2}`; - return [code, generator.ORDER_ATOMIC]; -}; diff --git a/blocks/test/toolbox.xml b/blocks/test/toolbox.xml deleted file mode 100644 index 6150c78..0000000 --- a/blocks/test/toolbox.xml +++ /dev/null @@ -1,17 +0,0 @@ - \ No newline at end of file diff --git a/ccIDE Defines.xlsx b/ccIDE Defines.xlsx index 8b14b6f..4e96e61 100644 Binary files a/ccIDE Defines.xlsx and b/ccIDE Defines.xlsx differ diff --git a/src/index.js b/index.js similarity index 54% rename from src/index.js rename to index.js index 0cdf264..78b24f9 100644 --- a/src/index.js +++ b/index.js @@ -4,32 +4,61 @@ const prompt = require('electron-prompt'); const path = require('path'); const ipc = ipcMain +process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'; + let currentprojectpath = null; let currentprojectname = null; -let currentprojectopen = false -let appexiting = false +let currentprojectopen = false; +let appexiting = false; +let appreloading = false; +let currentworkspacechange = false; +let isopennewproject = false; app.whenReady().then(() => { - currentprojectpath = null; - currentprojectname = null; - currentprojectopen = false; - appexiting = false; - + reloadall(false); const win = new BrowserWindow({ width: 1280, height: 720, - icon: path.join(__dirname, '..', 'assets', 'ccIDEIcon.ico'), + icon: path.join(__dirname, 'assets', 'ccIDEIcon.ico'), webPreferences: { devTools: true, nodeIntegration: true, enableRemoteModule: true, contextIsolation: false, - } + }, + show: false, + center: true, }) - win.loadFile('index.html') - //win.openDevTools(); - win.maximize() + var splash = new BrowserWindow({ + width: 600, + height: 300, + icon: path.join(__dirname, 'assets', 'ccIDEIcon.ico'), + transparent: true, + frame: false, + center: true + }); + + win.loadFile('src/index.html'); + splash.loadFile('src/splash.html'); + win.setTitle(`ccIDE`) + + + ipc.once('ready', () => { + console.log("ready") + if (splash) { + splash.close(); + } + win.show(); + win.maximize(); + }); + + ipc.on('erroronstart', (event, errormessage) => { + dialog.showErrorBox("Error on startup", errormessage); + //win.openDevTools(); + }); + + //app.on('activate', () => { // if (BrowserWindow.getAllWindows().length === 0) { @@ -37,6 +66,21 @@ app.whenReady().then(() => { // } //}) + function reloadall(isloaded=true) { + currentprojectpath = null; + currentprojectname = null; + currentprojectopen = false; + currentworkspacechange = false; + appexiting = false; + appreloading = false; + isopennewproject = false; + if (isloaded) { + win.setTitle(`ccIDE`) + win.reload(); + } + } + + // Define a custom menu template const menuTemplate = [ { @@ -46,43 +90,106 @@ app.whenReady().then(() => { label: 'New', accelerator: 'CmdOrCtrl+N', click: () => { - win.reload() + if (currentworkspacechange) { + const result = dialog.showMessageBoxSync({ + type: 'question', + buttons: ['Save', 'Don\'t Save', 'Cancel'], + defaultId: 2, + title: 'Save Changes', + message: "Your project is not saved", + }); + if (result === 1) { + // Don't save + reloadall(); + } else if (result === 0) { + // Save + appreloading = true; + win.webContents.send('save-workspace-request'); + } + } else { + reloadall(); + } } }, { label: 'Open', accelerator: 'CmdOrCtrl+O', click: () => { - dialog.showOpenDialog(win, { - title: 'Open Project', - defaultPath: app.getPath('documents'), - filters: [ - { name: 'ComputerCraft Project', extensions: ['ccp'] } - ], - properties: ['openFile'] - }).then(result => { - if (!result.canceled) { - const filePath = result.filePaths[0]; - - fs.readFile(filePath, 'utf8', (err, json) => { - if (err) { - console.error('Error loading workspace:', err); - return; + if (currentworkspacechange) { + const result = dialog.showMessageBoxSync({ + type: 'question', + buttons: ['Save', 'Don\'t Save', 'Cancel'], + defaultId: 2, + title: 'Save Changes', + message: "Your project is not saved", + }); + if (result === 1) { + // Don't save + dialog.showOpenDialog(win, { + title: 'Open Project', + defaultPath: app.getPath('documents'), + filters: [ + { name: 'ComputerCraft Project', extensions: ['ccp'] } + ], + properties: ['openFile'] + }).then(result => { + if (!result.canceled) { + const filePath = result.filePaths[0]; + + fs.readFile(filePath, 'utf8', (err, json) => { + if (err) { + console.error('Error loading workspace:', err); + return; + } + win.webContents.send('load-workspace', json); + + currentprojectpath = result.filePaths[0] + currentprojectname = path.basename(result.filePaths[0]); + currentprojectopen = true; + + win.setTitle(`${currentprojectname} | ccIDE`) + }); + } - win.webContents.send('load-workspace', json); - - currentprojectpath = result.filePaths[0] - currentprojectname = path.basename(result.filePaths[0]); - currentprojectopen = true; - - win.setTitle(`${currentprojectname} | ccIDE`) + }).catch(err => { + console.error('Error showing open dialog:', err); }); - + } else if (result === 0) { + // Save + isopennewproject = true; + win.webContents.send('save-workspace-request'); } - }).catch(err => { - console.error('Error showing open dialog:', err); - }); + } else { + dialog.showOpenDialog(win, { + title: 'Open Project', + defaultPath: app.getPath('documents'), + filters: [ + { name: 'ComputerCraft Project', extensions: ['ccp'] } + ], + properties: ['openFile'] + }).then(result => { + if (!result.canceled) { + const filePath = result.filePaths[0]; + + fs.readFile(filePath, 'utf8', (err, json) => { + if (err) { + console.error('Error loading workspace:', err); + return; + } + win.webContents.send('load-workspace', json); + currentprojectpath = result.filePaths[0] + currentprojectname = path.basename(result.filePaths[0]); + currentprojectopen = true; + + win.setTitle(`${currentprojectname} | ccIDE`) + }); + + } + }).catch(err => { + console.error('Error showing open dialog:', err); + }); + } } }, { @@ -133,7 +240,7 @@ app.whenReady().then(() => { { label: 'About', click: () => { - console.log('About clicked'); + win.webContents.send("open-about") } } ] @@ -194,6 +301,9 @@ app.whenReady().then(() => { win.webContents.send('workspace-saved', true); win.setTitle(`${currentprojectname} | ccIDE`) + if (currentworkspacechange) { + currentworkspacechange = false; + } } }); } else { @@ -217,9 +327,47 @@ app.whenReady().then(() => { win.setTitle(`${currentprojectname} | ccIDE`) + if (currentworkspacechange) { + currentworkspacechange = false; + } + if (appexiting) { app.quit(); } + if (appreloading) { + reloadall(); + } + if (isopennewproject) { + dialog.showOpenDialog(win, { + title: 'Open Project', + defaultPath: app.getPath('documents'), + filters: [ + { name: 'ComputerCraft Project', extensions: ['ccp'] } + ], + properties: ['openFile'] + }).then(result => { + if (!result.canceled) { + const filePath = result.filePaths[0]; + + fs.readFile(filePath, 'utf8', (err, json) => { + if (err) { + console.error('Error loading workspace:', err); + return; + } + win.webContents.send('load-workspace', json); + + currentprojectpath = result.filePaths[0] + currentprojectname = path.basename(result.filePaths[0]); + currentprojectopen = true; + + win.setTitle(`${currentprojectname} | ccIDE`) + }); + + } + }).catch(err => { + console.error('Error showing open dialog:', err); + }); + } } }); } @@ -227,7 +375,11 @@ app.whenReady().then(() => { ipc.on('workspace-notsave', (event) => { win.setTitle(`${currentprojectname}* | ccIDE`) - }) + currentworkspacechange = true; + }) + ipc.on('workspace-unsave', (event) => { + currentworkspacechange = true; + }) }) @@ -257,4 +409,10 @@ app.on("close", function(e) { // No unsaved changes, continue closing win = null; } +}); + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit(); + } }); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 52bf04b..f4b5ee9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,39 +9,23 @@ "version": "1.0.2", "license": "GPL-3.0-or-later", "dependencies": { - "@blockly/field-multilineinput": "^5.0.5", - "@blockly/theme-dark": "^7.0.3", + "@electron-fonts/noto-sans": "^1.2.0", "@electron/remote": "^2.1.2", "blockly": "^11.1.1", "bootstrap": "^5.3.3", "electron-prompt": "^1.7.0", - "mergexml": "^1.2.4", "xmldom": "^0.6.0" }, "devDependencies": { "electron": "^31.1.0" } }, - "node_modules/@blockly/field-multilineinput": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@blockly/field-multilineinput/-/field-multilineinput-5.0.5.tgz", - "integrity": "sha512-fCh+fkEeNCUwPyO6O45rH68e27RjMFWAvfUu/fYybGSIvt92uZfhZqq0veLMqAhwfYR7qQ7HIhUqvHQzAe4t6g==", - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "blockly": "^11.0.0" - } - }, - "node_modules/@blockly/theme-dark": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-7.0.3.tgz", - "integrity": "sha512-lRV9V5vjijbJAlUdZqtEhUt81OjHjZK8vagxir1cUqTrZ/+MNS2m7wkhIVPba4RWInJ1LY/nHEoQn6demZqRRQ==", - "engines": { - "node": ">=8.17.0" - }, - "peerDependencies": { - "blockly": "^11.0.0" + "node_modules/@electron-fonts/noto-sans": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@electron-fonts/noto-sans/-/noto-sans-1.2.0.tgz", + "integrity": "sha512-czys6R1EUpuc7sbK5h5SbVRE4HScbrnx4dlOrli7AyCWomSOYnAW+5nJevibZnTseFFe8MCdORaZoCe+LXe/1Q==", + "dependencies": { + "electron-css-injector": "1.3.0" } }, "node_modules/@electron/get": { @@ -153,14 +137,6 @@ "@types/node": "*" } }, - "node_modules/@xmldom/xmldom": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz", - "integrity": "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/agent-base": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", @@ -172,11 +148,6 @@ "node": ">= 14" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -397,15 +368,6 @@ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "optional": true }, - "node_modules/dezalgo": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, "node_modules/electron": { "version": "31.1.0", "resolved": "https://registry.npmjs.org/electron/-/electron-31.1.0.tgz", @@ -423,6 +385,11 @@ "node": ">= 12.20.55" } }, + "node_modules/electron-css-injector": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/electron-css-injector/-/electron-css-injector-1.3.0.tgz", + "integrity": "sha512-xRpwgP2fYSkB21vtL6jC77p4Gn/bc6PH2M6kOe5tOJkUsznqk3kpDe/UHpuvehHH+MMn8Mf+g24PXEADWhSvIA==" + }, "node_modules/electron-prompt": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/electron-prompt/-/electron-prompt-1.7.0.tgz", @@ -534,19 +501,6 @@ "node": ">= 6" } }, - "node_modules/formidable": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", - "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==", - "dependencies": { - "dezalgo": "^1.0.4", - "hexoid": "^1.0.0", - "once": "^1.4.0" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -736,14 +690,6 @@ "node": ">= 0.4" } }, - "node_modules/hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "engines": { - "node": ">=8" - } - }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -898,16 +844,6 @@ "node": ">=10" } }, - "node_modules/mergexml": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/mergexml/-/mergexml-1.2.4.tgz", - "integrity": "sha512-yiOlDqcVCz7AG1eSboonc18FTlfqDEKYfGoAV3Lul98u6YRV/s0kjtf4bjk47t0hLTFJR0BSYMd6BpmX3xDjNQ==", - "dependencies": { - "@xmldom/xmldom": "^0.7.0", - "formidable": "^3.5.1", - "xpath": "0.0.27" - } - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -1316,14 +1252,6 @@ "node": ">=10.0.0" } }, - "node_modules/xpath": { - "version": "0.0.27", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", - "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==", - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -1335,17 +1263,13 @@ } }, "dependencies": { - "@blockly/field-multilineinput": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@blockly/field-multilineinput/-/field-multilineinput-5.0.5.tgz", - "integrity": "sha512-fCh+fkEeNCUwPyO6O45rH68e27RjMFWAvfUu/fYybGSIvt92uZfhZqq0veLMqAhwfYR7qQ7HIhUqvHQzAe4t6g==", - "requires": {} - }, - "@blockly/theme-dark": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@blockly/theme-dark/-/theme-dark-7.0.3.tgz", - "integrity": "sha512-lRV9V5vjijbJAlUdZqtEhUt81OjHjZK8vagxir1cUqTrZ/+MNS2m7wkhIVPba4RWInJ1LY/nHEoQn6demZqRRQ==", - "requires": {} + "@electron-fonts/noto-sans": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@electron-fonts/noto-sans/-/noto-sans-1.2.0.tgz", + "integrity": "sha512-czys6R1EUpuc7sbK5h5SbVRE4HScbrnx4dlOrli7AyCWomSOYnAW+5nJevibZnTseFFe8MCdORaZoCe+LXe/1Q==", + "requires": { + "electron-css-injector": "1.3.0" + } }, "@electron/get": { "version": "2.0.3", @@ -1436,11 +1360,6 @@ "@types/node": "*" } }, - "@xmldom/xmldom": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz", - "integrity": "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==" - }, "agent-base": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", @@ -1449,11 +1368,6 @@ "debug": "^4.3.4" } }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1602,15 +1516,6 @@ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "optional": true }, - "dezalgo": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, "electron": { "version": "31.1.0", "resolved": "https://registry.npmjs.org/electron/-/electron-31.1.0.tgz", @@ -1621,6 +1526,11 @@ "extract-zip": "^2.0.1" } }, + "electron-css-injector": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/electron-css-injector/-/electron-css-injector-1.3.0.tgz", + "integrity": "sha512-xRpwgP2fYSkB21vtL6jC77p4Gn/bc6PH2M6kOe5tOJkUsznqk3kpDe/UHpuvehHH+MMn8Mf+g24PXEADWhSvIA==" + }, "electron-prompt": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/electron-prompt/-/electron-prompt-1.7.0.tgz", @@ -1700,16 +1610,6 @@ "mime-types": "^2.1.12" } }, - "formidable": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz", - "integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==", - "requires": { - "dezalgo": "^1.0.4", - "hexoid": "^1.0.0", - "once": "^1.4.0" - } - }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -1841,11 +1741,6 @@ "function-bind": "^1.1.2" } }, - "hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==" - }, "html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -1968,16 +1863,6 @@ "escape-string-regexp": "^4.0.0" } }, - "mergexml": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/mergexml/-/mergexml-1.2.4.tgz", - "integrity": "sha512-yiOlDqcVCz7AG1eSboonc18FTlfqDEKYfGoAV3Lul98u6YRV/s0kjtf4bjk47t0hLTFJR0BSYMd6BpmX3xDjNQ==", - "requires": { - "@xmldom/xmldom": "^0.7.0", - "formidable": "^3.5.1", - "xpath": "0.0.27" - } - }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -2278,11 +2163,6 @@ "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz", "integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==" }, - "xpath": { - "version": "0.0.27", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", - "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==" - }, "yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index 78c96f0..689272b 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "ComputerCraft mod virtual lua IDE", "main": "index.js", "scripts": { - "dev": "electron src/.", - "nodedev": "node src/." + "dev": "electron .", + "nodedev": "node ." }, "author": "DPSoftware Foundation", "license": "GPL-3.0-or-later", @@ -13,13 +13,10 @@ "electron": "^31.1.0" }, "dependencies": { - "@blockly/field-multilineinput": "^5.0.5", - "@blockly/theme-dark": "^7.0.3", "@electron/remote": "^2.1.2", "blockly": "^11.1.1", "bootstrap": "^5.3.3", "electron-prompt": "^1.7.0", - "mergexml": "^1.2.4", "xmldom": "^0.6.0" } } diff --git a/src/blocksmanager.js b/src/blocksmanager.js index 0769661..62af5ea 100644 --- a/src/blocksmanager.js +++ b/src/blocksmanager.js @@ -2,7 +2,9 @@ const fs = require('fs'); const path = require('path'); const { DOMParser, XMLSerializer } = require('xmldom'); -const peripheralsfolder = path.join(__dirname, "../blocks"); +const peripheralsfolder = path.join(__dirname, "../blocks"); + +let registedblock = {} function mergeXml(xml1, xml2) { const parser = new DOMParser(); @@ -20,7 +22,6 @@ function mergeXml(xml1, xml2) { } const mergedXml = serializer.serializeToString(doc1); - console.log(mergedXml) return mergedXml; } @@ -71,8 +72,48 @@ function loadperipheral(workspace, currenttoolbar, peripherals) { return newxml; } +function extractFolderName(path) { + // Normalize path separators to handle both Windows and Unix-style paths + const normalizedPath = path.replace(/[\\\/]/g, '/'); + // Split by '/' to get path segments + const parts = normalizedPath.split('/'); + // Filter out empty parts and get the last segment + const folderName = parts.filter(part => part.trim() !== '').pop(); + return folderName; +} +function scanindex() { + const files = fs.readdirSync(peripheralsfolder); + + // Iterate through files and directories + files.forEach(file => { + const filePath = path.join(peripheralsfolder, file); + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + // If it's a directory, recursively call scanFolders + const files = fs.readdirSync(filePath); + files.forEach(file => { + if (file === 'index.json') { + const filePath2 = path.join(filePath, file); + // If it's a file named index.json, read its contents + const content = fs.readFileSync(filePath2, 'utf8'); + const jsonData = JSON.parse(content); + + blockfoldername = extractFolderName(filePath); + registedblock[blockfoldername] = { + infomation: jsonData, + image: null + }; + console.log(`registered ${blockfoldername} blocks`) + } + + }) + } + }); +} module.exports = { - loadperipheral + loadperipheral, + scanindex } \ No newline at end of file diff --git a/src/frontend.js b/src/frontend.js new file mode 100644 index 0000000..4e9e4f0 --- /dev/null +++ b/src/frontend.js @@ -0,0 +1,73 @@ +var uploadpopup = document.getElementById('upload-popup'); +var aboutpopup = document.getElementById('about-popup'); +var librarypopup = document.getElementById('library-popup'); + +document.addEventListener('DOMContentLoaded', function () { + var tooltips = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); + var tooltipList = tooltips.map(function (tooltip) { + return new bootstrap.Tooltip(tooltip); + }); +}); + +// Event listener to close the upload-popup with fade-out effect +document.getElementById('uploadCloseBtn').addEventListener('click', function() { + uploadpopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation + setTimeout(function() { + uploadpopup.style.display = 'none'; // Hide popup after animation completes + uploadpopup.style.animation = ''; // Reset animation property + }, 300); // Adjust to match animation duration in milliseconds +}); + +document.getElementById('aboutCloseBtn').addEventListener('click', function() { + aboutpopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation + setTimeout(function() { + aboutpopup.style.display = 'none'; // Hide popup after animation completes + aboutpopup.style.animation = ''; // Reset animation property + }, 300); // Adjust to match animation duration in milliseconds +}); + +document.getElementById('libraryCloseBtn').addEventListener('click', function() { + librarypopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation + setTimeout(function() { + librarypopup.style.display = 'none'; // Hide popup after animation completes + librarypopup.style.animation = ''; // Reset animation property + }, 300); // Adjust to match animation duration in milliseconds +}); + +//-------------------------------- + +// Close the upload-popup if the user clicks outside of it +window.addEventListener('click', function(event) { + if (event.target == uploadpopup) { + uploadpopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation + setTimeout(function() { + uploadpopup.style.display = 'none'; // Hide popup after animation completes + uploadpopup.style.animation = ''; // Reset animation property + }, 300); // Adjust to match animation duration in milliseconds + } +}); + +window.addEventListener('click', function(event) { + if (event.target == aboutpopup) { + aboutpopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation + setTimeout(function() { + aboutpopup.style.display = 'none'; // Hide popup after animation completes + aboutpopup.style.animation = ''; // Reset animation property + }, 300); // Adjust to match animation duration in milliseconds + } +}); + +window.addEventListener('click', function(event) { + if (event.target == librarypopup) { + librarypopup.style.animation = 'fadeOut 0.3s ease'; // Apply fade-out animation + setTimeout(function() { + librarypopup.style.display = 'none'; // Hide popup after animation completes + librarypopup.style.animation = ''; // Reset animation property + }, 300); // Adjust to match animation duration in milliseconds + } +}); + +function openlibraryselect() { + librarypopup.style.display = 'block'; +} + diff --git a/src/index.html b/src/index.html index 5478afd..c9c53a1 100644 --- a/src/index.html +++ b/src/index.html @@ -4,28 +4,32 @@ ccIDE + + + - -
-

Loading...

-
- @@ -42,7 +46,7 @@ - :root { - --line-border-fill: #3498db; - --line-border-empty: #e0e0e0; - } - - body { - background-color: #212121; - margin: 0; - display: flex; - flex-direction: column; - height: 100vh; - } - - #navbar { - background-color: #2c3e50; - color: white; - display: flex; - padding: 15px; - gap: 10px; - } - - .navbar-button { - background-color: #2c3e50; - color: white; - border: none; - border-radius: 50%; /* Make the button circular */ - width: 40px; /* Adjust size as needed */ - height: 40px; /* Adjust size as needed */ - font-size: 1em; - cursor: pointer; - display: flex; - justify-content: center; - align-items: center; - transition: background-color 0.3s; - font-size: 1.5em; /* Adjust size as needed */ - } - - .navbar-button:hover { - background-color: #34495e; /* Darken color on hover */ - } - - [data-bs-toggle="tooltip"] { - position: relative; /* Ensure tooltips are positioned correctly */ - cursor: pointer; /* Add cursor style for tooltip interaction */ - } - - - #blocklyContainer { - position: relative; - width: 100%; - height: calc(100vh - 10vh); /* Adjust height to accommodate navbar and status bar */ - visibility: hidden; /* Initially hide the Blockly container */ - } - - #blocklyDiv { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - } - - #statusBar { - height: 3vh; /* Set the height of the status bar */ - background-color: #333; - color: #ffffff; - display: flex; - align-items: center; - padding: 0 10px; - box-sizing: border-box; - } - - #statusMessage { - margin: 0; - } - - /* Styles for the upload-popup container */ - .popup { - display: none; /* Hide initially */ - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */ - z-index: 999; /* Ensure it overlays other content */ - overflow: auto; - } - - /* Styles for the upload-popup content */ - .popup-content { - background-color: #fefefe; - margin: 15% auto; /* Center the upload-popup vertically and horizontally */ - padding: 20px; - border: 1px solid #888; - width: 80%; /* Adjust width as needed */ - max-width: 600px; /* Max width for larger screens */ - animation: fadeIn 0.3s ease; /* Fade-in animation */ - } - - /* Close button */ - .close { - float: right; - font-size: 28px; - font-weight: bold; - cursor: pointer; - } - - .close:hover, - .close:focus { - color: #000; - text-decoration: none; - } - - /* Fade-in animation */ - @keyframes fadeIn { - from { opacity: 0; } - to { opacity: 1; } - } - - /* Fade-out animation */ - @keyframes fadeOut { - from { opacity: 1; } - to { opacity: 0; } - } - - .progress-container { - display: flex; - justify-content: space-between; - position: relative; - margin-bottom: 30px; - max-width: 100%; - width: 350px; - } - - .progress-container::before { - content: ""; - background-color: var(--line-border-empty); - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - height: 4px; - width: 100%; - z-index: 99; /* Change z-index to 1 or higher */ - } - - .progress { - background-color: var(--line-border-fill); - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - height: 4px; - width: 0%; - z-index: 101; - transition: 0.4s ease; - } - - .progress.error { - background-color: red; /* Set to red color for error state */ - } - - - .circle { - background-color: #fff; - color: #999; - border-radius: 50%; - height: 30px; - width: 30px; - display: flex; - align-items: center; - justify-content: center; - border: 3px solid var(--line-border-empty); - transition: 0.4s ease; - z-index: 101; - } - - .circle.active { - border-color: var(--line-border-fill); - } - - .circle.error { - border-color: red; /* Optionally, change border color to red */ - color: white; /* Optionally, adjust text color for visibility */ - } - - - + + + + diff --git a/src/module_block_design.json b/src/module_block_design.json index b7cf57b..fafcc30 100644 --- a/src/module_block_design.json +++ b/src/module_block_design.json @@ -1,4 +1,13 @@ { + "sys_start": { + "message0": "When Code Start", + "message1": "do %1", + "args1": [ + {"type": "input_statement", "name": "DO"} + ], + "colour": 45, + "tooltip": "Not require but make your code easy to read." + }, "sys_sleep": { "message0": "Sleep For %1 Second", "args0": [ diff --git a/src/module_generator.js b/src/module_generator.js index 831048f..b3a615c 100644 --- a/src/module_generator.js +++ b/src/module_generator.js @@ -9,6 +9,20 @@ if (!luaGenerator.forBlock) { luaGenerator.forBlock['sys_sleep'] = function(block, generator) { var sleepfor = generator.valueToCode(block, 'SLEEPSEC', generator.ORDER_OVERRIDES); - var code = `sleep(${sleepfor})`; + var code = `sleep(${sleepfor})\n`; return code; }; + +luaGenerator.forBlock['sys_start'] = function(block, generator) { + var docode = generator.statementToCode(block, 'DO'); + + var code = +` +function main() +${docode} +end + +main() +` + return code; +}; \ No newline at end of file diff --git a/src/splash.html b/src/splash.html new file mode 100644 index 0000000..110db50 --- /dev/null +++ b/src/splash.html @@ -0,0 +1,72 @@ + + + + + Splash Screen + + + +
+ ccIDE Icon +

Loading ccIDE...

+
+
+
+
+ + + diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..6fdbb66 --- /dev/null +++ b/src/styles.css @@ -0,0 +1,190 @@ +:root { + --line-border-fill: #3498db; + --line-border-empty: #e0e0e0; +} + +body { + background-color: #212121; + margin: 0; + display: flex; + flex-direction: column; + height: 100vh; + font-family: 'Noto Sans', sans-serif; + overflow: hidden; /* Hide scrollbars */ +} + +#navbar { + background-color: #2c3e50; + color: white; + display: flex; + padding: 15px; + gap: 10px; +} + +.navbar-button { + background-color: #2c3e50; + color: white; + border: none; + border-radius: 50%; /* Make the button circular */ + width: 40px; /* Adjust size as needed */ + height: 40px; /* Adjust size as needed */ + font-size: 1em; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + transition: background-color 0.3s; + font-size: 1.5em; /* Adjust size as needed */ +} + +.navbar-button:hover { + background-color: #0066cc; /* Darken color on hover */ + z-index: 99; +} + +#blocklyContainer { + position: relative; + width: 100%; + height: calc(100vh - 10vh); /* Adjust height to accommodate navbar and status bar */ +} + +#blocklyDiv { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +#statusBar { + height: 3vh; /* Set the height of the status bar */ + background-color: #333; + color: #ffffff; + display: flex; + align-items: center; + padding: 0 10px; + box-sizing: border-box; +} + +#statusMessage { + margin: 0; +} + +/* Styles for the upload-popup container */ +.popup { + display: none; /* Hide initially */ + position: fixed; + justify-content: center; + align-items: center; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */ + z-index: 999; /* Ensure it overlays other content */ + overflow: auto; +} + +/* Styles for the upload-popup content */ +.popup-content { + background-color: #fefefe; + margin: 15% auto; /* Center the upload-popup vertically and horizontally */ + padding: 20px; + border: 1px solid #888; + width: 80%; /* Adjust width as needed */ + max-width: 600px; /* Max width for larger screens */ + animation: fadeIn 0.3s ease; /* Fade-in animation */ +} + + +/* Fade-in animation */ +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Fade-out animation */ +@keyframes fadeOut { + from { opacity: 1; } + to { opacity: 0; } +} + +.progress-container { + display: flex; + justify-content: space-between; + position: relative; + margin-bottom: 30px; + max-width: 100%; + width: 350px; +} + +.progress-container::before { + content: ""; + background-color: var(--line-border-empty); + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + height: 4px; + width: 100%; + z-index: 99; /* Change z-index to 1 or higher */ +} + +.progress { + background-color: var(--line-border-fill); + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + height: 4px; + width: 0%; + z-index: 101; + transition: 0.4s ease; +} + +.progress.error { + background-color: red; /* Set to red color for error state */ +} + + +.circle { + background-color: #fff; + color: #999; + border-radius: 50%; + height: 30px; + width: 30px; + display: flex; + align-items: center; + justify-content: center; + border: 3px solid var(--line-border-empty); + transition: 0.4s ease; + z-index: 101; +} + +.circle.active { + border-color: var(--line-border-fill); +} + +.circle.error { + border-color: red; /* Optionally, change border color to red */ + color: white; /* Optionally, adjust text color for visibility */ +} + +.libimage { + width: 100px; + height: 100px; + +} + +.library-item { + margin: 0 auto; + padding: 10px; +} + +.library-item:hover { + background-color: #cacaca; +} + +.library-container { + border: 1px solid #000000; +} \ No newline at end of file diff --git a/src/toolbox.xml b/src/toolbox.xml index efb0f07..679bd82 100644 --- a/src/toolbox.xml +++ b/src/toolbox.xml @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/src/virtualcode.js b/src/virtualcode.js index f8335ed..3b65509 100644 --- a/src/virtualcode.js +++ b/src/virtualcode.js @@ -1,4 +1,3 @@ -document.getElementById('statusMessage').textContent = "loading"; // override prompt command window.prompt = function(promptText, defaultValue) { return ipc.sendSync("prompt", promptText, defaultValue); @@ -7,12 +6,12 @@ window.prompt = function(promptText, defaultValue) { const fs = require('fs'); const path = require('path'); const { ipcRenderer } = require("electron"); -const { loadperipheral } = require("./blocksmanager"); +const { loadperipheral, scanindex } = require("./blocksmanager"); const Blockly = require('blockly'); -const { DarkTheme } = require('@blockly/theme-dark') const ipc = ipcRenderer; let isprojectsaved = false; +let isprojectopened = false; let usedlibinproject = [] Blockly.utils.colour.setHsvSaturation(0.9) @@ -32,10 +31,8 @@ for (const blockId in blocksJson) { } require("./module_generator") - var workspace = Blockly.inject('blocklyDiv', { toolbox: originaltoolbar, - theme: DarkTheme, trashcan: true, grid: { spacing: 20, @@ -45,11 +42,17 @@ var workspace = Blockly.inject('blocklyDiv', { } }); -originaltoolbar = loadperipheral(workspace, originaltoolbar, "test"); -originaltoolbar = loadperipheral(workspace, originaltoolbar, "IDE"); +try { + scanindex(); + originaltoolbar = loadperipheral(workspace, originaltoolbar, "Template"); + originaltoolbar = loadperipheral(workspace, originaltoolbar, "IDE"); +} catch (e) { + ipc.send("erroronstart", `Error on loading block: ${e}`) +} workspace.getToolbox().getFlyout().autoClose = false; + // Save workspace ipc.on('save-workspace-request', (event) => { const state = Blockly.serialization.workspaces.save(workspace); @@ -81,11 +84,16 @@ workspace.addChangeListener(function(event) { if (isprojectsaved) { isprojectsaved = false ipc.send("workspace-notsave") - }; + } else if (!isprojectopened) { + ipc.send("workspace-unsave") + } }); ipc.on('workspace-saved', (event, success) => { isprojectsaved = success + if (!isprojectopened) { + isprojectopened = true; + } }); ipc.on('request-undo-redo', (event, redo) => { @@ -93,8 +101,10 @@ ipc.on('request-undo-redo', (event, redo) => { workspace.undo(redo) }); -// Ensure Blockly container is shown after the workspace is injected -document.getElementById('loadingScreen').style.visibility = 'hidden'; -document.getElementById('blocklyContainer').style.visibility = 'visible'; -document.getElementById('statusMessage').textContent = "ready"; +ipc.on("open-about", () => { + document.getElementById('about-popup').style.display = 'block'; +}) +// Ensure Blockly container is shown after the workspace is injected +document.getElementById('statusMessage').textContent = "ready"; +ipc.send("ready") \ No newline at end of file