Skip to content
This repository has been archived by the owner on Apr 13, 2024. It is now read-only.

Migrate to launching shell as a child app #9

Merged
merged 6 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://puter.com/puter.js/v2"></script>
<link rel="stylesheet" href="xterm.css">
<link rel="stylesheet" href="normalize.css">
<link rel="stylesheet" href="style.css">
Expand All @@ -17,6 +18,5 @@
</script>
</head>
<body>
<div id="cross-document-container"></div>
</body>
</html>
1 change: 0 additions & 1 deletion config/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,4 @@
*/
globalThis.__CONFIG__ = {
"origin": "http://127.0.0.1:8082",
"shellURL": "http://127.0.0.1:8080",
};
1 change: 0 additions & 1 deletion config/release.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,4 @@
*/
globalThis.__CONFIG__ = {
"origin": "https://puter.sh",
"shellURL": "https://xd.puter.sh"
};
59 changes: 10 additions & 49 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,50 +123,21 @@ linkHandler.activate = (e, url) => {
newWindow.location.href = uri;
}

window.main_term = () => {
window.main_term = async () => {
const pty = new PTY();
const ptt = pty.getPTT();

const shell = new XDocumentANSIShell({
source: __CONFIG__.shellURL,
ptt
});

const shellURLAsURLType = new URL(__CONFIG__.shellURL);
const shellOrigin = shellURLAsURLType.origin;

const iframe = document.createElement('iframe');
const xdEl = document.getElementById('cross-document-container');
xdEl.appendChild(iframe);
shell.attachToIframe(iframe);

let initialSize;

const cw = iframe.contentWindow;
window.addEventListener('message', evt => {
if ( evt.source !== cw ) return;
if ( evt.data instanceof Uint8Array ) return;
if ( ! evt.data.hasOwnProperty('$') ) return;
// When the iframe reports it's ready, send configuration
if ( evt.data.$ === 'ready' ) {
const params = Object.fromEntries(
new URLSearchParams(window.location.search)
.entries()
);
cw.postMessage({
$: 'config',
source: params['puter.api_origin'] ??
( params['puter.domain']
? `https://api.${params['puter.domain']}/`
: 'https://api.puter.com/' ),
...params
}, shellOrigin);
if ( initialSize ) cw.postMessage({
$: 'ioctl.set',
windowSize: initialSize
}, shellOrigin);
return;
}
const phoenix = await puter.ui.launchApp('phoenix');
shell.attachToApp(phoenix);

// Close the shell when we exit
puter.ui.onWindowClose(() => {
phoenix.close();
puter.exit();
});

const termEl = document.createElement('div');
Expand All @@ -182,24 +153,14 @@ window.main_term = () => {
term.loadAddon(fitAddon);

term.onResize(evt => {
console.log('got this', evt)
initialSize = evt,
cw.postMessage({
$: 'ioctl.set',
windowSize: evt
}, shellOrigin);
})
shell.resize(evt);
});

fitAddon.fit();

window.addEventListener('resize', () => {
fitAddon.fit();
})

const termObserver = new ResizeObserver(() => {
fitAddon.fit();
});

termObserver.observe(termEl);

const ioController = new XTermIO({ term, pty });
Expand Down
63 changes: 49 additions & 14 deletions src/pty/XDocumentANSIShell.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,66 @@ export class XDocumentANSIShell {
for ( const k in params ) this.internal_[k] = params[k];
}

attachToIframe (iframeEl) {
const source = this.internal_.source;
attachToApp (shell) {
this.internal_.shell = shell;

iframeEl.src = source;
const ptt = this.internal_.ptt;

this.internal_.window = iframeEl.contentWindow;
this.attachToWindow_();
}
shell.on('message', message => {
// When the shell reports it's ready, send configuration
if (message.$ === 'ready') {
const params = Object.fromEntries(
new URLSearchParams(window.location.search)
.entries()
);
shell.postMessage({
$: 'config',
source: params['puter.api_origin'] ??
( params['puter.domain']
? `https://api.${params['puter.domain']}/`
: 'https://api.puter.com/' ),
...params
});

attachToWindow_ () {
const contentWindow = this.internal_.window;
const ptt = this.internal_.ptt;
const savedSize = this.internal_.windowSize;
if (savedSize) {
shell.postMessage({
$: 'ioctl.set',
windowSize: savedSize,
});
}
return;
}

window.addEventListener('message', evt => {
if ( evt.source !== contentWindow ) return;
if ( ! (evt.data instanceof Uint8Array) ) return;
if (message.$ === 'output') {
ptt.out.write(message.data);
return;
}
});

ptt.out.write(evt.data);
shell.on('close', () => {
const errorMessage = '\n\n\x1b[31;1mConnection lost with shell!\x1b[0m\n';
const errorArray = new TextEncoder().encode(errorMessage);
ptt.out.write(errorArray);
});

(async () => {
for ( ;; ) {
const chunk = (await ptt.in.read()).value;
contentWindow.postMessage(chunk, this.internal_.source);
shell.postMessage({
$: 'input',
data: chunk,
});
}
})();
}

resize (windowSize) {
const shell = this.internal_.shell;
this.internal_.windowSize = windowSize;
shell.postMessage({
$: 'ioctl.set',
windowSize,
});
}
}