Compare commits
No commits in common. "69a1760a113039b7224a3d880a69cb08ffe82e37" and "c6221f1e30517c3d367c1b4b479309dc3882474b" have entirely different histories.
69a1760a11
...
c6221f1e30
|
@ -57,7 +57,6 @@ AFRAME.registerComponent('helloworld-html', {
|
|||
"icons": [
|
||||
{
|
||||
"src": "https://css.gg/browser.svg",
|
||||
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNCA4QzQuNTUyMjggOCA1IDcuNTUyMjggNSA3QzUgNi40NDc3MiA0LjU1MjI4IDYgNCA2QzMuNDQ3NzIgNiAzIDYuNDQ3NzIgMyA3QzMgNy41NTIyOCAzLjQ0NzcyIDggNCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNOCA3QzggNy41NTIyOCA3LjU1MjI4IDggNyA4QzYuNDQ3NzIgOCA2IDcuNTUyMjggNiA3QzYgNi40NDc3MiA2LjQ0NzcyIDYgNyA2QzcuNTUyMjggNiA4IDYuNDQ3NzIgOCA3WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNMTAgOEMxMC41NTIzIDggMTEgNy41NTIyOCAxMSA3QzExIDYuNDQ3NzIgMTAuNTUyMyA2IDEwIDZDOS40NDc3MSA2IDkgNi40NDc3MiA5IDdDOSA3LjU1MjI4IDkuNDQ3NzEgOCAxMCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMyAzQzEuMzQzMTUgMyAwIDQuMzQzMTUgMCA2VjE4QzAgMTkuNjU2OSAxLjM0MzE1IDIxIDMgMjFIMjFDMjIuNjU2OSAyMSAyNCAxOS42NTY5IDI0IDE4VjZDMjQgNC4zNDMxNSAyMi42NTY5IDMgMjEgM0gzWk0yMSA1SDNDMi40NDc3MiA1IDIgNS40NDc3MiAyIDZWOUgyMlY2QzIyIDUuNDQ3NzIgMjEuNTUyMyA1IDIxIDVaTTIgMThWMTFIMjJWMThDMjIgMTguNTUyMyAyMS41NTIzIDE5IDIxIDE5SDNDMi40NDc3MiAxOSAyIDE4LjU1MjMgMiAxOFoiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
|
||||
"type": "image/svg+xml",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
|
|
|
@ -107,7 +107,6 @@ AFRAME.registerComponent('helloworld-htmlform', {
|
|||
"icons": [
|
||||
{
|
||||
"src": "https://css.gg/browser.svg",
|
||||
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNCA4QzQuNTUyMjggOCA1IDcuNTUyMjggNSA3QzUgNi40NDc3MiA0LjU1MjI4IDYgNCA2QzMuNDQ3NzIgNiAzIDYuNDQ3NzIgMyA3QzMgNy41NTIyOCAzLjQ0NzcyIDggNCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNOCA3QzggNy41NTIyOCA3LjU1MjI4IDggNyA4QzYuNDQ3NzIgOCA2IDcuNTUyMjggNiA3QzYgNi40NDc3MiA2LjQ0NzcyIDYgNyA2QzcuNTUyMjggNiA4IDYuNDQ3NzIgOCA3WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNMTAgOEMxMC41NTIzIDggMTEgNy41NTIyOCAxMSA3QzExIDYuNDQ3NzIgMTAuNTUyMyA2IDEwIDZDOS40NDc3MSA2IDkgNi40NDc3MiA5IDdDOSA3LjU1MjI4IDkuNDQ3NzEgOCAxMCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMyAzQzEuMzQzMTUgMyAwIDQuMzQzMTUgMCA2VjE4QzAgMTkuNjU2OSAxLjM0MzE1IDIxIDMgMjFIMjFDMjIuNjU2OSAyMSAyNCAxOS42NTY5IDI0IDE4VjZDMjQgNC4zNDMxNSAyMi42NTY5IDMgMjEgM0gzWk0yMSA1SDNDMi40NDc3MiA1IDIgNS40NDc3MiAyIDZWOUgyMlY2QzIyIDUuNDQ3NzIgMjEuNTUyMyA1IDIxIDVaTTIgMThWMTFIMjJWMThDMjIgMTguNTUyMyAyMS41NTIzIDE5IDIxIDE5SDNDMi40NDc3MiAxOSAyIDE4LjU1MjMgMiAxOFoiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
|
||||
"type": "image/svg+xml",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
|
|
|
@ -104,7 +104,6 @@ AFRAME.registerComponent('helloworld-iframe', {
|
|||
"icons": [
|
||||
{
|
||||
"src": "https://css.gg/browse.svg",
|
||||
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNCA4QzQuNTUyMjggOCA1IDcuNTUyMjggNSA3QzUgNi40NDc3MiA0LjU1MjI4IDYgNCA2QzMuNDQ3NzIgNiAzIDYuNDQ3NzIgMyA3QzMgNy41NTIyOCAzLjQ0NzcyIDggNCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNOCA3QzggNy41NTIyOCA3LjU1MjI4IDggNyA4QzYuNDQ3NzIgOCA2IDcuNTUyMjggNiA3QzYgNi40NDc3MiA2LjQ0NzcyIDYgNyA2QzcuNTUyMjggNiA4IDYuNDQ3NzIgOCA3WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNMTAgOEMxMC41NTIzIDggMTEgNy41NTIyOCAxMSA3QzExIDYuNDQ3NzIgMTAuNTUyMyA2IDEwIDZDOS40NDc3MSA2IDkgNi40NDc3MiA5IDdDOSA3LjU1MjI4IDkuNDQ3NzEgOCAxMCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMyAzQzEuMzQzMTUgMyAwIDQuMzQzMTUgMCA2VjE4QzAgMTkuNjU2OSAxLjM0MzE1IDIxIDMgMjFIMjFDMjIuNjU2OSAyMSAyNCAxOS42NTY5IDI0IDE4VjZDMjQgNC4zNDMxNSAyMi42NTY5IDMgMjEgM0gzWk0yMSA1SDNDMi40NDc3MiA1IDIgNS40NDc3MiAyIDZWOUgyMlY2QzIyIDUuNDQ3NzIgMjEuNTUyMyA1IDIxIDVaTTIgMThWMTFIMjJWMThDMjIgMTguNTUyMyAyMS41NTIzIDE5IDIxIDE5SDNDMi40NDc3MiAxOSAyIDE4LjU1MjMgMiAxOFoiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
|
||||
"type": "image/svg+xml",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
|
|
|
@ -86,7 +86,6 @@ AFRAME.registerComponent('helloworld-window', {
|
|||
"icons": [
|
||||
{
|
||||
"src": "https://css.gg/browser.svg",
|
||||
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNCA4QzQuNTUyMjggOCA1IDcuNTUyMjggNSA3QzUgNi40NDc3MiA0LjU1MjI4IDYgNCA2QzMuNDQ3NzIgNiAzIDYuNDQ3NzIgMyA3QzMgNy41NTIyOCAzLjQ0NzcyIDggNCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNOCA3QzggNy41NTIyOCA3LjU1MjI4IDggNyA4QzYuNDQ3NzIgOCA2IDcuNTUyMjggNiA3QzYgNi40NDc3MiA2LjQ0NzcyIDYgNyA2QzcuNTUyMjggNiA4IDYuNDQ3NzIgOCA3WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBkPSJNMTAgOEMxMC41NTIzIDggMTEgNy41NTIyOCAxMSA3QzExIDYuNDQ3NzIgMTAuNTUyMyA2IDEwIDZDOS40NDc3MSA2IDkgNi40NDc3MiA5IDdDOSA3LjU1MjI4IDkuNDQ3NzEgOCAxMCA4WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMyAzQzEuMzQzMTUgMyAwIDQuMzQzMTUgMCA2VjE4QzAgMTkuNjU2OSAxLjM0MzE1IDIxIDMgMjFIMjFDMjIuNjU2OSAyMSAyNCAxOS42NTY5IDI0IDE4VjZDMjQgNC4zNDMxNSAyMi42NTY5IDMgMjEgM0gzWk0yMSA1SDNDMi40NDc3MiA1IDIgNS40NDc3MiAyIDZWOUgyMlY2QzIyIDUuNDQ3NzIgMjEuNTUyMyA1IDIxIDVaTTIgMThWMTFIMjJWMThDMjIgMTguNTUyMyAyMS41NTIzIDE5IDIxIDE5SDNDMi40NDc3MiAxOSAyIDE4LjU1MjMgMiAxOFoiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
|
||||
"type": "image/svg+xml",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ AFRAME.registerComponent('helloworld', {
|
|||
"icons": [
|
||||
{
|
||||
"src": "https://css.gg/shape-hexagon.svg",
|
||||
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNNiAxNS4yMzQ4TDEyIDE4LjU2ODFMMTggMTUuMjM0OFY4Ljc2NTIxTDEyIDUuNDMxODhMNiA4Ljc2NTIxVjE1LjIzNDhaTTEyIDJMMyA3VjE3TDEyIDIyTDIxIDE3VjdMMTIgMloiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
|
||||
"type": "image/svg+xml",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ AFRAME.registerComponent('isoterminal', {
|
|||
iso: { type:"string", "default":"com/isoterminal/xrsh.iso" },
|
||||
cols: { type: 'number',"default": 120 },
|
||||
rows: { type: 'number',"default": 30 },
|
||||
padding:{ type: 'number',"default": 18 },
|
||||
padding:{ type: 'number',"default": 15 },
|
||||
transparent: { type:'boolean', "default":false } // need good gpu
|
||||
},
|
||||
|
||||
|
@ -13,8 +13,10 @@ AFRAME.registerComponent('isoterminal', {
|
|||
|
||||
requires:{
|
||||
'window': "com/window.js",
|
||||
xtermjs: "https://unpkg.com/@xterm/xterm@5.5.0/lib/xterm.js",
|
||||
xtermcss: "https://unpkg.com/@xterm/xterm@5.5.0/css/xterm.css",
|
||||
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", //
|
||||
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"
|
||||
//axterm: "https://unpkg.com/aframe-xterm-component/aframe-xterm-component.js"
|
||||
},
|
||||
|
@ -22,12 +24,15 @@ AFRAME.registerComponent('isoterminal', {
|
|||
dom: {
|
||||
scale: 0.7,
|
||||
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{
|
||||
background:#000;
|
||||
padding: ${me.com.data.padding}px;
|
||||
width:100%;
|
||||
height:100%;
|
||||
/*overflow:hidden; */
|
||||
}
|
||||
.isoterminal *{
|
||||
white-space: pre;
|
||||
|
@ -37,14 +42,7 @@ AFRAME.registerComponent('isoterminal', {
|
|||
display:inline;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.isoterminal style{ display:none }
|
||||
|
||||
.wb-body:has(> .isoterminal){
|
||||
background: #000c;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.wb-body:has(> .isoterminal){ background: #000; }
|
||||
.isoterminal div{ display:block; }
|
||||
.isoterminal span{ display: inline }
|
||||
|
||||
|
@ -78,41 +76,12 @@ AFRAME.registerComponent('isoterminal', {
|
|||
return uint8Array;
|
||||
},
|
||||
|
||||
runISO: function(dom,instance){
|
||||
//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}]` )
|
||||
}
|
||||
|
||||
runISO: function(dom){
|
||||
var emulator = window.emulator = dom.emulator = new V86({
|
||||
wasm_path: "com/isoterminal/v86.wasm",
|
||||
memory_size: 32 * 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: {
|
||||
url: "com/isoterminal/bios/seabios.bin",
|
||||
},
|
||||
|
@ -123,10 +92,11 @@ AFRAME.registerComponent('isoterminal', {
|
|||
cdrom: {
|
||||
url: this.data.iso,
|
||||
},
|
||||
cmdline: "rw root=host9p rootfstype=9p rootflags=trans=virtio,cache=loose modules=virtio_pci tsc=reliable init_on_free=on",
|
||||
bzimage:{
|
||||
url: "com/isoterminal/images/buildroot-bzimage.bin"
|
||||
},
|
||||
network_relay_url: "<UNUSED>",
|
||||
cmdline: "rw root=host9p rootfstype=9p rootflags=trans=virtio,cache=loose modules=virtio_pci tsc=reliable init_on_free=on init=/bin/date",
|
||||
//bzimage:{
|
||||
// url: "com/isoterminal/images/buildroot-bzimage.bin"
|
||||
//},
|
||||
//bzimage_initrd_from_filesystem: true,
|
||||
//filesystem: {
|
||||
// baseurl: "com/isoterminal/v86/images/alpine-rootfs-flat",
|
||||
|
@ -138,193 +108,57 @@ AFRAME.registerComponent('isoterminal', {
|
|||
autostart: true,
|
||||
});
|
||||
|
||||
const loading = [
|
||||
'loading quantum bits and bytes',
|
||||
'preparing quantum flux capacitors',
|
||||
'crunching peanuts and chakras',
|
||||
'preparing parallel universe',
|
||||
'loading quantum state fluctuations',
|
||||
'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'
|
||||
]
|
||||
emulator.bus.register("emulator-started", () => {
|
||||
emulator.create_file("motd", this.toUint8Array(`
|
||||
[38;5;57m ____ _____________ _________ ___ ___
|
||||
[38;5;93m \ \/ /\______ \/ _____// | \
|
||||
[38;5;93m \ / | _/\_____ \/ ~ \
|
||||
[38;5;129m / \ | | \/ \ Y /
|
||||
[38;5;165m /___/\ \ |____|_ /_______ /\___|_ /
|
||||
[38;5;201m \_/ \/ \/ \/
|
||||
|
||||
let motd = "\n\r"
|
||||
motd += "[38;5;57m " + ' ____ _____________ _________ ___ ___ ' + "\n\r"
|
||||
motd += "[38;5;93m " + ' \\ \\/ /\\______ \\/ _____// | \\ ' + "\n\r"
|
||||
motd += "[38;5;93m " + ' \\ / | _/\\_____ \\/ ~ \\ ' + "\n\r"
|
||||
motd += "[38;5;129m " + ' / \\ | | \\/ \\ Y / ' + "\n\r"
|
||||
motd += "[38;5;165m " + ' /___/\\ \\ |____|_ /_______ /\\___|_ / ' + "\n\r"
|
||||
motd += "[38;5;201m " + ' \\_/ \\/ \\/ \\/ ' + "\n\r"
|
||||
motd += " \n\r"
|
||||
motd += `${loading[ Math.floor(Math.random()*1000) % loading.length-1 ]}, please wait..\n\r\n\r`
|
||||
motd += "\033[0m"
|
||||
`+ "\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
|
||||
cat /mnt/motd
|
||||
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()
|
||||
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)
|
||||
}
|
||||
let line = ''
|
||||
emulator.add_listener("serial0-output-byte", async (byte) => {
|
||||
var chr = String.fromCharCode(byte);
|
||||
if(chr < " " && chr !== "\n" && chr !== "\t" || chr > "~")
|
||||
{
|
||||
return;
|
||||
}
|
||||
})
|
||||
|
||||
// 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')
|
||||
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")
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
@ -345,6 +179,8 @@ AFRAME.registerComponent('isoterminal', {
|
|||
launcher: async function(){
|
||||
if( this.instance ){
|
||||
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)')
|
||||
}
|
||||
|
||||
|
@ -354,32 +190,32 @@ AFRAME.registerComponent('isoterminal', {
|
|||
this.el.sceneEl.appendChild( instance )
|
||||
|
||||
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.addEventListener('window.oncreate', (e) => {
|
||||
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) => {
|
||||
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("xd", "") // allows flipping between DOM/WebGL when toggling XD-button
|
||||
instance.setAttribute("visible", AFRAME.utils.XD() == '3D' ? 'true' : 'false' )
|
||||
instance.setAttribute("position", AFRAME.utils.XD.getPositionInFrontOfCamera(0.5) )
|
||||
instance.setAttribute("grabbable","")
|
||||
|
||||
const focus = () => document.querySelector('canvas.a-canvas').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
|
||||
"iso": "linux-x64-4.15.iso",
|
||||
"short_name": "ISOTerm",
|
||||
|
@ -430,7 +233,6 @@ AFRAME.registerComponent('isoterminal', {
|
|||
"icons": [
|
||||
{
|
||||
"src": "https://css.gg/terminal.svg",
|
||||
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNS4wMzMzIDE0LjgyODRMNi40NDc1MSAxNi4yNDI2TDEwLjY5MDIgMTJMNi40NDc1MSA3Ljc1NzMzTDUuMDMzMyA5LjE3MTU1TDcuODYxNzIgMTJMNS4wMzMzIDE0LjgyODRaIgogICAgZmlsbD0iY3VycmVudENvbG9yIgogIC8+CiAgPHBhdGggZD0iTTE1IDE0SDExVjE2SDE1VjE0WiIgZmlsbD0iY3VycmVudENvbG9yIiAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMiAyQzAuODk1NDMxIDIgMCAyLjg5NTQzIDAgNFYyMEMwIDIxLjEwNDYgMC44OTU0MyAyMiAyIDIySDIyQzIzLjEwNDYgMjIgMjQgMjEuMTA0NiAyNCAyMFY0QzI0IDIuODk1NDMgMjMuMTA0NiAyIDIyIDJIMlpNMjIgNEgyTDIgMjBIMjJWNFoiCiAgICBmaWxsPSJjdXJyZW50Q29sb3IiCiAgLz4KPC9zdmc+",
|
||||
"type": "image/svg+xml",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -1,6 +0,0 @@
|
|||
#!/bin/sh
|
||||
title=$1
|
||||
shift
|
||||
msg="$*"
|
||||
echo "[38;5;165m$title $(printf "\033[0m")$msg"
|
||||
hook alert $title "$msg"
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
read -p "$(printf "\033[0m")[?] [38;5;165m$1 [y/n] $(printf "\033[0m")" y
|
||||
test $y = y && echo true && exit
|
||||
echo false
|
|
@ -1 +0,0 @@
|
|||
alert("hello")
|
|
@ -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
|
||||
}
|
|
@ -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"
|
|
@ -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
|
||||
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
[38;5;93m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
[38;5;57m . . ____ _____________ ________. ._. ._. . . . . . . . .
|
||||
[38;5;93m . . _\ \/ /\______ \/ _____// | \. . . . . . . .
|
||||
[38;5;93m . . _ \ / | _/\_____ \/ ~ \ . . . . . . .
|
||||
[38;5;129m _ _ / \ | | \/ \ Y / _ _ _ _ _ _ _
|
||||
[38;5;165m . . /___/\ \ |____|_ /_______ /\___|_ /. . . . . . . .
|
||||
[38;5;201m . . . . . .\_/. . . . \/ . . . .\/ . . _ \/ . . . . . . . .
|
||||
[38;5;165m ▬ ▬ ▬ https://xrsh.isvery.ninja ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬ ▬
|
||||
[38;5;93m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
[38;5;165mOpen, local-first, hackable & selfcontained XR apps.
|
||||
|
||||
credits: all FOSS devs | @lvk@mastodon.online
|
||||
copy.sh (v86) | @utopiah@mastodon.pirateparty.be
|
||||
|
|
@ -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="\n[38;5;57mx[38;5;93mr[38;5;129ms[38;5;165mh [38;5;201m# \033[0m"
|
|
@ -1,3 +0,0 @@
|
|||
window.helloworld = function(){
|
||||
alert("hello world")
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
read -p "$(printf "\033[0m")[?] [38;5;165m$1: $(printf "\033[0m")" answer
|
||||
echo "$answer"
|
|
@ -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++
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -47,7 +47,6 @@ AFRAME.registerComponent('launcher-optional', {
|
|||
"icons": [
|
||||
{
|
||||
"src": "https://css.gg/add-r.svg",
|
||||
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNMTIgNkMxMi41NTIzIDYgMTMgNi40NDc3MiAxMyA3VjExSDE3QzE3LjU1MjMgMTEgMTggMTEuNDQ3NyAxOCAxMkMxOCAxMi41NTIzIDE3LjU1MjMgMTMgMTcgMTNIMTNWMTdDMTMgMTcuNTUyMyAxMi41NTIzIDE4IDEyIDE4QzExLjQ0NzcgMTggMTEgMTcuNTUyMyAxMSAxN1YxM0g3QzYuNDQ3NzIgMTMgNiAxMi41NTIzIDYgMTJDNiAxMS40NDc3IDYuNDQ3NzIgMTEgNyAxMUgxMVY3QzExIDYuNDQ3NzIgMTEuNDQ3NyA2IDEyIDZaIgogICAgZmlsbD0iY3VycmVudENvbG9yIgogIC8+CiAgPHBhdGgKICAgIGZpbGwtcnVsZT0iZXZlbm9kZCIKICAgIGNsaXAtcnVsZT0iZXZlbm9kZCIKICAgIGQ9Ik01IDIyQzMuMzQzMTUgMjIgMiAyMC42NTY5IDIgMTlWNUMyIDMuMzQzMTUgMy4zNDMxNSAyIDUgMkgxOUMyMC42NTY5IDIgMjIgMy4zNDMxNSAyMiA1VjE5QzIyIDIwLjY1NjkgMjAuNjU2OSAyMiAxOSAyMkg1Wk00IDE5QzQgMTkuNTUyMyA0LjQ0NzcyIDIwIDUgMjBIMTlDMTkuNTUyMyAyMCAyMCAxOS41NTIzIDIwIDE5VjVDMjAgNC40NDc3MiAxOS41NTIzIDQgMTkgNEg1QzQuNDQ3NzIgNCA0IDQuNDQ3NzIgNCA1VjE5WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgo8L3N2Zz4K",
|
||||
"type": "image/svg+xml",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
|
|
|
@ -63,10 +63,7 @@ AFRAME.registerComponent('launcher', {
|
|||
if( this.data.attach ){
|
||||
this.el.object3D.visible = false
|
||||
if( this.isHand(this.data.attach) ){
|
||||
this.data.attach.addEventListener('model-loaded', () => {
|
||||
this.ready = true
|
||||
this.attachMenu()
|
||||
})
|
||||
this.data.attach.addEventListener('model-loaded', () => this.attachMenu() )
|
||||
// add button
|
||||
this.menubutton = this.createMenuButton()
|
||||
this.menubutton.object3D.visible = false
|
||||
|
@ -283,7 +280,7 @@ AFRAME.registerComponent('launcher', {
|
|||
},
|
||||
|
||||
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
|
||||
this.el.object3D.getWorldPosition(this.worldPosition)
|
||||
const lookingAtPalm = this.data.attach.components['hand-tracking-controls'].wristObject3D.rotation.z > 2.0
|
||||
|
|
|
@ -34,8 +34,7 @@ AFRAME.utils.require = function(arr_or_obj,opts){
|
|||
if( AFRAME.required[id] ) return // already loaded before
|
||||
AFRAME.required[id] = true
|
||||
|
||||
if( !document.body.querySelector(`script#${id}`) &&
|
||||
!document.body.querySelector(`link#${id}`) ){
|
||||
if( !document.head.querySelector(`script#${id}`) ){
|
||||
let {type} = parseURI(package)
|
||||
let p = new Promise( (resolve,reject) => {
|
||||
switch(type){
|
||||
|
@ -44,15 +43,14 @@ AFRAME.utils.require = function(arr_or_obj,opts){
|
|||
script.onload = () => setTimeout( () => resolve(id), 50 )
|
||||
script.onerror = (e) => reject(e)
|
||||
script.src = package
|
||||
document.body.appendChild(script)
|
||||
document.head.appendChild(script)
|
||||
break;
|
||||
case "css": let link = document.createElement("link")
|
||||
link.id = id
|
||||
link.href = package
|
||||
link.rel = 'stylesheet'
|
||||
link.onload = () => setTimeout( () => resolve(id), 50 )
|
||||
link.onerror = (e) => reject(e)
|
||||
document.body.appendChild(link)
|
||||
document.head.appendChild(link)
|
||||
resolve(id)
|
||||
break;
|
||||
}
|
||||
})
|
||||
|
|
45
com/save.js
45
com/save.js
|
@ -3,13 +3,10 @@ AFRAME.registerComponent('save', {
|
|||
foo: { type:"string"}
|
||||
},
|
||||
|
||||
init: async function () {
|
||||
init: function () {
|
||||
this.el.object3D.visible = false
|
||||
await AFRAME.utils.require(this.dependencies)
|
||||
},
|
||||
|
||||
dependencies:{
|
||||
'xhook': 'https://jpillora.com/xhook/dist/xhook.min.js'
|
||||
//this.el.innerHTML = ` `
|
||||
},
|
||||
|
||||
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(){
|
||||
let l = document.querySelector("#left-hand")
|
||||
let r = document.querySelector("#right-hand")
|
||||
|
@ -58,8 +33,11 @@ AFRAME.registerComponent('save', {
|
|||
save_state: async function(){
|
||||
if( window.emulator ){
|
||||
let binaryString = '';
|
||||
const state = await emulator.save_state() //restore_state(state);
|
||||
//console.log(this.convert.arrayBufferToBase64(state))
|
||||
const state = await emulator.restore_state(state);
|
||||
uint8Array.forEach(byte => binaryString += String.fromCharCode(byte) );
|
||||
let b64data = btoa(binaryString);
|
||||
console.log(b64data)
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -75,8 +53,8 @@ AFRAME.registerComponent('save', {
|
|||
|
||||
inlineFiles: function(){
|
||||
let p = []
|
||||
let tags = [ ...document.querySelectorAll('script[src]'),
|
||||
...document.querySelectorAll('link[href]')
|
||||
let tags = [ ...document.querySelectorAll('script'),
|
||||
...document.querySelectorAll('link')
|
||||
]
|
||||
tags.map( (el) => {
|
||||
let remoteFile = el.src || el.href
|
||||
|
@ -89,12 +67,12 @@ AFRAME.registerComponent('save', {
|
|||
case 'LINK': el2 = document.createElement('style')
|
||||
el2.setAttribute("type","text/css")
|
||||
el2.setAttribute("_href", el.href )
|
||||
el2.innerHTML = `${text}`
|
||||
el2.innerHTML = text
|
||||
el.parentNode.appendChild(el2)
|
||||
el.remove()
|
||||
break;
|
||||
|
||||
case 'SCRIPT': el.innerHTML = `${text.replace(/<\//g,'</')}`
|
||||
case 'SCRIPT': el.innerHTML = text
|
||||
el.setAttribute("_src", el.src)
|
||||
el.removeAttribute("src")
|
||||
break;
|
||||
|
@ -114,7 +92,6 @@ AFRAME.registerComponent('save', {
|
|||
"icons": [
|
||||
{
|
||||
"src": "https://css.gg/arrow-down-r.svg",
|
||||
"src": "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNMTQuODI4NCAxMi4wMjU5TDE2LjI0MjYgMTMuNDQwMkwxMiAxNy42ODI4TDcuNzU3MzMgMTMuNDQwMkw5LjE3MTU1IDEyLjAyNTlMMTEgMTMuODU0NFY2LjMxNzI0SDEzVjEzLjg1NDRMMTQuODI4NCAxMi4wMjU5WiIKICAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAvPgogIDxwYXRoCiAgICBmaWxsLXJ1bGU9ImV2ZW5vZGQiCiAgICBjbGlwLXJ1bGU9ImV2ZW5vZGQiCiAgICBkPSJNMSA1QzEgMi43OTA4NiAyLjc5MDg2IDEgNSAxSDE5QzIxLjIwOTEgMSAyMyAyLjc5MDg2IDIzIDVWMTlDMjMgMjEuMjA5MSAyMS4yMDkxIDIzIDE5IDIzSDVDMi43OTA4NiAyMyAxIDIxLjIwOTEgMSAxOVY1Wk01IDNIMTlDMjAuMTA0NiAzIDIxIDMuODk1NDMgMjEgNVYxOUMyMSAyMC4xMDQ2IDIwLjEwNDYgMjEgMTkgMjFINUMzLjg5NTQzIDIxIDMgMjAuMTA0NiAzIDE5VjVDMyAzLjg5NTQzIDMuODk1NDMgMyA1IDNaIgogICAgZmlsbD0iY3VycmVudENvbG9yIgogIC8+Cjwvc3ZnPg==",
|
||||
"type": "image/svg+xml",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
|
|
|
@ -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) )
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -2,7 +2,7 @@ AFRAME.registerComponent('window', {
|
|||
schema:{
|
||||
title: {type:'string',"default":"title"},
|
||||
width: {type:'string'}, // wrap
|
||||
height: {type:'string',"default":'260px'},
|
||||
height: {type:'string',"default":'50px'},
|
||||
uid: {type:'string'},
|
||||
attach: {type:'selector'},
|
||||
dom: {type:'selector'},
|
||||
|
@ -13,8 +13,6 @@ AFRAME.registerComponent('window', {
|
|||
dependencies:{
|
||||
dom: "com/dom.js",
|
||||
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(){
|
||||
|
@ -34,17 +32,13 @@ AFRAME.registerComponent('window', {
|
|||
id: this.data.uid || String(Math.random()).substr(4), // important hint for html-mesh
|
||||
root: this.data.attach || document.body,
|
||||
mount: this.data.dom,
|
||||
onresize: () => this.el.emit('window.onresize',{}),
|
||||
onmaximize: () => this.el.emit('window.onmaximize',{}),
|
||||
oncreate: () => {
|
||||
this.el.emit('window.oncreate',{})
|
||||
// resize after the dom content has been rendered & updated
|
||||
setTimeout( () => {
|
||||
winbox.resize( this.el.dom.offsetWidth+'px', this.el.dom.offsetHeight+'px' )
|
||||
setTimeout( () => this.el.setAttribute("html",`html:#${this.data.uid}; cursor:#cursor`), 1000)
|
||||
// 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()
|
||||
this.el.setAttribute("grabbable","")
|
||||
},1000)
|
||||
},
|
||||
onclose: () => {
|
||||
|
@ -52,15 +46,14 @@ AFRAME.registerComponent('window', {
|
|||
this.el.emit('window.onclose',e)
|
||||
if( e.halt ) return true
|
||||
this.data.dom.style.display = 'none';
|
||||
this.data.dom.parentElement.remove()
|
||||
debugger
|
||||
this.el.parentElement.remove( this.el )
|
||||
return false
|
||||
},
|
||||
});
|
||||
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()
|
||||
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue