electron: removed workspaces, added sentry lib, electron-builder

This commit is contained in:
Steven Hugg 2021-07-10 14:28:02 -05:00
parent 10d04f9114
commit d31428aa42
8 changed files with 4489 additions and 646 deletions

View File

@ -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)

View File

@ -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);
}); });

View File

@ -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>

View File

@ -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);
});
*/ */

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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"
}
}
} }

View File

@ -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?