Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 04d7c08b authored by Simon Chan's avatar Simon Chan Committed by GitHub
Browse files

feat(demo): use tabby as terminal emulator (#541)

parent 58794f0d
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
        "lint": "next lint"
    },
    "dependencies": {
        "@angular/compiler": "^15.2.6",
        "@fluentui/react": "^8.107.5",
        "@fluentui/react-file-type-icons": "^8.8.13",
        "@fluentui/react-hooks": "^8.6.20",
@@ -18,6 +19,7 @@
        "@griffel/react": "^1.5.7",
        "@yume-chan/adb": "workspace:^0.0.19",
        "@yume-chan/adb-backend-direct-sockets": "workspace:^0.0.9",
        "@yume-chan/adb-backend-proxy": "workspace:^0.0.9",
        "@yume-chan/adb-backend-webusb": "workspace:^0.0.19",
        "@yume-chan/adb-backend-ws": "workspace:^0.0.9",
        "@yume-chan/adb-credential-web": "workspace:^0.0.19",
@@ -34,18 +36,23 @@
        "@yume-chan/stream-extra": "workspace:^0.0.19",
        "@yume-chan/stream-saver": "^2.0.6",
        "@yume-chan/struct": "workspace:^0.0.19",
        "@yume-chan/tabby-tango": "workspace:^0.0.19",
        "@yume-chan/undici-browser": "5.21.2-mod.9",
        "fflate": "^0.7.4",
        "yaml": "^2.2.1",
        "mobx": "^6.7.0",
        "mobx-react-lite": "^3.4.3",
        "next": "13.3.0",
        "tabby-core": "^1.0.197-nightly.0",
        "tabby-settings": "^1.0.197-nightly.0",
        "tabby-terminal": "^1.0.197-nightly.0",
        "tabby-community-color-schemes": "^1.0.197-nightly.0",
        "tabby-web": "^1.0.197-nightly.0",
        "tabby-web-container": "^1.0.197-nightly.0",
        "react": "^18.2.0",
        "react-dom": "^18.2.0",
        "webm-muxer": "^2.2.3",
        "xterm": "^5.1.0",
        "xterm-addon-fit": "^0.7.0",
        "xterm-addon-search": "^0.11.0",
        "xterm-addon-webgl": "^0.14.0"
        "rxjs": "^7.8.0",
        "webm-muxer": "^2.2.3"
    },
    "devDependencies": {
        "@mdx-js/loader": "^2.2.1",
+24 −0
Original line number Diff line number Diff line
@@ -27,3 +27,27 @@ fs.writeFileSync(
    ),
    "utf8"
);

fs.writeFileSync(
    new URL(
        "../node_modules/tabby-web-container/dist/preload.mjs",
        import.meta.url
    ),
    "export {};\n" +
        fs
            .readFileSync(
                new URL(
                    "../node_modules/tabby-web-container/dist/preload.js",
                    import.meta.url
                ),
                "utf8"
            )
            .replaceAll(/__webpack_require__\.p \+ "(.+)"/g, (_, match) => {
                return `new URL("./${match}", import.meta.url).toString()`;
            })
            .replaceAll(/__webpack_require__/g, "__webpack_require_nested__")
            .replace(
                "var scriptUrl;",
                "var scriptUrl = import.meta.url.toString();"
            )
);

apps/demo/scripts/postinstall.js

deleted100644 → 0
+0 −19
Original line number Diff line number Diff line
const fs = require('fs');
const path = require('path');

const PublicFolder = path.resolve(__dirname, '..', 'public');

const SourceFolder = path.dirname(require.resolve('streamsaver'));

const DistFolder = path.resolve(PublicFolder, 'StreamSaver');

if (!fs.existsSync(DistFolder)) {
    fs.mkdirSync(DistFolder);
}

function copyFile(name) {
    fs.copyFileSync(path.resolve(SourceFolder, name), path.resolve(DistFolder, name));
}

copyFile('mitm.html');
copyFile('sw.js');
+11 −10
Original line number Diff line number Diff line
export * from './command-bar';
export * from './connect';
export * from './demo-mode-panel';
export * from './device-view';
export * from './error-dialog';
export * from './external-link';
export * from './grid';
export * from './hex-viewer';
export * from "./command-bar";
export * from "./connect";
export * from "./demo-mode-panel";
export * from "./device-view";
export * from "./error-dialog";
export * from "./external-link";
export * from "./grid";
export * from "./hex-viewer";
export * from "./list-selection";
export * from './log-view';
export * from './resize-observer';
export * from "./log-view";
export * from "./resize-observer";
export * from "./tabby-frame-manager";
+80 −0
Original line number Diff line number Diff line
import { AdbProxyServer } from "@yume-chan/adb-backend-proxy";
import { autorun } from "mobx";
import getConfig from "next/config";
import { GLOBAL_STATE } from "../state";

let proxy: AdbProxyServer | undefined;
let resizeObserver: ResizeObserver | undefined;
let frame: HTMLIFrameElement | undefined;

function syncDevice() {
    if (proxy) {
        proxy.dispose();
        proxy = undefined;
    }

    if (GLOBAL_STATE.device && frame) {
        const proxy = new AdbProxyServer(GLOBAL_STATE.device);
        const info = proxy.createPort();
        frame.contentWindow?.postMessage(
            {
                type: "adb",
                ...info,
            },
            "*",
            [info.port]
        );
    }
}

export function attachTabbyFrame(container: HTMLDivElement | null) {
    if (container === null) {
        if (resizeObserver !== undefined) {
            resizeObserver.disconnect();
        }
        if (frame !== undefined) {
            frame.style.visibility = "hidden";
        }
        return;
    }

    if (!frame) {
        const {
            publicRuntimeConfig: { basePath },
        } = getConfig();

        frame = document.createElement("iframe");
        frame.src = `${basePath}/tabby-frame`;
        frame.style.display = "block";
        frame.style.position = "fixed";
        frame.style.border = "none";
        document.body.appendChild(frame);

        window.addEventListener("message", (e) => {
            // Wait for Tabby to be ready
            if (e.source === frame?.contentWindow && e.data === "adb") {
                syncDevice();
            }
        });

        // Sync device when it's changed
        autorun(syncDevice);
    }

    // Because re-parent an iframe will cause it to reload,
    // use visibility to show/hide it
    // and use a ResizeObserver to put it in the right place.
    frame.style.visibility = "visible";
    resizeObserver = new ResizeObserver(() => {
        const { top, left, width, height } = container.getBoundingClientRect();
        if (width === 0 || height === 0) {
            // zero size makes xterm.js wrap lines incorrectly
            return;
        }
        frame!.style.top = `${top}px`;
        frame!.style.left = `${left}px`;
        frame!.style.width = `${width}px`;
        frame!.style.height = `${height}px`;
    });
    resizeObserver.observe(container);
}
Loading