Compare commits

..

No commits in common. "69a1760a113039b7224a3d880a69cb08ffe82e37" and "c6221f1e30517c3d367c1b4b479309dc3882474b" have entirely different histories.

28 changed files with 97 additions and 691 deletions

View File

@ -57,7 +57,6 @@ AFRAME.registerComponent('helloworld-html', {
"icons": [ "icons": [
{ {
"src": "https://css.gg/browser.svg", "src": "https://css.gg/browser.svg",
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNCA4QzQuNTUyMjggOCA1IDcuNTUyMjggNSA3QzUgNi40NDc3MiA0LjU1MjI4IDYgNCA2QzMuNDQ3NzIgNiAzIDYuNDQ3NzIgMyA3QzMgNy41NTIyOCAzLjQ0NzcyIDggNCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNOCA3QzggNy41NTIyOCA3LjU1MjI4IDggNyA4QzYuNDQ3NzIgOCA2IDcuNTUyMjggNiA3QzYgNi40NDc3MiA2LjQ0NzcyIDYgNyA2QzcuNTUyMjggNiA4IDYuNDQ3NzIgOCA3WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNMTAgOEMxMC41NTIzIDggMTEgNy41NTIyOCAxMSA3QzExIDYuNDQ3NzIgMTAuNTUyMyA2IDEwIDZDOS40NDc3MSA2IDkgNi40NDc3MiA5IDdDOSA3LjU1MjI4IDkuNDQ3NzEgOCAxMCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMyAzQzEuMzQzMTUgMyAwIDQuMzQzMTUgMCA2VjE4QzAgMTkuNjU2OSAxLjM0MzE1IDIxIDMgMjFIMjFDMjIuNjU2OSAyMSAyNCAxOS42NTY5IDI0IDE4VjZDMjQgNC4zNDMxNSAyMi42NTY5IDMgMjEgM0gzWk0yMSA1SDNDMi40NDc3MiA1IDIgNS40NDc3MiAyIDZWOUgyMlY2QzIyIDUuNDQ3NzIgMjEuNTUyMyA1IDIxIDVaTTIgMThWMTFIMjJWMThDMjIgMTguNTUyMyAyMS41NTIzIDE5IDIxIDE5SDNDMi40NDc3MiAxOSAyIDE4LjU1MjMgMiAxOFoiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
"type": "image/svg+xml", "type": "image/svg+xml",
"sizes": "512x512" "sizes": "512x512"
} }

View File

@ -107,7 +107,6 @@ AFRAME.registerComponent('helloworld-htmlform', {
"icons": [ "icons": [
{ {
"src": "https://css.gg/browser.svg", "src": "https://css.gg/browser.svg",
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNCA4QzQuNTUyMjggOCA1IDcuNTUyMjggNSA3QzUgNi40NDc3MiA0LjU1MjI4IDYgNCA2QzMuNDQ3NzIgNiAzIDYuNDQ3NzIgMyA3QzMgNy41NTIyOCAzLjQ0NzcyIDggNCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNOCA3QzggNy41NTIyOCA3LjU1MjI4IDggNyA4QzYuNDQ3NzIgOCA2IDcuNTUyMjggNiA3QzYgNi40NDc3MiA2LjQ0NzcyIDYgNyA2QzcuNTUyMjggNiA4IDYuNDQ3NzIgOCA3WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNMTAgOEMxMC41NTIzIDggMTEgNy41NTIyOCAxMSA3QzExIDYuNDQ3NzIgMTAuNTUyMyA2IDEwIDZDOS40NDc3MSA2IDkgNi40NDc3MiA5IDdDOSA3LjU1MjI4IDkuNDQ3NzEgOCAxMCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMyAzQzEuMzQzMTUgMyAwIDQuMzQzMTUgMCA2VjE4QzAgMTkuNjU2OSAxLjM0MzE1IDIxIDMgMjFIMjFDMjIuNjU2OSAyMSAyNCAxOS42NTY5IDI0IDE4VjZDMjQgNC4zNDMxNSAyMi42NTY5IDMgMjEgM0gzWk0yMSA1SDNDMi40NDc3MiA1IDIgNS40NDc3MiAyIDZWOUgyMlY2QzIyIDUuNDQ3NzIgMjEuNTUyMyA1IDIxIDVaTTIgMThWMTFIMjJWMThDMjIgMTguNTUyMyAyMS41NTIzIDE5IDIxIDE5SDNDMi40NDc3MiAxOSAyIDE4LjU1MjMgMiAxOFoiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
"type": "image/svg+xml", "type": "image/svg+xml",
"sizes": "512x512" "sizes": "512x512"
} }

View File

@ -104,7 +104,6 @@ AFRAME.registerComponent('helloworld-iframe', {
"icons": [ "icons": [
{ {
"src": "https://css.gg/browse.svg", "src": "https://css.gg/browse.svg",
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNCA4QzQuNTUyMjggOCA1IDcuNTUyMjggNSA3QzUgNi40NDc3MiA0LjU1MjI4IDYgNCA2QzMuNDQ3NzIgNiAzIDYuNDQ3NzIgMyA3QzMgNy41NTIyOCAzLjQ0NzcyIDggNCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNOCA3QzggNy41NTIyOCA3LjU1MjI4IDggNyA4QzYuNDQ3NzIgOCA2IDcuNTUyMjggNiA3QzYgNi40NDc3MiA2LjQ0NzcyIDYgNyA2QzcuNTUyMjggNiA4IDYuNDQ3NzIgOCA3WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNMTAgOEMxMC41NTIzIDggMTEgNy41NTIyOCAxMSA3QzExIDYuNDQ3NzIgMTAuNTUyMyA2IDEwIDZDOS40NDc3MSA2IDkgNi40NDc3MiA5IDdDOSA3LjU1MjI4IDkuNDQ3NzEgOCAxMCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMyAzQzEuMzQzMTUgMyAwIDQuMzQzMTUgMCA2VjE4QzAgMTkuNjU2OSAxLjM0MzE1IDIxIDMgMjFIMjFDMjIuNjU2OSAyMSAyNCAxOS42NTY5IDI0IDE4VjZDMjQgNC4zNDMxNSAyMi42NTY5IDMgMjEgM0gzWk0yMSA1SDNDMi40NDc3MiA1IDIgNS40NDc3MiAyIDZWOUgyMlY2QzIyIDUuNDQ3NzIgMjEuNTUyMyA1IDIxIDVaTTIgMThWMTFIMjJWMThDMjIgMTguNTUyMyAyMS41NTIzIDE5IDIxIDE5SDNDMi40NDc3MiAxOSAyIDE4LjU1MjMgMiAxOFoiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
"type": "image/svg+xml", "type": "image/svg+xml",
"sizes": "512x512" "sizes": "512x512"
} }

View File

@ -86,7 +86,6 @@ AFRAME.registerComponent('helloworld-window', {
"icons": [ "icons": [
{ {
"src": "https://css.gg/browser.svg", "src": "https://css.gg/browser.svg",
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNCA4QzQuNTUyMjggOCA1IDcuNTUyMjggNSA3QzUgNi40NDc3MiA0LjU1MjI4IDYgNCA2QzMuNDQ3NzIgNiAzIDYuNDQ3NzIgMyA3QzMgNy41NTIyOCAzLjQ0NzcyIDggNCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNOCA3QzggNy41NTIyOCA3LjU1MjI4IDggNyA4QzYuNDQ3NzIgOCA2IDcuNTUyMjggNiA3QzYgNi40NDc3MiA2LjQ0NzcyIDYgNyA2QzcuNTUyMjggNiA4IDYuNDQ3NzIgOCA3WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNMTAgOEMxMC41NTIzIDggMTEgNy41NTIyOCAxMSA3QzExIDYuNDQ3NzIgMTAuNTUyMyA2IDEwIDZDOS40NDc3MSA2IDkgNi40NDc3MiA5IDdDOSA3LjU1MjI4IDkuNDQ3NzEgOCAxMCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMyAzQzEuMzQzMTUgMyAwIDQuMzQzMTUgMCA2VjE4QzAgMTkuNjU2OSAxLjM0MzE1IDIxIDMgMjFIMjFDMjIuNjU2OSAyMSAyNCAxOS42NTY5IDI0IDE4VjZDMjQgNC4zNDMxNSAyMi42NTY5IDMgMjEgM0gzWk0yMSA1SDNDMi40NDc3MiA1IDIgNS40NDc3MiAyIDZWOUgyMlY2QzIyIDUuNDQ3NzIgMjEuNTUyMyA1IDIxIDVaTTIgMThWMTFIMjJWMThDMjIgMTguNTUyMyAyMS41NTIzIDE5IDIxIDE5SDNDMi40NDc3MiAxOSAyIDE4LjU1MjMgMiAxOFoiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
"type": "image/svg+xml", "type": "image/svg+xml",
"sizes": "512x512" "sizes": "512x512"
} }

View File

@ -44,7 +44,6 @@ AFRAME.registerComponent('helloworld', {
"icons": [ "icons": [
{ {
"src": "https://css.gg/shape-hexagon.svg", "src": "https://css.gg/shape-hexagon.svg",
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNNiAxNS4yMzQ4TDEyIDE4LjU2ODFMMTggMTUuMjM0OFY4Ljc2NTIxTDEyIDUuNDMxODhMNiA4Ljc2NTIxVjE1LjIzNDhaTTEyIDJMMyA3VjE3TDEyIDIyTDIxIDE3VjdMMTIgMloiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
"type": "image/svg+xml", "type": "image/svg+xml",
"sizes": "512x512" "sizes": "512x512"
} }

View File

@ -3,7 +3,7 @@ AFRAME.registerComponent('isoterminal', {
iso: { type:"string", "default":"com/isoterminal/xrsh.iso" }, iso: { type:"string", "default":"com/isoterminal/xrsh.iso" },
cols: { type: 'number',"default": 120 }, cols: { type: 'number',"default": 120 },
rows: { type: 'number',"default": 30 }, rows: { type: 'number',"default": 30 },
padding:{ type: 'number',"default": 18 }, padding:{ type: 'number',"default": 15 },
transparent: { type:'boolean', "default":false } // need good gpu transparent: { type:'boolean', "default":false } // need good gpu
}, },
@ -13,8 +13,10 @@ AFRAME.registerComponent('isoterminal', {
requires:{ requires:{
'window': "com/window.js", 'window': "com/window.js",
xtermjs: "https://unpkg.com/@xterm/xterm@5.5.0/lib/xterm.js", winboxjs: "https://unpkg.com/winbox@0.2.82/dist/winbox.bundle.min.js", // deadsimple windows: https://nextapps-de.github.io/winbox
xtermcss: "https://unpkg.com/@xterm/xterm@5.5.0/css/xterm.css", winboxcss: "https://unpkg.com/winbox@0.2.82/dist/css/winbox.min.css", //
xtermcss: "https://unpkg.com/xterm@3.12.0/dist/xterm.css",
xtermjs: "https://unpkg.com/xterm@3.12.0/dist/xterm.js",
v86: "com/isoterminal/libv86.js" v86: "com/isoterminal/libv86.js"
//axterm: "https://unpkg.com/aframe-xterm-component/aframe-xterm-component.js" //axterm: "https://unpkg.com/aframe-xterm-component/aframe-xterm-component.js"
}, },
@ -22,12 +24,15 @@ AFRAME.registerComponent('isoterminal', {
dom: { dom: {
scale: 0.7, scale: 0.7,
events: ['click','keydown'], events: ['click','keydown'],
html: (me) => `<div class="isoterminal"></div>`, html: (me) => `<div class="isoterminal">
<div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
<canvas></canvas>
</div>`,
css: (me) => `.isoterminal{ css: (me) => `.isoterminal{
background:#000;
padding: ${me.com.data.padding}px; padding: ${me.com.data.padding}px;
width:100%; /*overflow:hidden; */
height:100%;
} }
.isoterminal *{ .isoterminal *{
white-space: pre; white-space: pre;
@ -37,14 +42,7 @@ AFRAME.registerComponent('isoterminal', {
display:inline; display:inline;
overflow: hidden; overflow: hidden;
} }
.wb-body:has(> .isoterminal){ background: #000; }
.isoterminal style{ display:none }
.wb-body:has(> .isoterminal){
background: #000c;
overflow:hidden;
}
.isoterminal div{ display:block; } .isoterminal div{ display:block; }
.isoterminal span{ display: inline } .isoterminal span{ display: inline }
@ -78,41 +76,12 @@ AFRAME.registerComponent('isoterminal', {
return uint8Array; return uint8Array;
}, },
runISO: function(dom,instance){ runISO: function(dom){
//var term = new Terminal()
//term.open(dom)
//term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')``
if( typeof Terminal == undefined ) throw 'xterm terminal not loaded'
// monkeypatch Xterm (which V86 initializes) so we can add our own constructor args
window._Terminal = window.Terminal
window.Terminal = function(opts){
const term = new window._Terminal({ ...opts,
cursorBlink:true,
onSelectionChange: function(e){
debugger
}
})
term.onSelectionChange( () => {
document.execCommand('copy')
term.select(0, 0, 0)
instance.setStatus('copied to clipboard')
})
return term
}
instance.setStatus = (msg) => {
const w = instance.winbox
w.titleBak = w.titleBak || w.title
instance.winbox.setTitle( `${w.titleBak} [${msg}]` )
}
var emulator = window.emulator = dom.emulator = new V86({ var emulator = window.emulator = dom.emulator = new V86({
wasm_path: "com/isoterminal/v86.wasm", wasm_path: "com/isoterminal/v86.wasm",
memory_size: 32 * 1024 * 1024, memory_size: 32 * 1024 * 1024,
vga_memory_size: 2 * 1024 * 1024, vga_memory_size: 2 * 1024 * 1024,
serial_container_xtermjs: dom, screen_container: dom, //this.canvas.parentElement,
//screen_container: dom, //this.canvas.parentElement,
bios: { bios: {
url: "com/isoterminal/bios/seabios.bin", url: "com/isoterminal/bios/seabios.bin",
}, },
@ -123,10 +92,11 @@ AFRAME.registerComponent('isoterminal', {
cdrom: { cdrom: {
url: this.data.iso, url: this.data.iso,
}, },
cmdline: "rw root=host9p rootfstype=9p rootflags=trans=virtio,cache=loose modules=virtio_pci tsc=reliable init_on_free=on", network_relay_url: "<UNUSED>",
bzimage:{ cmdline: "rw root=host9p rootfstype=9p rootflags=trans=virtio,cache=loose modules=virtio_pci tsc=reliable init_on_free=on init=/bin/date",
url: "com/isoterminal/images/buildroot-bzimage.bin" //bzimage:{
}, // url: "com/isoterminal/images/buildroot-bzimage.bin"
//},
//bzimage_initrd_from_filesystem: true, //bzimage_initrd_from_filesystem: true,
//filesystem: { //filesystem: {
// baseurl: "com/isoterminal/v86/images/alpine-rootfs-flat", // baseurl: "com/isoterminal/v86/images/alpine-rootfs-flat",
@ -138,195 +108,59 @@ AFRAME.registerComponent('isoterminal', {
autostart: true, autostart: true,
}); });
const loading = [ emulator.bus.register("emulator-started", () => {
'loading quantum bits and bytes', emulator.create_file("motd", this.toUint8Array(`
'preparing quantum flux capacitors',  ____ _____________ _________ ___ ___
'crunching peanuts and chakras',  \ \/ /\______ \/ _____// | \
'preparing parallel universe',  \ / | _/\_____ \/ ~ \
'loading quantum state fluctuations',  / \ | | \/ \ Y /
'preparing godmode',  /___/\ \ |____|_ /_______ /\___|_ /
'loading cat pawns and cuteness',  \_/ \/ \/ \/
'beaming up scotty',
'still faster than Windows update',
'loading a microlinux',
'figuring out meaning of life',
'Aligning your chakras now',
'Breathing in good vibes',
'Finding inner peace soon',
'Centering your Zen energy',
'Awakening third eye powers',
'Tuning into the universe',
'Balancing your cosmic karma',
'Stretching time and space',
'Recharging your soul battery',
'Transcending earthly limits'
]
let motd = "\n\r" `+ "\033[0m" ))
motd += " " + ' ____ _____________ _________ ___ ___ ' + "\n\r"
motd += " " + ' \\ \\/ /\\______ \\/ _____// | \\ ' + "\n\r"
motd += " " + ' \\ / | _/\\_____ \\/ ~ \\ ' + "\n\r"
motd += " " + ' / \\ | | \\/ \\ Y / ' + "\n\r"
motd += " " + ' /___/\\ \\ |____|_ /_______ /\\___|_ / ' + "\n\r"
motd += " " + ' \\_/ \\/ \\/ \\/ ' + "\n\r"
motd += " \n\r"
motd += `${loading[ Math.floor(Math.random()*1000) % loading.length-1 ]}, please wait..\n\r\n\r`
motd += "\033[0m"
const files = [
"com/isoterminal/mnt/js",
"com/isoterminal/mnt/jsh",
"com/isoterminal/mnt/confirm",
"com/isoterminal/mnt/prompt",
"com/isoterminal/mnt/alert",
"com/isoterminal/mnt/hook",
"com/isoterminal/mnt/xrsh",
"com/isoterminal/mnt/profile",
"com/isoterminal/mnt/profile.xrsh",
"com/isoterminal/mnt/profile.js",
"com/isoterminal/mnt/motd",
"com/isoterminal/mnt/v86pipe"
]
const redirectConsole = (handler) => {
const log = console.log;
const dir = console.dir;
const err = console.error;
const warn = console.warn;
console.log = (...args)=>{
const textArg = args[0];
handler(textArg+'\n');
log.apply(log, args);
};
console.error = (...args)=>{
const textArg = args[0].message?args[0].message:args[0];
handler( textArg+'\n', '\x1b[31merror\x1b[0m');
err.apply(log, args);
};
console.dir = (...args)=>{
const textArg = args[0].message?args[0].message:args[0];
handler( JSON.stringify(textArg,null,2)+'\n');
dir.apply(log, args);
};
console.warn = (...args)=>{
const textArg = args[0].message?args[0].message:args[0];
handler(textArg+'\n','\x1b[38;5;208mwarn\x1b[0m');
err.apply(log, args);
};
}
emulator.bus.register("emulator-started", async () => {
emulator.serial_adapter.term.element.querySelector('.xterm-viewport').style.background = 'transparent'
emulator.serial_adapter.term.clear()
emulator.serial_adapter.term.write(motd)
emulator.create_file("motd", this.toUint8Array(motd) )
emulator.create_file("js", this.toUint8Array(`#!/bin/sh emulator.create_file("js", this.toUint8Array(`#!/bin/sh
cat /mnt/motd cat /mnt/motd
cat > /dev/null cat > /dev/null
`)) `))
redirectConsole( (str,prefix) => {
if( emulator.log_to_tty ){
prefix = prefix ? prefix+' ' : ' '
str.trim().split("\n").map( (line) => {
emulator.serial_adapter.term.write( '\r\x1b[38;5;165m/dev/browser: \x1b[0m'+prefix+line+'\n' )
})
emulator.serial_adapter.term.write( '\r' )
}
emulator.create_file( "console", this.toUint8Array( str ) )
})
let p = files.map( (f) => fetch(f) )
Promise.all(p)
.then( (files) => {
files.map( (f) => {
f.arrayBuffer().then( (buf) => {
emulator.create_file( f.url.replace(/.*mnt\//,''), new Uint8Array(buf) )
})
})
})
//emulator.serial0_send('chmod +x /mnt/js') //emulator.serial0_send('chmod +x /mnt/js')
//emulator.serial0_send() //emulator.serial0_send()
let line = ''
let ready = false
emulator.add_listener("serial0-output-byte", async (byte) => {
var chr = String.fromCharCode(byte);
if(chr < " " && chr !== "\n" && chr !== "\t" || chr > "~")
{
return;
}
if(chr === "\n")
{
var new_line = line;
line = "";
}
else if(chr >= " " && chr <= "~")
{
line += chr;
}
//if(!ran_command && line.endsWith("~% "))
//{
// ran_command = true;
// emulator.serial0_send("chmod +x /mnt/test-i386\n");
// emulator.serial0_send("/mnt/test-i386 > /mnt/result\n");
// emulator.serial0_send("echo test fini''shed\n");
//}
//console.dir({line,new_line})
if( !ready && line.match(/^(\/ #|~%)/) ){
instance.dom.classList.remove('blink')
// set environment
let env = ['export BROWSER=1']
for ( let i in document.location ){
if( typeof document.location[i] == 'string' )
env.push( 'export '+String(i).toUpperCase()+'="'+document.location[i]+'"')
}
env.map( (e) => emulator.serial0_send(`echo '${e}' >> /mnt/profile\n`) )
let boot = `source /mnt/profile`
// exec hash as extra boot cmd
if( document.location.hash.length > 1 ){
boot += `&& cmd='${decodeURI(document.location.hash.substr(1))}' && $cmd`
}
emulator.serial0_send(boot+"\n")
instance.winbox.maximize()
emulator.serial_adapter.term.focus()
ready = true
//emulator.serial0_send("root\n")
//emulator.serial0_send("mv /mnt/js . && chmod +x js\n")
}
});
// unix to js device
emulator.add_listener("9p-write-end", async (opts) => {
const decoder = new TextDecoder('utf-8');
if ( opts[0] == 'js' ){
const buf = await emulator.read_file("dev/browser/js")
const script = decoder.decode(buf)
try{
let res = (new Function(`${script}`))()
if( res && typeof res != 'string' ) res = JSON.stringify(res,null,2)
}catch(e){
console.error(e)
}
}
})
// enable/disable logging file (echo 1 > mnt/console.tty)
emulator.add_listener("9p-write-end", async (opts) => {
const decoder = new TextDecoder('utf-8');
if ( opts[0] == 'console.tty' ){
const buf = await emulator.read_file("console.tty")
const val = decoder.decode(buf)
emulator.log_to_tty = ( String(val).trim() == '1')
}
})
}); });
let line = ''
emulator.add_listener("serial0-output-byte", async (byte) => {
var chr = String.fromCharCode(byte);
if(chr < " " && chr !== "\n" && chr !== "\t" || chr > "~")
{
return;
}
if(chr === "\n")
{
var new_line = line;
line = "";
}
else if(chr >= " " && chr <= "~")
{
line += chr;
}
//if(!ran_command && line.endsWith("~% "))
//{
// ran_command = true;
// emulator.serial0_send("chmod +x /mnt/test-i386\n");
// emulator.serial0_send("/mnt/test-i386 > /mnt/result\n");
// emulator.serial0_send("echo test fini''shed\n");
//}
console.dir({line,new_line})
if(new_line && new_line.includes("buildroot login:"))
{
emulator.serial0_send("root\n")
emulator.serial0_send("mv /mnt/js . && chmod +x js\n")
}
});
}, },
events:{ events:{
@ -345,6 +179,8 @@ AFRAME.registerComponent('isoterminal', {
launcher: async function(){ launcher: async function(){
if( this.instance ){ if( this.instance ){
const el = document.querySelector('.isoterminal') const el = document.querySelector('.isoterminal')
el.classList.add('blink')
setTimeout( () => el.classList.remove('blink'), 2000 )
return console.warn('TODO: allow multiple terminals (see v86 examples)') return console.warn('TODO: allow multiple terminals (see v86 examples)')
} }
@ -354,32 +190,32 @@ AFRAME.registerComponent('isoterminal', {
this.el.sceneEl.appendChild( instance ) this.el.sceneEl.appendChild( instance )
instance.addEventListener('DOMready', () => { instance.addEventListener('DOMready', () => {
this.runISO(instance.dom, instance) this.runISO(instance.dom)
instance.setAttribute("window", `title: ${this.data.iso}; uid: ${instance.uid}; attach: #overlay; dom: #${instance.dom.id}`) instance.setAttribute("window", `title: ${this.data.iso}; uid: ${instance.uid}; attach: #overlay; dom: #${instance.dom.id}`)
}) })
instance.addEventListener('window.oncreate', (e) => { instance.addEventListener('window.oncreate', (e) => {
instance.dom.classList.add('blink') instance.dom.classList.add('blink')
// resize after the dom content has been rendered & updated
setTimeout( () => {
let spans = [...instance.dom.querySelectorAll('span')]
instance.winbox.resize(
(spans[0].offsetWidth + (2*this.data.padding))+'px',
((spans.length * spans[0].offsetHeight) ) +'px'
)
},1200)
setTimeout( () => instance.dom.classList.remove('blink'), 5000 )
}) })
instance.addEventListener('window.onclose', (e) => { instance.addEventListener('window.onclose', (e) => {
if( !confirm('do you want to kill this virtual machine and all its processes?') ) e.halt = true if( !confirm('do you want to kill this virtual machine and all its processes?') ) e.halt = true
}) })
const resize = (w,h) => {
if( instance.dom.emulator && instance.dom.emulator.serial_adapter ){
setTimeout( () => {
this.autoResize(instance.dom.emulator.serial_adapter.term,instance,-5)
},500) // wait for resize anim
}
}
instance.addEventListener('window.onresize', resize )
instance.addEventListener('window.onmaximize', resize )
instance.setAttribute("dom", "") instance.setAttribute("dom", "")
instance.setAttribute("xd", "") // allows flipping between DOM/WebGL when toggling XD-button instance.setAttribute("xd", "") // allows flipping between DOM/WebGL when toggling XD-button
instance.setAttribute("visible", AFRAME.utils.XD() == '3D' ? 'true' : 'false' ) instance.setAttribute("visible", AFRAME.utils.XD() == '3D' ? 'true' : 'false' )
instance.setAttribute("position", AFRAME.utils.XD.getPositionInFrontOfCamera(0.5) ) instance.setAttribute("position", AFRAME.utils.XD.getPositionInFrontOfCamera(0.5) )
instance.setAttribute("grabbable","")
const focus = () => document.querySelector('canvas.a-canvas').focus() const focus = () => document.querySelector('canvas.a-canvas').focus()
instance.addEventListener('obbcollisionstarted', focus ) instance.addEventListener('obbcollisionstarted', focus )
@ -390,39 +226,6 @@ AFRAME.registerComponent('isoterminal', {
}, },
autoResize: function(term,instance,rowoffset){
if( !term.element ) return
const defaultScrollWidth = 24;
const MINIMUM_COLS = 2;
const MINIMUM_ROWS = 2;
const dims = term._core._renderService.dimensions;
const scrollbarWidth = (term.options.scrollback === 0
? 0
: (term.options.overviewRuler?.width || defaultScrollWidth ));
const parentElementStyle = window.getComputedStyle(instance.dom);
const parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height'));
const parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')));
const elementStyle = window.getComputedStyle(term.element);
const elementPadding = {
top: parseInt(elementStyle.getPropertyValue('padding-top')),
bottom: parseInt(elementStyle.getPropertyValue('padding-bottom')),
right: parseInt(elementStyle.getPropertyValue('padding-right')),
left: parseInt(elementStyle.getPropertyValue('padding-left'))
};
const elementPaddingVer = elementPadding.top + elementPadding.bottom;
const elementPaddingHor = elementPadding.right + elementPadding.left;
const availableHeight = parentElementHeight - elementPaddingVer;
const availableWidth = parentElementWidth - elementPaddingHor - scrollbarWidth;
const geometry = {
cols: Math.max(MINIMUM_COLS, Math.floor(availableWidth / dims.css.cell.width)),
rows: Math.max(MINIMUM_ROWS, Math.floor(availableHeight / dims.css.cell.height))
};
term.resize(geometry.cols, geometry.rows + (rowoffset||0) );
},
manifest: { // HTML5 manifest to identify app to xrsh manifest: { // HTML5 manifest to identify app to xrsh
"iso": "linux-x64-4.15.iso", "iso": "linux-x64-4.15.iso",
"short_name": "ISOTerm", "short_name": "ISOTerm",
@ -430,7 +233,6 @@ AFRAME.registerComponent('isoterminal', {
"icons": [ "icons": [
{ {
"src": "https://css.gg/terminal.svg", "src": "https://css.gg/terminal.svg",
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNS4wMzMzIDE0LjgyODRMNi40NDc1MSAxNi4yNDI2TDEwLjY5MDIgMTJMNi40NDc1MSA3Ljc1NzMzTDUuMDMzMyA5LjE3MTU1TDcuODYxNzIgMTJMNS4wMzMzIDE0LjgyODRaIgogICAgZmlsbD0iY3VycmVudENvbG9yIgogIC8+CiAgPHBhdGggZD0iTTE1IDE0SDExVjE2SDE1VjE0WiIgZmlsbD0iY3VycmVudENvbG9yIiAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMiAyQzAuODk1NDMxIDIgMCAyLjg5NTQzIDAgNFYyMEMwIDIxLjEwNDYgMC44OTU0MyAyMiAyIDIySDIyQzIzLjEwNDYgMjIgMjQgMjEuMTA0NiAyNCAyMFY0QzI0IDIuODk1NDMgMjMuMTA0NiAyIDIyIDJIMlpNMjIgNEgyTDIgMjBIMjJWNFoiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
"type": "image/svg+xml", "type": "image/svg+xml",
"sizes": "512x512" "sizes": "512x512"
} }

View File

@ -1,6 +0,0 @@
#!/bin/sh
title=$1
shift
msg="$*"
echo "$title $(printf "\033[0m")$msg"
hook alert $title "$msg"

View File

@ -1,4 +0,0 @@
#!/bin/sh
read -p "$(printf "\033[0m")[?] $1 [y/n] $(printf "\033[0m")" y
test $y = y && echo true && exit
echo false

View File

@ -1 +0,0 @@
alert("hello")

View File

@ -1,11 +0,0 @@
#!/bin/sh
test -z $1 && { echo "usage: hook <cmd_or_jsfunction> [args]"; exit 0; }
cmd=$1
shift
test -d ~/hook.d/$cmd && {
find ~/hook.d/$cmd/ -type f -executable | while read hook; do
{ $hook "$@" || true; } | awk '{ gsub(/\/root\/\//,"",$1); $1 = sprintf("%-40s", $1)} 1'
done
}

View File

@ -1,19 +0,0 @@
#!/bin/sh
test -z "$1" && { echo "Usage: js 'somefunction(1)'"; exit 0; }
test -n "$BROWSER" || { alert warning "/dev/browser not active (are you running outside of v86?)"; }
javascript="$*"
# if we are run as shebang, use the file as input
case "$1" in
*/*) javascript="args = String('$*').split(' '); $(cat $1 | tail +2)"
;;
esac
echo -n "$javascript" > /dev/browser/js
# should we use flock, an awesome way to make processes read/write the same file
# while preventing 1001 concurrency issues?
# attempt:
#
# flock /dev/browser/js -c "echo \"$javascript\" > /dev/browser/js"

View File

@ -1,42 +0,0 @@
#!/bin/sh
# usage: jsh <function> [arg1] [arg2] ...
#
# 'jsh prompt question answer' executes: js prompt('question','answer') )
to_js(){
printf "%s(" "$1"
shift
for arg in "$@"; do
case "$arg" in
(*[\.0-9]*)
printf '%s,' "$arg"
;;
(*)
printf '"%s",' "$arg"
;;
esac
done
printf ")\n"
}
# run argument as js
test -z "$1" || {
func=$(to_js "$@")
func=${func/,)/)}
js "$func"
hook "$@"
exit 0
}
# otherwise start repl
echo "jsh> type 'exit' or CTRL-C to quit"
echo "jsh> HINT: to run alert('foo') outside this REPL, run 'jsh alert foo'"
echo "jsh>"
while true; do
echo -n -e "\r$(printf "\033[0m")jsh> $(printf "\033[0m")"
read line
test "$line" = exit && exit
js "$line"
done

View File

@ -1,15 +0,0 @@
 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
 . . ____ _____________ ________. ._. ._. . . . . . . . .
 . . _\ \/ /\______ \/ _____// | \. . . . . . . .
 . . _ \ / | _/\_____ \/ ~ \ . . . . . . .
 _ _ / \ | | \/ \ Y / _ _ _ _ _ _ _
 . . /___/\ \ |____|_ /_______ /\___|_ /. . . . . . . .
 . . . . . .\_/. . . . \/ . . . .\/ . . _ \/ . . . . . . . .
 ▬ ▬ ▬ https://xrsh.isvery.ninja ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬
 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Open, local-first, hackable & selfcontained XR apps.
credits: all FOSS devs | @lvk@mastodon.online
copy.sh (v86) | @utopiah@mastodon.pirateparty.be

View File

@ -1,22 +0,0 @@
# install xrsh env
source /mnt/profile.xrsh
## forward not-found commands to javascript (via jsh)
command_not_found_handle(){
echo "$1 not found, did you mean $1(...) (javascript?)"
alert '[XRSH TIPS]'
alert 'js console: ' "type 'jsh'"
alert 'js shellfunction:' "type 'alias $1=\"jsh $1\"' to run '$1 yo' as $1('yo')"
alert 'js logging: ' "type 'echo 0 > /dev/browser/console.tty' to disable"
alert 'js capture log: ' "type 'tail -f /dev/browser/console'"
alert 'jsh<->sh hooks: ' "type 'chmod +x ~/hook.d/alert/* && alert helloworld'"
}
# source javascript functions
#js "$(cat /mnt/profile.js)"
resize
#clear
cat /mnt/motd
export PATH=$PATH:/mnt
export PS1="\nxrsh # \033[0m"

View File

@ -1,3 +0,0 @@
window.helloworld = function(){
alert("hello world")
}

View File

@ -1,47 +0,0 @@
#!/bin/sh
test -d /dev/browser || {
setup_binaries(){
for bin in /mnt/prompt /mnt/alert /mnt/confirm /mnt/hook /mnt/js* /mnt/v86pipe /mnt/xrsh; do
chmod +x $bin
ln -s $bin /bin/.
done
}
setup_browser_dev(){
mkdir -p /mnt/dev/browser
touch /mnt/dev/browser/js
touch /mnt/dev/browser/html
touch /mnt/console.tty
ln -s /mnt/dev/browser /dev/browser
# setup console goodies
ln -s /mnt/console.tty /dev/browser/console.tty # emulator.write_file() only writes to /mnt/. :(
echo 1 > /dev/browser/console.tty # should be in /proc, but v86 gives 'no such file or dir' when creating it there
v86pipe /mnt/console /dev/browser/console &
test -f /etc/profile && rm /etc/profile
ln -s /mnt/profile /etc/profile
}
setup_hook_dirs(){ # see /mnt/hook for usage
mkdir -p ~/hook.d/alert
mkdir -p ~/hook.d/confirm
mkdir -p ~/hook.d/prompt
echo -e "#!/bin/sh\necho hook.d/alert/yo: yo \$*" > ~/hook.d/alert/yo
echo -e "#!/bin/js\nalert(\"hook.d/alert/yo.js \"+args.slice(1).join(' '))" > ~/hook.d/alert/yo.js
echo -e "#!/usr/bin/lua\nprint(\"hook.d/alert/yo.lua: yo \" .. arg[1])" > ~/hook.d/alert/yo.lua
}
setup_network(){
test -n "$BROWSER" || return 0
mount -a
udhcpc 1>>/var/log/network.log 2>>/var/log/network.log &
echo 0 > /proc/sys/kernel/printk
}
setup_binaries
setup_browser_dev
setup_hook_dirs
}

View File

@ -1,3 +0,0 @@
#!/bin/sh
read -p "$(printf "\033[0m")[?] $1: $(printf "\033[0m")" answer
echo "$answer"

View File

@ -1,26 +0,0 @@
#!/bin/awk -f
BEGIN {
for (i = 1; i < ARGC; i++) {
options[i] = ARGV[i]
}
ARGC = 0
selected = 1
n = length(options)
while (1) {
printf "\r "
for (i = 1; i <= n; i++) {
if (i == selected)
printf "\033[44m%s\033[0m ", options[i]
else
printf "%s ", options[i]
}
if (c == 0) {
getline dir < "/dev/stdin"
print dir
if (dir == "up" && selected > 1) selected--
if (dir == "down" && selected < n) selected++
}
}
}

View File

@ -1,30 +0,0 @@
#!/bin/sh
#
# this daemon allows 'tail -f' on v86 files (which don't persist inode when updated
# via javascript)
# more info see: https://github.com/copy/v86/issues/1140
#
# Hopefully as V86 (or my understanding of it) matures, this will be no longer needed
test -z $2 && { echo "usage: v86pipe <logfile> <namedpipe>"; exit 0; }
# Start reading from the last line in the log file
last_size=0
LOG_FILE=$1
LOG_PIPE=$2
test -f $LOG_FILE || touch $LOG_FILE
test -p $LOG_PIPE || mkfifo $LOG_PIPE
while true; do
# Get the current size of the file using wc -c (count bytes)
current_size=$(wc -c < $LOG_FILE)
test $current_size = $last_size || {
cat $LOG_FILE > $LOG_PIPE
truncate -s 0 $LOG_FILE
}
last_size=$current_size
# Sleep for a moment to avoid excessive CPU usage
sleep 0.2
done

View File

@ -1,62 +0,0 @@
#!/bin/sh
#
# a minimalistic terminal muxer
# Save the original stdout and stderr file descriptors for later restoration
exec 3>&1 4>&2
# Function to check if a session is already running on the given VT
is_session_running() {
vt_number=$1
# Check if any process is running on /dev/tty<vt_number>
fuser /dev/tty"$vt_number" >/dev/null 2>&1
return $?
}
# Function to mute the output of a session
mute_session() {
vt_number=$1
if is_session_running "$vt_number"; then
# Redirect stdout and stderr of the session to /dev/null
exec > /dev/null 2>&1
fi
}
# Function to unmute the current session (restore stdout and stderr)
unmute_session() {
exec 1>&3 2>&4 # Restore stdout and stderr from file descriptors 3 and 4
}
# Function to start a new session if not already running
start_or_switch_session() {
vt_number=$1
# Mute all other sessions except the one we're switching to
for vt in $(seq 1 12); do # Assuming you have up to 12 VTs, adjust as needed
if [ "$vt" != "$vt_number" ]; then
mute_session "$vt"
fi
done
if is_session_running "$vt_number"; then
echo "Switching to existing session on VT$vt_number"
unmute_session # Unmute the session we're switching to
chvt "$vt_number"
else
echo "Starting a new session on VT$vt_number"
openvt -c "$vt_number" -- /bin/sh &
sleep 1 # Give the session a moment to start
unmute_session # Unmute the new session
chvt "$vt_number"
fi
}
# Ensure a session number is provided
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <session_number>"
exit 1
fi
# Start or switch to the session
start_or_switch_session $1

View File

@ -47,7 +47,6 @@ AFRAME.registerComponent('launcher-optional', {
"icons": [ "icons": [
{ {
"src": "https://css.gg/add-r.svg", "src": "https://css.gg/add-r.svg",
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNMTIgNkMxMi41NTIzIDYgMTMgNi40NDc3MiAxMyA3VjExSDE3QzE3LjU1MjMgMTEgMTggMTEuNDQ3NyAxOCAxMkMxOCAxMi41NTIzIDE3LjU1MjMgMTMgMTcgMTNIMTNWMTdDMTMgMTcuNTUyMyAxMi41NTIzIDE4IDEyIDE4QzExLjQ0NzcgMTggMTEgMTcuNTUyMyAxMSAxN1YxM0g3QzYuNDQ3NzIgMTMgNiAxMi41NTIzIDYgMTJDNiAxMS40NDc3IDYuNDQ3NzIgMTEgNyAxMUgxMVY3QzExIDYuNDQ3NzIgMTEuNDQ3NyA2IDEyIDZaIgogICAgZmlsbD0iY3VycmVudENvbG9yIgogIC8+CiAgPHBhdGgKICAgIGZpbGwtcnVsZT0iZXZlbm9kZCIKICAgIGNsaXAtcnVsZT0iZXZlbm9kZCIKICAgIGQ9Ik01IDIyQzMuMzQzMTUgMjIgMiAyMC42NTY5IDIgMTlWNUMyIDMuMzQzMTUgMy4zNDMxNSAyIDUgMkgxOUMyMC42NTY5IDIgMjIgMy4zNDMxNSAyMiA1VjE5QzIyIDIwLjY1NjkgMjAuNjU2OSAyMiAxOSAyMkg1Wk00IDE5QzQgMTkuNTUyMyA0LjQ0NzcyIDIwIDUgMjBIMTlDMTkuNTUyMyAyMCAyMCAxOS41NTIzIDIwIDE5VjVDMjAgNC40NDc3MiAxOS41NTIzIDQgMTkgNEg1QzQuNDQ3NzIgNCA0IDQuNDQ3NzIgNCA1VjE5WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgo8L3N2Zz4K",
"type": "image/svg+xml", "type": "image/svg+xml",
"sizes": "512x512" "sizes": "512x512"
} }

View File

@ -63,10 +63,7 @@ AFRAME.registerComponent('launcher', {
if( this.data.attach ){ if( this.data.attach ){
this.el.object3D.visible = false this.el.object3D.visible = false
if( this.isHand(this.data.attach) ){ if( this.isHand(this.data.attach) ){
this.data.attach.addEventListener('model-loaded', () => { this.data.attach.addEventListener('model-loaded', () => this.attachMenu() )
this.ready = true
this.attachMenu()
})
// add button // add button
this.menubutton = this.createMenuButton() this.menubutton = this.createMenuButton()
this.menubutton.object3D.visible = false this.menubutton.object3D.visible = false
@ -283,7 +280,7 @@ AFRAME.registerComponent('launcher', {
}, },
tick: function(){ tick: function(){
if( this.ready && this.data.open ){ if( this.data.open ){
let indexTipPosition = document.querySelector('#right-hand[hand-tracking-controls]').components['hand-tracking-controls'].indexTipPosition let indexTipPosition = document.querySelector('#right-hand[hand-tracking-controls]').components['hand-tracking-controls'].indexTipPosition
this.el.object3D.getWorldPosition(this.worldPosition) this.el.object3D.getWorldPosition(this.worldPosition)
const lookingAtPalm = this.data.attach.components['hand-tracking-controls'].wristObject3D.rotation.z > 2.0 const lookingAtPalm = this.data.attach.components['hand-tracking-controls'].wristObject3D.rotation.z > 2.0

View File

@ -34,8 +34,7 @@ AFRAME.utils.require = function(arr_or_obj,opts){
if( AFRAME.required[id] ) return // already loaded before if( AFRAME.required[id] ) return // already loaded before
AFRAME.required[id] = true AFRAME.required[id] = true
if( !document.body.querySelector(`script#${id}`) && if( !document.head.querySelector(`script#${id}`) ){
!document.body.querySelector(`link#${id}`) ){
let {type} = parseURI(package) let {type} = parseURI(package)
let p = new Promise( (resolve,reject) => { let p = new Promise( (resolve,reject) => {
switch(type){ switch(type){
@ -44,15 +43,14 @@ AFRAME.utils.require = function(arr_or_obj,opts){
script.onload = () => setTimeout( () => resolve(id), 50 ) script.onload = () => setTimeout( () => resolve(id), 50 )
script.onerror = (e) => reject(e) script.onerror = (e) => reject(e)
script.src = package script.src = package
document.body.appendChild(script) document.head.appendChild(script)
break; break;
case "css": let link = document.createElement("link") case "css": let link = document.createElement("link")
link.id = id link.id = id
link.href = package link.href = package
link.rel = 'stylesheet' link.rel = 'stylesheet'
link.onload = () => setTimeout( () => resolve(id), 50 ) document.head.appendChild(link)
link.onerror = (e) => reject(e) resolve(id)
document.body.appendChild(link)
break; break;
} }
}) })

View File

@ -3,13 +3,10 @@ AFRAME.registerComponent('save', {
foo: { type:"string"} foo: { type:"string"}
}, },
init: async function () { init: function () {
this.el.object3D.visible = false this.el.object3D.visible = false
await AFRAME.utils.require(this.dependencies)
},
dependencies:{ //this.el.innerHTML = ` `
'xhook': 'https://jpillora.com/xhook/dist/xhook.min.js'
}, },
events:{ events:{
@ -20,28 +17,6 @@ AFRAME.registerComponent('save', {
}, },
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;
}
},
save: function(){ save: function(){
let l = document.querySelector("#left-hand") let l = document.querySelector("#left-hand")
let r = document.querySelector("#right-hand") let r = document.querySelector("#right-hand")
@ -58,8 +33,11 @@ AFRAME.registerComponent('save', {
save_state: async function(){ save_state: async function(){
if( window.emulator ){ if( window.emulator ){
let binaryString = ''; let binaryString = '';
const state = await emulator.save_state() //restore_state(state); const state = await emulator.restore_state(state);
//console.log(this.convert.arrayBufferToBase64(state)) uint8Array.forEach(byte => binaryString += String.fromCharCode(byte) );
let b64data = btoa(binaryString);
console.log(b64data)
} }
}, },
@ -75,8 +53,8 @@ AFRAME.registerComponent('save', {
inlineFiles: function(){ inlineFiles: function(){
let p = [] let p = []
let tags = [ ...document.querySelectorAll('script[src]'), let tags = [ ...document.querySelectorAll('script'),
...document.querySelectorAll('link[href]') ...document.querySelectorAll('link')
] ]
tags.map( (el) => { tags.map( (el) => {
let remoteFile = el.src || el.href let remoteFile = el.src || el.href
@ -89,12 +67,12 @@ AFRAME.registerComponent('save', {
case 'LINK': el2 = document.createElement('style') case 'LINK': el2 = document.createElement('style')
el2.setAttribute("type","text/css") el2.setAttribute("type","text/css")
el2.setAttribute("_href", el.href ) el2.setAttribute("_href", el.href )
el2.innerHTML = `${text}` el2.innerHTML = text
el.parentNode.appendChild(el2) el.parentNode.appendChild(el2)
el.remove() el.remove()
break; break;
case 'SCRIPT': el.innerHTML = `${text.replace(/<\//g,'&lt;/')}` case 'SCRIPT': el.innerHTML = text
el.setAttribute("_src", el.src) el.setAttribute("_src", el.src)
el.removeAttribute("src") el.removeAttribute("src")
break; break;
@ -114,7 +92,6 @@ AFRAME.registerComponent('save', {
"icons": [ "icons": [
{ {
"src": "https://css.gg/arrow-down-r.svg", "src": "https://css.gg/arrow-down-r.svg",
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNMTQuODI4NCAxMi4wMjU5TDE2LjI0MjYgMTMuNDQwMkwxMiAxNy42ODI4TDcuNzU3MzMgMTMuNDQwMkw5LjE3MTU1IDEyLjAyNTlMMTEgMTMuODU0NFY2LjMxNzI0SDEzVjEzLjg1NDRMMTQuODI4NCAxMi4wMjU5WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMSA1QzEgMi43OTA4NiAyLjc5MDg2IDEgNSAxSDE5QzIxLjIwOTEgMSAyMyAyLjc5MDg2IDIzIDVWMTlDMjMgMjEuMjA5MSAyMS4yMDkxIDIzIDE5IDIzSDVDMi43OTA4NiAyMyAxIDIxLjIwOTEgMSAxOVY1Wk01IDNIMTlDMjAuMTA0NiAzIDIxIDMuODk1NDMgMjEgNVYxOUMyMSAyMC4xMDQ2IDIwLjEwNDYgMjEgMTkgMjFINUMzLjg5NTQzIDIxIDMgMjAuMTA0NiAzIDE5VjVDMyAzLjg5NTQzIDMuODk1NDMgMyA1IDNaIgogICAgZmlsbD0iY3VycmVudENvbG9yIgogIC8+Cjwvc3ZnPg==",
"type": "image/svg+xml", "type": "image/svg+xml",
"sizes": "512x512" "sizes": "512x512"
} }

View File

@ -1,64 +0,0 @@
AFRAME.registerComponent('selfcontainer', {
schema: {
foo: { type:"string"}
},
init: async function () {
this.installProxyServer()
},
events:{ },
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;
}
},
installProxyServer: function(){
if( !window.store ) window.store = {}
// selfcontain every webrequest to store (and serve if stored)
let curry = function(me){
return function(request, response, cb){
let data = request ? window.store[ request.url ] || false : false
if( data ){ // return inline version
console.log('selfcontained cache: '+request.url)
let res = new Response()
res[ data.binary ? 'data' : 'text' ] = data.binary ? () => me.convert.base64ToArrayBuffer(data.text) : data.text
cb(res)
}else{
if( response.text ){
data = {text: response.text}
}else{
data = {binary: true, text: me.convert.arrayBufferToBase64(response.data)}
}
window.store[ request.url ] = data
let $store = document.querySelector('template#store')
if( $store ) $store.remove()
document.head.innerHTML += `\n<`+`template id="store">\nwindow.store = ${JSON.stringify(window.store,null,2)}\n`+`<`+`/template>`
cb(response);
}
}
}
xhook.after( curry(this) )
}
});

View File

@ -2,7 +2,7 @@ AFRAME.registerComponent('window', {
schema:{ schema:{
title: {type:'string',"default":"title"}, title: {type:'string',"default":"title"},
width: {type:'string'}, // wrap width: {type:'string'}, // wrap
height: {type:'string',"default":'260px'}, height: {type:'string',"default":'50px'},
uid: {type:'string'}, uid: {type:'string'},
attach: {type:'selector'}, attach: {type:'selector'},
dom: {type:'selector'}, dom: {type:'selector'},
@ -13,8 +13,6 @@ AFRAME.registerComponent('window', {
dependencies:{ dependencies:{
dom: "com/dom.js", dom: "com/dom.js",
html: "https://unpkg.com/aframe-htmlmesh@2.1.0/build/aframe-html.js", // html to AFRAME html: "https://unpkg.com/aframe-htmlmesh@2.1.0/build/aframe-html.js", // html to AFRAME
winboxjs: "https://unpkg.com/winbox@0.2.82/dist/winbox.bundle.min.js", // deadsimple windows: https://nextapps-de.github.io/winbox
//winboxcss: "https://unpkg.com/winbox@0.2.82/dist/css/winbox.min.css", // main theme
}, },
init: function(){ init: function(){
@ -34,17 +32,13 @@ AFRAME.registerComponent('window', {
id: this.data.uid || String(Math.random()).substr(4), // important hint for html-mesh id: this.data.uid || String(Math.random()).substr(4), // important hint for html-mesh
root: this.data.attach || document.body, root: this.data.attach || document.body,
mount: this.data.dom, mount: this.data.dom,
onresize: () => this.el.emit('window.onresize',{}),
onmaximize: () => this.el.emit('window.onmaximize',{}),
oncreate: () => { oncreate: () => {
this.el.emit('window.oncreate',{}) this.el.emit('window.oncreate',{})
// resize after the dom content has been rendered & updated // resize after the dom content has been rendered & updated
setTimeout( () => { setTimeout( () => {
winbox.resize( this.el.dom.offsetWidth+'px', this.el.dom.offsetHeight+'px' ) winbox.resize( this.el.dom.offsetWidth+'px', this.el.dom.offsetHeight+'px' )
setTimeout( () => this.el.setAttribute("html",`html:#${this.data.uid}; cursor:#cursor`), 1000) setTimeout( () => this.el.setAttribute("html",`html:#${this.data.uid}; cursor:#cursor`), 1000)
// hint grabbable's obb-collider to track the window-object this.el.setAttribute("grabbable","")
this.el.components['obb-collider'].data.trackedObject3D = 'components.html.el.object3D.children.0'
this.el.components['obb-collider'].update()
},1000) },1000)
}, },
onclose: () => { onclose: () => {
@ -52,15 +46,14 @@ AFRAME.registerComponent('window', {
this.el.emit('window.onclose',e) this.el.emit('window.onclose',e)
if( e.halt ) return true if( e.halt ) return true
this.data.dom.style.display = 'none'; this.data.dom.style.display = 'none';
this.data.dom.parentElement.remove()
debugger
this.el.parentElement.remove( this.el )
return false return false
}, },
}); });
this.data.dom.style.display = '' // show this.data.dom.style.display = '' // show
this.el.setAttribute("grabbable","") // hint grabbable's obb-collider to track the window-object
this.el.components['obb-collider'].data.trackedObject3D = 'components.html.el.object3D.children.0'
this.el.components['obb-collider'].update()
} }
}) })