File size: 6,789 Bytes
1d8dca3
7c5f4e7
1d8dca3
7c5f4e7
1d8dca3
 
 
7c5f4e7
1d8dca3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62af5f0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1d8dca3
 
 
 
 
 
 
 
 
 
 
 
7c5f4e7
1d8dca3
 
 
 
 
 
 
 
 
 
 
 
 
7c5f4e7
 
 
1d8dca3
7c5f4e7
 
1d8dca3
 
 
 
 
 
 
 
 
7c5f4e7
1d8dca3
 
 
 
 
 
 
 
 
 
7c5f4e7
1d8dca3
 
 
 
7c5f4e7
1d8dca3
 
7c5f4e7
1d8dca3
 
 
 
7c5f4e7
1d8dca3
 
 
 
7c5f4e7
1d8dca3
 
 
7c5f4e7
1d8dca3
 
 
 
 
 
 
7c5f4e7
1d8dca3
 
 
 
 
 
 
7c5f4e7
 
1d8dca3
 
 
 
8acffa8
 
9509aed
8acffa8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9509aed
7c5f4e7
20e35db
 
 
7c5f4e7
1d8dca3
7c5f4e7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Enhanced Terminal</title>
    <link rel="stylesheet" href="https://unpkg.com/xterm@4.11.0/css/xterm.css" />
    <style>
        html {
            font-family: Arial, sans-serif;
        }
        body {
            background-color: #1e1e1e; /* Dark grey background */
            color: white;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            height: 100vh;
        }
        #status-bar {
            background-color: #333; /* Darker background for status bar */
            color: #fff;
            padding: 5px 10px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-size: small;
        }
        #terminal-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            padding: 10px;
        }
        #terminal {
            flex: 1;
            width: 100%;
            height: 100%;
            border: 1px solid #444; /* Border around terminal */
            border-radius: 5px; /* Rounded corners */
            overflow: hidden; /* Hide overflow */
        }
        /* Custom scrollbar styles */
        ::-webkit-scrollbar {
            width: 12px;
            height: 12px;
        }
        ::-webkit-scrollbar-track {
            background: #2e2e2e; /* Darker background for track */
            border-radius: 10px;
        }
        ::-webkit-scrollbar-thumb {
            background-color: #555; /* Grey color for thumb */
            border-radius: 10px;
            border: 3px solid #2e2e2e; /* Padding around thumb */
        }
        ::-webkit-scrollbar-thumb:hover {
            background-color: #777; /* Lighter grey on hover */
        }
        .link-container {
            text-align: right;
            font-size: small;
            margin-top: 5px;
        }
        .link-container a {
            color: #1e90ff; /* Link color */
            text-decoration: none;
        }
        .link-container a:hover {
            text-decoration: underline;
        }
    </style>
</head>
<body>
    <div id="status-bar">
        <span>Status: <span id="status">connecting...</span></span>
        <span id="resize-status"></span>
    </div>
    <div id="terminal-container">
        <div id="terminal"></div>
        <div class="link-container">
            <a href="https://www.youtube.com/watch?v=o-YBDTqX_ZU">Get Rickrolled</a> | 
            <a href="https://github.com">GitHub</a>
        </div>
    </div>
    <script src="https://unpkg.com/xterm@4.11.0/lib/xterm.js"></script>
    <script src="https://unpkg.com/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.js"></script>
    <script src="https://unpkg.com/xterm-addon-web-links@0.4.0/lib/xterm-addon-web-links.js"></script>
    <script src="https://unpkg.com/xterm-addon-search@0.8.0/lib/xterm-addon-search.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js"></script>
    <script>
        const term = new Terminal({
            cursorBlink: true,
            macOptionIsMeta: true,
            scrollback: true,
        });
        const fit = new FitAddon.FitAddon();
        term.loadAddon(fit);
        term.loadAddon(new WebLinksAddon.WebLinksAddon());
        term.loadAddon(new SearchAddon.SearchAddon());

        term.open(document.getElementById("terminal"));
        fit.fit();
        term.resize(15, 50);
        console.log(`size: ${term.cols} columns, ${term.rows} rows`);
        fit.fit();
        term.writeln("Welcome to AR-server");
        term.writeln("");
        term.writeln("You can copy with ctrl+shift+x");
        term.writeln("You can paste with ctrl+shift+v");
        term.writeln('');

        term.onData((data) => {
            console.log("browser terminal received new data:", data);
            socket.emit("pty-input", { input: data });
        });

        const socket = io.connect("/pty");
        const status = document.getElementById("status");

        socket.on("pty-output", function (data) {
            console.log("new output received from server:", data.output);
            term.write(data.output);
        });

        socket.on("connect", () => {
            fitToscreen();
            status.innerHTML = '<span style="background-color: lightgreen; padding: 2px 4px; border-radius: 3px;">connected</span>';
        });

        socket.on("disconnect", () => {
            status.innerHTML = '<span style="background-color: #ff8383; padding: 2px 4px; border-radius: 3px;">disconnected</span>';
        });

        function fitToscreen() {
            fit.fit();
            const dims = { cols: term.cols, rows: term.rows };
            console.log("sending new dimensions to server's pty", dims);
            socket.emit("resize", dims);
            document.getElementById("resize-status").textContent = `Resized to: ${dims.cols}x${dims.rows}`;
        }

        function debounce(func, wait_ms) {
            let timeout;
            return function (...args) {
                const context = this;
                clearTimeout(timeout);
                timeout = setTimeout(() => func.apply(context, args), wait_ms);
            };
        }

        /**
         * Handle copy and paste events
         */
        function customKeyEventHandler(e) {
            if (e.type !== "keydown") {
                return true;
            }
            if (e.ctrlKey && e.shiftKey) {
                const key = e.key.toLowerCase();
                if (key === "v") {
                    // ctrl+shift+v: paste whatever is in the clipboard
                    navigator.clipboard.readText().then((toPaste) => {
                        socket.emit("pty-input", { input: toPaste });
                    });
                    
                    // Prevent default paste action
                    e.preventDefault();
                    
                    return false;
                } else if (key === "c" || key === "x") {
                    // ctrl+shift+x: copy whatever is highlighted to clipboard
                    const toCopy = term.getSelection();
                    if (toCopy) {
                        navigator.clipboard.writeText(toCopy).then(() => {
                            term.focus();
                        });
                    }
                    return false;
                }
            }
            return true;
        }

        const wait_ms = 50;
        window.onresize = debounce(fitToscreen, wait_ms);
        term.attachCustomKeyEventHandler(customKeyEventHandler);
    </script>
</body>
</html>