mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-09-27 08:54:48 +00:00
electron: removed workspaces, added sentry lib, electron-builder
This commit is contained in:
parent
10d04f9114
commit
d31428aa42
17
Makefile
17
Makefile
@ -23,18 +23,19 @@ all:
|
|||||||
$(TSC)
|
$(TSC)
|
||||||
npm run mkdoc
|
npm run mkdoc
|
||||||
|
|
||||||
dist:
|
distro:
|
||||||
rm -fr $(TMP) && mkdir -p $(TMP)
|
rm -fr $(TMP) && mkdir -p $(TMP)
|
||||||
git archive HEAD | tar x -C $(TMP)
|
git archive HEAD | tar x -C $(TMP)
|
||||||
cp -rp gen $(TMP)
|
cp -rp gen $(TMP)
|
||||||
rm -r $(TMP)/doc $(TMP)/meta $(TMP)/scripts $(TMP)/test* $(TMP)/tools $(TMP)/.[a-z]* $(TMP)/ts*.json
|
rm -r $(TMP)/doc $(TMP)/scripts $(TMP)/test* $(TMP)/tools $(TMP)/.[a-z]* $(TMP)/ts*.json # $(TMP)/meta
|
||||||
rm -f $(TMP)/javatari && mkdir -p $(TMP)/javatari && cp javatari.js/release/javatari/* $(TMP)/javatari/
|
rm -f $(TMP)/javatari && mkdir -p $(TMP)/javatari && cp javatari.js/release/javatari/* $(TMP)/javatari/
|
||||||
tar cf - `cat electron.html | egrep "^<(script|link)" | egrep -o '"([^"]+).(js|css)"' | cut -d '"' -f2` | tar x -C $(TMP)
|
tar cf - `cat electron.html | egrep "^<(script|link)" | egrep -o '"([^"]+).(js|css)"' | cut -d '"' -f2` | tar x -C $(TMP)
|
||||||
|
|
||||||
%.dist:
|
desktop: distro
|
||||||
./node_modules/.bin/electron-packager $(TMP) --icon meta/icons/8bitworkshop-icon-1024.icns --out ./release --overwrite --platform $*
|
pushd $(TMP) && npm i && popd $(TMP)
|
||||||
|
mkdir -p $(TMP)/resources
|
||||||
package: dist darwin.dist win32.dist linux.dist
|
./node_modules/.bin/electron-builder -mlw --project $(TMP) # --prepackaged $(TMP)
|
||||||
|
mv $(TMP)/dist/*.* ./release/
|
||||||
|
|
||||||
meta/electron.diff: index.html electron.html
|
meta/electron.diff: index.html electron.html
|
||||||
-diff -u index.html electron.html > $@
|
-diff -u index.html electron.html > $@
|
||||||
@ -53,11 +54,11 @@ astrolibre.b64.txt: astrolibre.rom
|
|||||||
|
|
||||||
VERSION := $(shell git tag -l --points-at HEAD)
|
VERSION := $(shell git tag -l --points-at HEAD)
|
||||||
|
|
||||||
syncdev: dist
|
syncdev: distro
|
||||||
cp config.js $(TMP)
|
cp config.js $(TMP)
|
||||||
aws --profile pzp s3 sync --follow-symlinks $(TMP)/ s3://8bitworkshop.com/dev
|
aws --profile pzp s3 sync --follow-symlinks $(TMP)/ s3://8bitworkshop.com/dev
|
||||||
|
|
||||||
syncprod: dist
|
syncprod: distro
|
||||||
@[ "${VERSION}" ] || ( echo ">> No version set at HEAD, tag it first"; exit 1 )
|
@[ "${VERSION}" ] || ( echo ">> No version set at HEAD, tag it first"; exit 1 )
|
||||||
echo Version: $(VERSION)
|
echo Version: $(VERSION)
|
||||||
cp config.js $(TMP)
|
cp config.js $(TMP)
|
||||||
|
@ -1,7 +1,22 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
// preload.js for Electron app
|
// preload.js for Electron app
|
||||||
const { ipcRenderer } = require('electron');
|
const { ipcRenderer } = require('electron');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const modpath = require('path');
|
const _path = require('path');
|
||||||
|
const chokidar = require('chokidar');
|
||||||
|
|
||||||
|
const homeDirectory = require('os').homedir();
|
||||||
|
const wsroot = _path.join(homeDirectory, '8bitworkshop');
|
||||||
|
|
||||||
|
function getLocalDir() {
|
||||||
|
const _ui = window.ui_1 || window.ui || window; // TODO: module naming
|
||||||
|
var dir = _ui.repo_id || _ui.platform_id || 'default';
|
||||||
|
return _path.join(wsroot, dir);
|
||||||
|
}
|
||||||
|
function getLocalFilePath(path) {
|
||||||
|
return _path.join(getLocalDir(), path);
|
||||||
|
}
|
||||||
|
|
||||||
function isProbablyBinary(path, data) {
|
function isProbablyBinary(path, data) {
|
||||||
var score = 0;
|
var score = 0;
|
||||||
@ -33,37 +48,84 @@ function isProbablyBinary(path, data) {
|
|||||||
return score > 0;
|
return score > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is before startUI is called
|
||||||
process.once('loaded', () => {
|
process.once('loaded', () => {
|
||||||
// workspace root path
|
var watcher;
|
||||||
// reload() clears this, so we have to set it every time
|
var allfiles = new Set();
|
||||||
var wsroot;
|
// get workspace root dir
|
||||||
// from browser: read workspace file synchronously
|
// from browser: read workspace files asynchronously
|
||||||
window.getWorkspaceFile = function(path, filetype) {
|
window.alternateLocalFilesystem = {
|
||||||
if (wsroot == null) throw Error("no workspace root set");
|
getFileData: (path) => {
|
||||||
try {
|
let fullpath = getLocalFilePath(path);
|
||||||
var fullpath = modpath.join(wsroot, modpath.normalize(path));
|
allfiles.add(fullpath);
|
||||||
var data = fs.readFileSync(fullpath); // read binary
|
if (!fs.existsSync(fullpath)) {
|
||||||
var buf = new Uint8Array(data); // convert to array
|
return null;
|
||||||
var isBinary = filetype != 'text' || isProbablyBinary(path, buf);
|
}
|
||||||
data = isBinary ? buf : data.toString('utf-8');
|
return new Promise( (resolve, reject) => {
|
||||||
console.log("getWorkspaceFile", path, isBinary, data.length);
|
fs.readFile(fullpath, (err,buf) => {
|
||||||
return data;
|
if (err) {
|
||||||
} catch (e) {
|
resolve(err);
|
||||||
console.log(e);
|
} else {
|
||||||
return null;
|
let isBinary = isProbablyBinary(path, buf);
|
||||||
|
let data = isBinary ? buf : buf.toString('utf-8');
|
||||||
|
console.log("getWorkspaceFile", path, isBinary, data.length);
|
||||||
|
resolve(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setFileData: (path, data) => {
|
||||||
|
let fullpath = getLocalFilePath(path);
|
||||||
|
allfiles.add(fullpath);
|
||||||
|
let encoding = typeof data === 'string' ? 'utf8' : null;
|
||||||
|
console.log("setWorkspaceFile", fullpath, data.length);
|
||||||
|
return new Promise( (resolve, reject) => {
|
||||||
|
fs.mkdir(_path.dirname(fullpath), {recursive:true}, (err,dirpath) => {
|
||||||
|
fs.writeFile(fullpath, data, {encoding:encoding}, (err) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// from browser: put workspace file
|
// watch/unwatch files as browser loses/gains focus
|
||||||
window.putWorkspaceFile = function(path, data) {
|
window.addEventListener("blur", (e) => {
|
||||||
if (wsroot == null) throw Error("no workspace root set");
|
let localdir = getLocalDir();
|
||||||
var fullpath = modpath.join(wsroot, modpath.normalize(path));
|
if (!watcher && localdir) {
|
||||||
var encoding = typeof data === 'string' ? 'utf8' : null;
|
// watch files for changes
|
||||||
fs.writeFileSync(fullpath, data, {encoding:encoding});
|
watcher = chokidar.watch(Array.from(allfiles), {
|
||||||
}
|
//awaitWriteFinish: {pollInterval:50,stabilityThreshold:300},
|
||||||
|
ignoreInitial: true
|
||||||
|
});
|
||||||
|
watcher.on('all', (event, path) => {
|
||||||
|
path = path.substring(localdir.length + 1); //strip off prefix
|
||||||
|
console.log('WATCH', event, path);
|
||||||
|
// we don't use awaitWriteFinish b/c we might close() the watcher
|
||||||
|
setTimeout(() => {
|
||||||
|
window.reloadWorkspaceFile(path);
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
console.log('watching', getLocalDir());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
window.addEventListener("focus", (e) => {
|
||||||
|
if (watcher) {
|
||||||
|
watcher.close();
|
||||||
|
watcher = null;
|
||||||
|
}
|
||||||
|
console.log('stopped watching');
|
||||||
|
});
|
||||||
|
|
||||||
// from electron.js: set workspace root directory
|
// from electron.js: set workspace root directory
|
||||||
|
/*
|
||||||
|
TODO
|
||||||
ipcRenderer.on('setWorkspaceRoot', (event, data) => {
|
ipcRenderer.on('setWorkspaceRoot', (event, data) => {
|
||||||
wsroot = data.root;
|
wsroot = data.root;
|
||||||
var binpath = modpath.join(wsroot, 'bin');
|
var binpath = _path.join(wsroot, 'bin');
|
||||||
if (!fs.existsSync(binpath)) fs.mkdirSync(binpath, {});
|
if (!fs.existsSync(binpath)) fs.mkdirSync(binpath, {});
|
||||||
console.log('setWorkspaceRoot', wsroot);
|
console.log('setWorkspaceRoot', wsroot);
|
||||||
});
|
});
|
||||||
@ -72,4 +134,6 @@ process.once('loaded', () => {
|
|||||||
var path = data.path;
|
var path = data.path;
|
||||||
window.reloadWorkspaceFile(path);
|
window.reloadWorkspaceFile(path);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
console.log('loaded preload', window.alternateLocalFilesystem, window.startUI);
|
||||||
});
|
});
|
||||||
|
@ -363,6 +363,7 @@ body {
|
|||||||
<script src="src/codemirror/fastbasic.js"></script>
|
<script src="src/codemirror/fastbasic.js"></script>
|
||||||
<script src="src/codemirror/basic.js"></script>
|
<script src="src/codemirror/basic.js"></script>
|
||||||
<script src="src/codemirror/wiz.js"></script>
|
<script src="src/codemirror/wiz.js"></script>
|
||||||
|
<script src="src/codemirror/vasm.js"></script>
|
||||||
<link rel="stylesheet" href="css/codemirror.css">
|
<link rel="stylesheet" href="css/codemirror.css">
|
||||||
<script src="codemirror/addon/edit/matchbrackets.js"></script>
|
<script src="codemirror/addon/edit/matchbrackets.js"></script>
|
||||||
<script src="codemirror/addon/search/search.js"></script>
|
<script src="codemirror/addon/search/search.js"></script>
|
||||||
@ -420,6 +421,7 @@ function require(modname) {
|
|||||||
<script src="gen/common/devices.js"></script>
|
<script src="gen/common/devices.js"></script>
|
||||||
<script src="gen/common/cpu/MOS6502.js"></script>
|
<script src="gen/common/cpu/MOS6502.js"></script>
|
||||||
<script src="gen/common/cpu/ZilogZ80.js"></script>
|
<script src="gen/common/cpu/ZilogZ80.js"></script>
|
||||||
|
<script src="gen/common/cpu/ARM.js"></script>
|
||||||
<script src="gen/machine/vdp_z80.js"></script>
|
<script src="gen/machine/vdp_z80.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -435,28 +437,5 @@ $( ".dropdown-submenu" ).click(function(event) {
|
|||||||
startUI();
|
startUI();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Sentry error reporting -->
|
|
||||||
<script
|
|
||||||
src="https://browser.sentry-cdn.com/6.4.1/bundle.min.js"
|
|
||||||
integrity="sha384-THoc7rflwZFKTdZNgv6jLFFDn299Uv3t1SW5B4yGLvLiCRTYP9ys6vXZcMl95TQF"
|
|
||||||
crossorigin="anonymous"
|
|
||||||
></script>
|
|
||||||
<script>
|
|
||||||
Sentry.init({
|
|
||||||
dsn: 'https://bf329df3d1b34afa9f5b5e8ecd80ad11@o320878.ingest.sentry.io/1813925',
|
|
||||||
beforeBreadcrumb(breadcrumb, hint) {
|
|
||||||
if (breadcrumb.category === 'xhr' && typeof breadcrumb.data.url === 'string') {
|
|
||||||
if (breadcrumb.data.url.startsWith('http')) return null; // discard external scripts
|
|
||||||
}
|
|
||||||
return breadcrumb;
|
|
||||||
},
|
|
||||||
beforeSend(event, hint) {
|
|
||||||
const error = hint.originalException;
|
|
||||||
if (error instanceof EmuHalt) return null; // ignore EmuHalt
|
|
||||||
return event;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
314
electron.js
314
electron.js
@ -1,217 +1,14 @@
|
|||||||
const { app, dialog, ipcMain, ipcRenderer, Menu, BrowserWindow } = require('electron')
|
"use strict";
|
||||||
|
|
||||||
|
const { app, Menu, BrowserWindow } = require('electron')
|
||||||
const modpath = require('path')
|
const modpath = require('path')
|
||||||
const fs = require('fs')
|
|
||||||
const {URLSearchParams} = require('url')
|
|
||||||
const isMac = process.platform === 'darwin'
|
const isMac = process.platform === 'darwin'
|
||||||
const chokidar = require('chokidar')
|
|
||||||
const Store = require('electron-store');
|
|
||||||
const store = new Store();
|
|
||||||
const WSMETA_FILENAME = "8bitworkshop.json"
|
|
||||||
const README_FILENAME = "README.md"
|
|
||||||
|
|
||||||
// call updater
|
// call updater
|
||||||
require('update-electron-app')()
|
///require('update-electron-app')()
|
||||||
|
|
||||||
// show error dialog
|
// init sentry
|
||||||
function showError(msg, detail) {
|
require('@sentry/electron').init({ dsn: "https://bf329df3d1b34afa9f5b5e8ecd80ad11@o320878.ingest.sentry.io/1813925" });
|
||||||
msg = msg.message || msg;
|
|
||||||
dialog.showMessageBoxSync({
|
|
||||||
type: "error",
|
|
||||||
message: msg,
|
|
||||||
detail: detail
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// file watcher
|
|
||||||
class Workspace {
|
|
||||||
constructor(directory, meta) {
|
|
||||||
this.directory = directory;
|
|
||||||
this.mainfile = meta.mainfile;
|
|
||||||
this.platform = meta.platform;
|
|
||||||
if (!this.mainfile) throw new Error(`The "mainfile" key is missing in ${WSMETA_FILENAME}.`)
|
|
||||||
if (!this.platform) throw new Error(`The "platform" key is missing in ${WSMETA_FILENAME}.`)
|
|
||||||
var mainfilepath = this.getMainFilePath();
|
|
||||||
if (!fs.existsSync(mainfilepath)) throw new Error(`The file "${mainfilepath}" is missing.`);
|
|
||||||
console.log("workspace opened", this.directory, this.mainfile);
|
|
||||||
}
|
|
||||||
getMainFilePath() {
|
|
||||||
return modpath.join(this.directory, this.mainfile);
|
|
||||||
}
|
|
||||||
close() {
|
|
||||||
this.unwatch();
|
|
||||||
console.log("workspace closed", this.directory, this.mainfile);
|
|
||||||
}
|
|
||||||
watch(wnd) {
|
|
||||||
this.watcher = chokidar.watch(this.directory, {
|
|
||||||
awaitWriteFinish: false
|
|
||||||
});
|
|
||||||
this.watcher.on('all', (event, path) => {
|
|
||||||
switch (event) {
|
|
||||||
case 'change':
|
|
||||||
console.log(event, path);
|
|
||||||
wnd.webContents.send('fileChanged', {
|
|
||||||
path: modpath.relative(this.directory, path),
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
console.log("watching workspace");
|
|
||||||
}
|
|
||||||
unwatch() {
|
|
||||||
if (this.watcher) {
|
|
||||||
this.watcher.close();
|
|
||||||
this.watcher = null;
|
|
||||||
console.log("un-watching workspace");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function readWorkspaceMetadata(directory) {
|
|
||||||
// check README file
|
|
||||||
var readmepath = modpath.join(directory, README_FILENAME);
|
|
||||||
if (fs.existsSync(readmepath)) {
|
|
||||||
let readme = fs.readFileSync(readmepath, 'utf8');
|
|
||||||
let sess = {};
|
|
||||||
// check README for main file
|
|
||||||
const re8main = /8bitworkshop.com[^)]+file=([^)&]+)/;
|
|
||||||
m = re8main.exec(readme);
|
|
||||||
if (m && m[1]) {
|
|
||||||
sess.mainfile = m[1];
|
|
||||||
}
|
|
||||||
// check README for proper platform
|
|
||||||
// unless we use githubURL=
|
|
||||||
const re8plat = /8bitworkshop.com[^)]+platform=([A-Za-z0-9._\-]+)/;
|
|
||||||
m = re8plat.exec(readme);
|
|
||||||
if (m) {
|
|
||||||
sess.platform = m[1];
|
|
||||||
}
|
|
||||||
if (sess.mainfile != null && sess.platform != null) return sess;
|
|
||||||
}
|
|
||||||
// check JSON file
|
|
||||||
var metapath = modpath.join(directory, WSMETA_FILENAME);
|
|
||||||
if (fs.existsSync(metapath)) {
|
|
||||||
return JSON.parse(fs.readFileSync(metapath, 'utf8'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeWorkspaceMetadata(directory, meta) {
|
|
||||||
var metapath = modpath.join(directory, WSMETA_FILENAME);
|
|
||||||
fs.writeFileSync(metapath, JSON.stringify(meta), 'utf8');
|
|
||||||
}
|
|
||||||
|
|
||||||
function openWorkspace(wnd, ws) {
|
|
||||||
if (wnd.workspace) { wnd.workspace.close(); }
|
|
||||||
wnd.workspace = ws;
|
|
||||||
wnd.on('closed', () => {
|
|
||||||
ws.close();
|
|
||||||
});
|
|
||||||
var qs = new URLSearchParams();
|
|
||||||
qs.set('electron_ws', 1);
|
|
||||||
qs.set('repo', ws.directory);
|
|
||||||
qs.set('file', ws.mainfile);
|
|
||||||
qs.set('platform', ws.platform);
|
|
||||||
console.log(qs);
|
|
||||||
wnd.loadURL(`file://${__dirname}/electron.html?${qs}`).then(() => {
|
|
||||||
wnd.webContents.send('setWorkspaceRoot', {root:ws.directory});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getActiveWorkspace() {
|
|
||||||
var wnd = BrowserWindow.getFocusedWindow();
|
|
||||||
return wnd && wnd.workspace;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: doesn't work if browser window reloads itself
|
|
||||||
function reloadCurrentWindow() {
|
|
||||||
var wnd = BrowserWindow.getFocusedWindow();
|
|
||||||
if (wnd.workspace) {
|
|
||||||
openWorkspace(wnd, wnd.workspace);
|
|
||||||
} else {
|
|
||||||
wnd.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: better way to get this?
|
|
||||||
function getCurrentPlatform(wnd) {
|
|
||||||
var url = wnd.webContents.getURL();
|
|
||||||
if (url != null) {
|
|
||||||
console.log(url);
|
|
||||||
var m = /platform=([^&]+)/.exec(url);
|
|
||||||
if (m) return m[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function openWorkspaceWindow(wspath) {
|
|
||||||
try {
|
|
||||||
// replace current window
|
|
||||||
var wnd = BrowserWindow.getFocusedWindow() || createWindow();
|
|
||||||
// read metadata file
|
|
||||||
var meta = readWorkspaceMetadata(wspath);
|
|
||||||
// does it exist?
|
|
||||||
if (meta == null) {
|
|
||||||
// create a new workspace?
|
|
||||||
var cancel = dialog.showMessageBoxSync(wnd, {
|
|
||||||
type: 'question',
|
|
||||||
title: 'Create Workspace?',
|
|
||||||
message: `Project metadata not found. Create new ${getCurrentPlatform(wnd)||""} project in this directory?`,
|
|
||||||
detail: wspath,
|
|
||||||
buttons: ['Create', 'Cancel'],
|
|
||||||
});
|
|
||||||
if (!cancel) {
|
|
||||||
var platform = getCurrentPlatform(wnd);
|
|
||||||
// choose main file
|
|
||||||
var files = dialog.showOpenDialogSync({
|
|
||||||
message: `Choose the main file of your ${platform} project, or create one.`,
|
|
||||||
defaultPath: wspath,
|
|
||||||
properties: ['openFile','promptToCreate'],
|
|
||||||
});
|
|
||||||
if (files != null) {
|
|
||||||
var mainfile = modpath.relative(wspath, files[0]);
|
|
||||||
// write new metadata
|
|
||||||
meta = {
|
|
||||||
platform: platform,
|
|
||||||
mainfile: mainfile,
|
|
||||||
};
|
|
||||||
console.log(meta);
|
|
||||||
if (meta.platform == null) {
|
|
||||||
showError("Can't determine current platform.");
|
|
||||||
} else {
|
|
||||||
writeWorkspaceMetadata(wspath, meta);
|
|
||||||
openWorkspaceWindow(wspath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log(meta);
|
|
||||||
var ws = new Workspace(wspath, meta);
|
|
||||||
openWorkspace(wnd, ws);
|
|
||||||
app.addRecentDocument(wspath);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
showError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function openDefaultWorkspace() {
|
|
||||||
if (process.argv.length >= 3) {
|
|
||||||
openWorkspaceWindow(modpath.resolve(process.argv[2]));
|
|
||||||
} else {
|
|
||||||
createWindow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function openWorkspaceDialog() {
|
|
||||||
dialog.showOpenDialog({
|
|
||||||
title: "Open Workspace",
|
|
||||||
properties: ['openDirectory'],
|
|
||||||
message: "Choose the directory that holds your source files.",
|
|
||||||
}).then((rtn) => {
|
|
||||||
if (!rtn.canceled && rtn.filePaths && rtn.filePaths.length > 0) {
|
|
||||||
var path = rtn.filePaths[0];
|
|
||||||
openWorkspaceWindow(path);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function openURL(url) {
|
function openURL(url) {
|
||||||
return async () => {
|
return async () => {
|
||||||
@ -220,6 +17,37 @@ function openURL(url) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createWindow () {
|
||||||
|
// Create the browser window.
|
||||||
|
const win = new BrowserWindow({
|
||||||
|
width: 1024,
|
||||||
|
height: 768,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
webPreferences: {
|
||||||
|
preload: modpath.join(__dirname, './electron-preload.js'),
|
||||||
|
nodeIntegration: false,
|
||||||
|
enableRemoteModule: false,
|
||||||
|
contextIsolation: false,
|
||||||
|
sandbox: false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// and load the index.html of the app.
|
||||||
|
win.loadFile('electron.html', {
|
||||||
|
search: 'electron=1&repo=/'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Maximize
|
||||||
|
win.maximize();
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: doesn't work if browser window reloads itself
|
||||||
|
function reloadCurrentWindow() {
|
||||||
|
var wnd = BrowserWindow.getFocusedWindow();
|
||||||
|
wnd.reload();
|
||||||
|
}
|
||||||
|
|
||||||
function buildMenu() {
|
function buildMenu() {
|
||||||
|
|
||||||
const template = [
|
const template = [
|
||||||
@ -242,28 +70,6 @@ function buildMenu() {
|
|||||||
{
|
{
|
||||||
label: 'File',
|
label: 'File',
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
|
||||||
label: 'New Playground',
|
|
||||||
click: createWindow,
|
|
||||||
accelerator: 'CmdOrCtrl+N',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Open Workspace...',
|
|
||||||
click: openWorkspaceDialog,
|
|
||||||
accelerator: 'CmdOrCtrl+O',
|
|
||||||
},
|
|
||||||
// When a file is requested from the recent documents menu, the open-file event of app module will be emitted for it.
|
|
||||||
{
|
|
||||||
"label":"Open Recent",
|
|
||||||
"role":"recentdocuments",
|
|
||||||
"submenu":[
|
|
||||||
{
|
|
||||||
"label":"Clear Recent",
|
|
||||||
"role":"clearrecentdocuments"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ type: 'separator' },
|
|
||||||
isMac ? { role: 'close' } : { role: 'quit' }
|
isMac ? { role: 'close' } : { role: 'quit' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -365,38 +171,10 @@ function buildMenu() {
|
|||||||
Menu.setApplicationMenu(menu)
|
Menu.setApplicationMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
function createWindow () {
|
|
||||||
// Create the browser window.
|
|
||||||
const win = new BrowserWindow({
|
|
||||||
width: 1024,
|
|
||||||
height: 768,
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
webPreferences: {
|
|
||||||
preload: modpath.join(__dirname, './electron-preload.js'),
|
|
||||||
nodeIntegration: false,
|
|
||||||
enableRemoteModule: false,
|
|
||||||
contextIsolation: false,
|
|
||||||
sandbox: false,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// and load the index.html of the app.
|
|
||||||
win.loadFile('electron.html', {
|
|
||||||
search: 'repo=/'
|
|
||||||
})
|
|
||||||
|
|
||||||
// Open the DevTools.
|
|
||||||
//win.webContents.openDevTools()
|
|
||||||
|
|
||||||
// Maximize
|
|
||||||
win.maximize();
|
|
||||||
return win;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method will be called when Electron has finished
|
// This method will be called when Electron has finished
|
||||||
// initialization and is ready to create browser windows.
|
// initialization and is ready to create browser windows.
|
||||||
// Some APIs can only be used after this event occurs.
|
// Some APIs can only be used after this event occurs.
|
||||||
app.whenReady().then(buildMenu).then(openDefaultWorkspace)
|
app.whenReady().then(buildMenu).then(createWindow)
|
||||||
|
|
||||||
// Quit when all windows are closed, except on macOS. There, it's common
|
// Quit when all windows are closed, except on macOS. There, it's common
|
||||||
// for applications and their menu bar to stay active until the user quits
|
// for applications and their menu bar to stay active until the user quits
|
||||||
@ -415,6 +193,7 @@ app.on('activate', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/* TODO
|
||||||
app.on('browser-window-focus', (e) => {
|
app.on('browser-window-focus', (e) => {
|
||||||
var ws = e.sender.workspace;
|
var ws = e.sender.workspace;
|
||||||
if (ws) ws.unwatch();
|
if (ws) ws.unwatch();
|
||||||
@ -424,19 +203,4 @@ app.on('browser-window-blur', (e) => {
|
|||||||
var ws = e.sender.workspace;
|
var ws = e.sender.workspace;
|
||||||
if (ws) ws.watch(e.sender);
|
if (ws) ws.watch(e.sender);
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on('open-file', (event, path) => {
|
|
||||||
openWorkspaceWindow(path);
|
|
||||||
})
|
|
||||||
|
|
||||||
// In this file you can include the rest of your app's specific main process
|
|
||||||
// code. You can also put them in separate files and require them here.
|
|
||||||
|
|
||||||
// Register IPC messages
|
|
||||||
// https://stackoverflow.com/questions/52236641/electron-ipc-and-nodeintegration
|
|
||||||
/*
|
|
||||||
ipcMain.on('hello', (event, message) => {
|
|
||||||
console.log(event);
|
|
||||||
});
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
--- index.html 2020-12-08 10:30:08.000000000 -0600
|
--- index.html 2021-07-09 15:15:12.000000000 -0500
|
||||||
+++ electron.html 2020-12-08 11:57:52.000000000 -0600
|
+++ electron.html 2021-07-10 13:34:48.000000000 -0500
|
||||||
@@ -3,18 +3,7 @@
|
@@ -3,18 +3,7 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
@ -223,3 +223,32 @@
|
|||||||
|
|
||||||
<script src="jquery/jquery.min.js"></script>
|
<script src="jquery/jquery.min.js"></script>
|
||||||
|
|
||||||
|
@@ -614,28 +437,5 @@
|
||||||
|
startUI();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
-<!-- Sentry error reporting -->
|
||||||
|
-<script
|
||||||
|
- src="https://browser.sentry-cdn.com/6.4.1/bundle.min.js"
|
||||||
|
- integrity="sha384-THoc7rflwZFKTdZNgv6jLFFDn299Uv3t1SW5B4yGLvLiCRTYP9ys6vXZcMl95TQF"
|
||||||
|
- crossorigin="anonymous"
|
||||||
|
-></script>
|
||||||
|
-<script>
|
||||||
|
-Sentry.init({
|
||||||
|
- dsn: 'https://bf329df3d1b34afa9f5b5e8ecd80ad11@o320878.ingest.sentry.io/1813925',
|
||||||
|
- beforeBreadcrumb(breadcrumb, hint) {
|
||||||
|
- if (breadcrumb.category === 'xhr' && typeof breadcrumb.data.url === 'string') {
|
||||||
|
- if (breadcrumb.data.url.startsWith('http')) return null; // discard external scripts
|
||||||
|
- }
|
||||||
|
- return breadcrumb;
|
||||||
|
- },
|
||||||
|
- beforeSend(event, hint) {
|
||||||
|
- const error = hint.originalException;
|
||||||
|
- if (error instanceof EmuHalt) return null; // ignore EmuHalt
|
||||||
|
- return event;
|
||||||
|
- },
|
||||||
|
-});
|
||||||
|
-</script>
|
||||||
|
-
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
4539
package-lock.json
generated
4539
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "8bitworkshop",
|
"name": "8bitworkshop",
|
||||||
"version": "3.7.2",
|
"version": "3.8.0b1",
|
||||||
"author": "Steven Hugg",
|
"author": "Steven Hugg",
|
||||||
"description": "8bitworkshop.com",
|
"category": "Development",
|
||||||
|
"description": "Desktop version of 8bitworkshop.com retro programming IDE",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/sehugg/8bitworkshop.git"
|
"url": "git+https://github.com/sehugg/8bitworkshop.git"
|
||||||
},
|
},
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@sentry/electron": "^2.5.1",
|
||||||
"binaryen": "^101.0.0",
|
"binaryen": "^101.0.0",
|
||||||
"chokidar": "^3.5.0",
|
"chokidar": "^3.5.0",
|
||||||
"electron-store": "^6.0.1",
|
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13"
|
||||||
"update-electron-app": "^1.5.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bootbox": "^5.1.3",
|
"@types/bootbox": "^5.1.3",
|
||||||
@ -30,6 +30,7 @@
|
|||||||
"clipboard": "^2.0.6",
|
"clipboard": "^2.0.6",
|
||||||
"command-exists": "^1.2.9",
|
"command-exists": "^1.2.9",
|
||||||
"electron": "^9.4.0",
|
"electron": "^9.4.0",
|
||||||
|
"electron-builder": "^22.11.7",
|
||||||
"electron-packager": "^15.2.0",
|
"electron-packager": "^15.2.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"heapdump": "^0.3.15",
|
"heapdump": "^0.3.15",
|
||||||
@ -51,10 +52,6 @@
|
|||||||
"typescript-formatter": "^7.2.2",
|
"typescript-formatter": "^7.2.2",
|
||||||
"vgm-parser": "^0.6.3"
|
"vgm-parser": "^0.6.3"
|
||||||
},
|
},
|
||||||
"directories": {
|
|
||||||
"doc": "doc",
|
|
||||||
"test": "tests"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "make",
|
"build": "make",
|
||||||
"test": "npm run test-node",
|
"test": "npm run test-node",
|
||||||
@ -82,5 +79,13 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/sehugg/8bitworkshop/issues"
|
"url": "https://github.com/sehugg/8bitworkshop/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/sehugg/8bitworkshop#readme"
|
"homepage": "https://github.com/sehugg/8bitworkshop#readme",
|
||||||
|
"build": {
|
||||||
|
"appId": "com.8bitworkshop.ide",
|
||||||
|
"icon": "meta/icons/8bitworkshop-icon-1024.png",
|
||||||
|
"copyright": "Copyright (c) 2021 Puzzling Plans LLC",
|
||||||
|
"linux": {
|
||||||
|
"category": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,19 +183,14 @@ function unsetLastPreset() {
|
|||||||
function initProject() {
|
function initProject() {
|
||||||
var basefs : ProjectFilesystem = new WebPresetsFileSystem(platform_id);
|
var basefs : ProjectFilesystem = new WebPresetsFileSystem(platform_id);
|
||||||
//basefs = new FirebaseProjectFilesystem("TEST", "TEST");
|
//basefs = new FirebaseProjectFilesystem("TEST", "TEST");
|
||||||
var filesystem = new OverlayFilesystem(
|
if (isElectron) {
|
||||||
basefs,
|
console.log('using electron with local filesystem', alternateLocalFilesystem);
|
||||||
new LocalForageFilesystem(store));
|
var filesystem = new OverlayFilesystem(basefs, alternateLocalFilesystem)
|
||||||
|
} else {
|
||||||
|
var filesystem = new OverlayFilesystem(basefs, new LocalForageFilesystem(store));
|
||||||
|
}
|
||||||
current_project = new CodeProject(newWorker(), platform_id, platform, filesystem);
|
current_project = new CodeProject(newWorker(), platform_id, platform, filesystem);
|
||||||
projectWindows = new ProjectWindows($("#workspace")[0] as HTMLElement, current_project);
|
projectWindows = new ProjectWindows($("#workspace")[0] as HTMLElement, current_project);
|
||||||
if (isElectronWorkspace) {
|
|
||||||
// TODO
|
|
||||||
/*
|
|
||||||
current_project.persistent = false;
|
|
||||||
current_project.callbackGetRemote = getElectronFile;
|
|
||||||
current_project.callbackStoreFile = putWorkspaceFile;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
current_project.callbackBuildResult = (result:WorkerResult) => {
|
current_project.callbackBuildResult = (result:WorkerResult) => {
|
||||||
setCompileOutput(result);
|
setCompileOutput(result);
|
||||||
};
|
};
|
||||||
@ -1080,9 +1075,7 @@ async function updateSelector() {
|
|||||||
await populateFiles(sel, "Local Files", "", foundFiles);
|
await populateFiles(sel, "Local Files", "", foundFiles);
|
||||||
finishSelector(sel);
|
finishSelector(sel);
|
||||||
} else {
|
} else {
|
||||||
if (!isElectronWorkspace) {
|
sel.append($("<option />").val('/').text('Leave Repository'));
|
||||||
sel.append($("<option />").val('/').text('Leave Repository'));
|
|
||||||
}
|
|
||||||
$("#repo_name").text(getFilenameForPath(repo_id)+'/').show();
|
$("#repo_name").text(getFilenameForPath(repo_id)+'/').show();
|
||||||
// repo: populate all files
|
// repo: populate all files
|
||||||
await populateFiles(sel, repo_id, "", {});
|
await populateFiles(sel, repo_id, "", {});
|
||||||
@ -1958,8 +1951,7 @@ export var qs = (function (a : string[]) {
|
|||||||
return b;
|
return b;
|
||||||
})(window.location.search.substr(1).split('&'));
|
})(window.location.search.substr(1).split('&'));
|
||||||
|
|
||||||
const isElectronWorkspace = qs['electron_ws'];
|
const isElectron = !!qs['electron'];
|
||||||
const isElectron = qs['electron'] || isElectronWorkspace;
|
|
||||||
|
|
||||||
function globalErrorHandler(msgevent) {
|
function globalErrorHandler(msgevent) {
|
||||||
var msg = (msgevent.message || msgevent.error || msgevent)+"";
|
var msg = (msgevent.message || msgevent.error || msgevent)+"";
|
||||||
@ -2220,13 +2212,7 @@ function setPlatformUI() {
|
|||||||
$(".platform_name").text(name || platform_id);
|
$(".platform_name").text(name || platform_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// start
|
export function getPlatformAndRepo() {
|
||||||
export async function startUI() {
|
|
||||||
// import from github?
|
|
||||||
if (qs['githubURL']) {
|
|
||||||
importProjectFromGithub(qs['githubURL'], true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// add default platform?
|
// add default platform?
|
||||||
// TODO: do this after repo_id
|
// TODO: do this after repo_id
|
||||||
platform_id = qs['platform'] || (hasLocalStorage && localStorage.getItem("__lastplatform"));
|
platform_id = qs['platform'] || (hasLocalStorage && localStorage.getItem("__lastplatform"));
|
||||||
@ -2249,6 +2235,16 @@ export async function startUI() {
|
|||||||
repo_id = '';
|
repo_id = '';
|
||||||
delete qs['repo'];
|
delete qs['repo'];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// start
|
||||||
|
export async function startUI() {
|
||||||
|
// import from github?
|
||||||
|
if (qs['githubURL']) {
|
||||||
|
importProjectFromGithub(qs['githubURL'], true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getPlatformAndRepo();
|
||||||
setupSplits();
|
setupSplits();
|
||||||
// create store
|
// create store
|
||||||
store_id = repo_id || getBasePlatform(platform_id);
|
store_id = repo_id || getBasePlatform(platform_id);
|
||||||
@ -2340,7 +2336,7 @@ function redirectToHTTPS() {
|
|||||||
// redirect to HTTPS after script loads?
|
// redirect to HTTPS after script loads?
|
||||||
redirectToHTTPS();
|
redirectToHTTPS();
|
||||||
|
|
||||||
//// ELECTRON STUFF
|
//// ELECTRON (and other external) STUFF
|
||||||
|
|
||||||
export function setTestInput(path: string, data: FileData) {
|
export function setTestInput(path: string, data: FileData) {
|
||||||
platform.writeFile(path, data);
|
platform.writeFile(path, data);
|
||||||
@ -2362,29 +2358,21 @@ export function emulationHalted(err: EmuHalt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get remote file from local fs
|
// get remote file from local fs
|
||||||
declare var getWorkspaceFile, putWorkspaceFile;
|
declare var alternateLocalFilesystem : ProjectFilesystem;
|
||||||
export function getElectronFile(url:string, success:(text:string|Uint8Array)=>void, datatype:'text'|'arraybuffer') {
|
|
||||||
// TODO: we have to split() to strip off presets/platform, yukky
|
export async function reloadWorkspaceFile(path: string) {
|
||||||
var contents = getWorkspaceFile(url.split('/',3)[2], datatype);
|
|
||||||
if (contents != null) {
|
|
||||||
success(contents); // return result
|
|
||||||
} else {
|
|
||||||
getWithBinary(url, success, datatype); // try to load from presets/platform via GET
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export function reloadWorkspaceFile(path: string) {
|
|
||||||
var oldval = current_project.filedata[path];
|
var oldval = current_project.filedata[path];
|
||||||
if (oldval != null) {
|
if (oldval != null) {
|
||||||
var datatype = typeof oldval == 'string' ? 'text' : 'arraybuffer';
|
projectWindows.updateFile(path, await alternateLocalFilesystem.getFileData(path));
|
||||||
projectWindows.updateFile(path, getWorkspaceFile(path, datatype));
|
console.log('updating file', path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function writeOutputROMFile() {
|
function writeOutputROMFile() {
|
||||||
if (isElectronWorkspace && current_output instanceof Uint8Array) {
|
if (isElectron && current_output instanceof Uint8Array) {
|
||||||
var prefix = getFilenamePrefix(getCurrentMainFilename());
|
var prefix = getFilenamePrefix(getCurrentMainFilename());
|
||||||
var suffix = (platform.getROMExtension && platform.getROMExtension(current_output))
|
var suffix = (platform.getROMExtension && platform.getROMExtension(current_output))
|
||||||
|| "-" + getBasePlatform(platform_id) + ".bin";
|
|| "-" + getBasePlatform(platform_id) + ".bin";
|
||||||
putWorkspaceFile(`bin/${prefix}${suffix}`, current_output);
|
alternateLocalFilesystem.setFileData(`bin/${prefix}${suffix}`, current_output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function highlightSearch(query: string) { // TODO: filename?
|
export function highlightSearch(query: string) { // TODO: filename?
|
||||||
|
Loading…
Reference in New Issue
Block a user