finetuned autorestore and codemirror
/ test (push) Successful in 4s Details

This commit is contained in:
Leon van Kammen 2024-09-23 14:58:48 +00:00
parent f75f34d6a6
commit 8369dde488
9 changed files with 103 additions and 70 deletions

View File

@ -2,11 +2,17 @@ if( AFRAME.components.codemirror ) delete AFRAME.components.codemirror
AFRAME.registerComponent('codemirror', {
schema: {
foo: { type:"string"}
file: { type:"string"},
term: { type:"selector", default: "[isoterminal]" },
},
init: function () {
this.el.object3D.visible = false
if( !this.data.term || !this.data.term.components ) throw 'codemirror cannot get isoterminal'
if( this.data.file && this.data.file[0] != '/'){
this.data.file = "root/"+this.data.file
}
this.isoterminal = this.data.term.components.isoterminal.isoterminal
//this.el.innerHTML = ` `
this.requireAll()
},
@ -17,10 +23,7 @@ AFRAME.registerComponent('codemirror', {
},
requires:{
window: "com/window.js",
codemirror: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.1/codemirror.js",
codemirrorcss: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.35.0/codemirror.css",
cmtheme: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.35.0/theme/shadowfox.css"
window: "com/window.js"
},
dom: {
@ -49,28 +52,54 @@ AFRAME.registerComponent('codemirror', {
`
},
createEditor: function(value){
this.el.setAttribute("window", `title: codemirror; uid: ${this.el.dom.id}; attach: #overlay; dom: #${this.el.dom.id};`)
this.editor = CodeMirror( this.el.dom, {
value,
mode: "htmlmixed",
lineNumbers: true,
styleActiveLine: true,
matchBrackets: true,
Tab: "indentMore",
defaultTab: function(cm) {
if (cm.somethingSelected()) cm.indentSelection("add");
else cm.replaceSelection(" ", "end");
}
})
this.editor.setOption("theme", "shadowfox")
this.editor.updateFile = AFRAME.utils.throttleLeadingAndTrailing( (file,str) => {
this.updateFile(file,str),
2000
})
this.editor.on('change', (instance,changeObj) => {
this.editor.updateFile( this.data.file, instance.getValue() )
})
setTimeout( () => {
this.el.setAttribute("html-as-texture-in-xr", `domid: #${this.el.dom.id}`) // only show aframe-html in xr
},1500)
},
updateFile: async function(file,str){
// we don't do via shellcmd: isoterminal.exec(`echo '${str}' > ${file}`,1)
// as it would require all kindof ugly stringescaping
console.log("updating "+file)
await this.isoterminal.emulator.fs9p.update_file( file, str)
},
events:{
// component events
DOMready: function(e){
console.log(`title: codemirror; uid: ${this.el.dom.id}; attach: #overlay; dom: #${this.el.dom.id};`)
this.el.setAttribute("window", `title: codemirror; uid: ${this.el.dom.id}; attach: #overlay; dom: #${this.el.dom.id};`)
this.editor = CodeMirror( this.el.dom, {
value: "function myScript(){return 100;}\n",
mode: "javascript",
lineNumbers: true,
styleActiveLine: true,
matchBrackets: true,
Tab: "indentMore",
defaultTab: function(cm) {
if (cm.somethingSelected()) cm.indentSelection("add");
else cm.replaceSelection(" ", "end");
}
this.isoterminal.emulator.read_file( this.data.file )
.then( this.isoterminal.convert.Uint8ArrayToString )
.then( (str) => {
this.createEditor( str )
})
.catch( (e) => {
console.log("error opening "+this.data.file+", creating new one")
this.createEditor("")
})
this.editor.setOption("theme", "shadowfox")
setTimeout( () => {
this.el.setAttribute("html-as-texture-in-xr", `domid: #${this.el.dom.id}`) // only show aframe-html in xr
},1500)
},
},

View File

@ -40,7 +40,7 @@ if( typeof AFRAME != 'undefined '){
minimized: { type: 'boolean',"default":false},
maximized: { type: 'boolean',"default":true},
transparent: { type:'boolean', "default":false }, // need good gpu
xterm: { type: 'boolean', "default":true }, // use xterm.js (slower)
xterm: { type: 'boolean', "default":true }, // use xterm.js? (=slower)
memory: { type: 'number', "default":48 } // VM memory (in MB)
},

View File

@ -8,16 +8,17 @@ ISOTerminal.addEventListener('emulator-started', function(){
if(p.id === -1)
{
return Promise.resolve(null);
return emulator.create_file(file,data)
}
const inode = this.GetInode(p.id);
const buf = typeof data == 'string' ? isoterminal.toUint8Array(data) : data
const buf = typeof data == 'string' ? isoterminal.convert.toUint8Array(data) : data
await this.Write(p.id,0, buf.length, buf )
// update inode
inode.size = buf.length
const now = Math.round(Date.now() / 1000);
inode.atime = inode.mtime = now;
isoterminal.exec(`touch ${file}`) // update inode
return new Promise( (resolve,reject) => resolve(buf) )
}
@ -32,7 +33,7 @@ ISOTerminal.addEventListener('emulator-started', function(){
}
const inode = this.GetInode(p.id);
const buf = typeof data == 'string' ? isoterminal.toUint8Array(data) : data
const buf = typeof data == 'string' ? isoterminal.convert.toUint8Array(data) : data
await this.Write(p.id, inode.size, buf.length, buf )
// update inode
inode.size = inode.size + buf.length

View File

@ -2,28 +2,6 @@ ISOTerminal.addEventListener('emulator-started', function(e){
this.autorestore(e)
})
ISOTerminal.prototype.convert = {
arrayBufferToBase64: function(buffer){
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) binary += String.fromCharCode(bytes[i]);
return window.btoa(binary);
},
base64ToArrayBuffer: function(base64) {
const binaryString = window.atob(base64);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
}
ISOTerminal.prototype.autorestore = async function(e){
localforage.setDriver([
@ -32,7 +10,7 @@ ISOTerminal.prototype.autorestore = async function(e){
localforage.LOCALSTORAGE
]).then( () => {
localforage.getItem("state", (err,stateBase64) => {
localforage.getItem("state", async (err,stateBase64) => {
if( !err && confirm('continue last session?') ){
this.noboot = true // see feat/boot.js
state = this.convert.base64ToArrayBuffer( stateBase64 )
@ -40,7 +18,19 @@ ISOTerminal.prototype.autorestore = async function(e){
this.emit('postReady',e)
setTimeout( () => {
this.emit('ready',e)
this.send("alert last session restored\n")
// press CTRL+a l (=gnu screen redisplay)
setTimeout( () => this.send("l\n"),400 )
// reload index.js
this.emulator.read_file("root/index.js")
.then( this.convert.Uint8ArrayToString )
.then( this.runJavascript )
.catch( console.error )
// reload index.html
this.emulator.read_file("root/index.html")
.then( this.convert.Uint8ArrayToString )
.then( this.runHTML )
.catch( console.error )
}, 500 )
}
})
@ -50,6 +40,13 @@ ISOTerminal.prototype.autorestore = async function(e){
console.log( String(this.convert.arrayBufferToBase64(state)).substr(0,5) )
localforage.setItem("state", this.convert.arrayBufferToBase64(state) )
}
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = "Sure you want to leave?\nTIP: enter 'save' to continue this session later";
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Webkit, Safari, Chrome
});
})
}

View File

@ -9,7 +9,7 @@ ISOTerminal.prototype.boot = async function(e){
if( typeof document.location[i] == 'string' )
env.push( 'export '+String(i).toUpperCase()+'="'+document.location[i]+'"')
}
await this.emulator.create_file("profile.browser", this.toUint8Array( env.join('\n') ) )
await this.emulator.create_file("profile.browser", this.convert.toUint8Array( env.join('\n') ) )
if( this.serial_input == 0 ){
if( !this.noboot ){

View File

@ -10,14 +10,7 @@ ISOTerminal.addEventListener('init', function(){
const decoder = new TextDecoder('utf-8');
const html = decoder.decode(buf)
try{
let $scene = document.querySelector("a-scene")
let $root = document.querySelector("a-entity#root")
if( !$root ){
$root = document.createElement("a-entity")
$root.id = "root"
$scene.appendChild($root)
}
$root.innerHTML = html
this.runHTML(html)
}catch(e){
console.error(e)
}
@ -27,3 +20,13 @@ ISOTerminal.addEventListener('init', function(){
})
ISOTerminal.prototype.runHTML = function(html){
let $scene = document.querySelector("a-scene")
let $root = document.querySelector("a-entity#root")
if( !$root ){
$root = document.createElement("a-entity")
$root.id = "root"
$scene.appendChild($root)
}
$root.innerHTML = html
}

View File

@ -10,13 +10,7 @@ ISOTerminal.addEventListener('init', function(){
const decoder = new TextDecoder('utf-8');
const js = decoder.decode(buf)
try{
let $root = document.querySelector("script#root")
if( !$root ){
$root = document.createElement("script")
$root.id = "root"
document.body.appendChild($root)
}
$root.innerHTML = js
this.runJavascript(js)
}catch(e){
console.error(e)
}
@ -26,3 +20,13 @@ ISOTerminal.addEventListener('init', function(){
})
ISOTerminal.prototype.runJavascript = function(js){
let $root = document.querySelector("script#root")
if( !$root ){
$root = document.createElement("script")
$root.id = "root"
document.body.appendChild($root)
}
$root.innerHTML = js
}

View File

@ -7,8 +7,7 @@ ISOTerminal.addEventListener('init', function(){
// unix to js device
this.readFromPipe( '/mnt/js', async (data) => {
const buf = await emulator.read_file("js")
const decoder = new TextDecoder('utf-8');
const script = decoder.decode(buf)
const script = this.convert.Uint8ArrayToString(buf)
let PID="?"
try{
if( script.match(/^PID/) ){
@ -18,7 +17,7 @@ ISOTerminal.addEventListener('init', function(){
if( res && typeof res != 'string' ) res = JSON.stringify(res,null,2)
// write output to 9p with PID as filename
// *FIXME* not flexible / robust
emulator.create_file(PID, this.toUint8Array(res) )
emulator.create_file(PID, this.convert.toUint8Array(res) )
}catch(e){
console.error(e)
}

View File

@ -54,8 +54,8 @@ AFRAME.registerComponent('window', {
this.el.emit('window.onclose',e)
if( e.halt ) return true
this.data.dom.style.display = 'none';
if( this.el.parentNode ) this.el.remove() //parentElement.remove( this.el )
this.data.dom.parentElement.remove()
this.el.parentElement.remove( this.el )
return false
},
});