Skip to content

Commit eba7a98

Browse files
committed
fix: terminals sync + share css
1 parent 6db26ba commit eba7a98

File tree

3 files changed

+11
-16
lines changed

3 files changed

+11
-16
lines changed

app/components/ShareModal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
<div class="section">
7575
<p class="section-label">Connected Users ({{ guests.length + 1 }})</p>
7676
<ul class="guest-list">
77-
<li class="guest-item host"><span class="user-dot" /> {{ hostName }} (host)</li>
77+
<li class="guest-item"><span class="user-dot" /> {{ hostName }} (host)</li>
7878
<li v-for="g in guests" :key="g.id" class="guest-item"
7979
:class="{ you: g.id === guestId }">
8080
<span class="user-dot" /> {{ g.name }}{{ g.id === guestId ? ' (you)' : '' }}

server/routes/_share-terminal.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,8 @@ async function createDirectTerminal(shareId: string, session: any, terminalId: s
157157
directTerminals.set(terminalId, { shareId, sshConn: conn, stream });
158158
addActiveTerminal(shareId, terminalId, name, creatorId);
159159

160-
// Mute initial MOTD
161-
let muted = true;
162-
stream.write("clear\n");
163-
164160
stream.on("data", (chunk: Buffer) => {
165-
const str = chunk.toString("utf-8");
166-
if (muted) {
167-
if (str.includes("\x1b[2J")) muted = false;
168-
else return;
169-
}
170-
broadcastToTerminalPeers(terminalId, { type: "output", terminalId, data: str });
161+
broadcastToTerminalPeers(terminalId, { type: "output", terminalId, data: chunk.toString("utf-8") });
171162
});
172163

173164
stream.on("close", () => {

server/routes/_ssh-terminal.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,23 @@ export default defineWebSocketHandler({
7272
terminalConns.set(peer.id, { conn, stream, sessionId });
7373

7474
// Mute output until clear has finished (hides MOTD/banners and cd command)
75+
// Use broad regex to catch all erase-screen sequences:
76+
// \x1b[J, \x1b[0J, \x1b[1J, \x1b[2J, \x1b[3J (busybox uses \x1b[J)
7577
let muted = true;
78+
const eraseScreenRe = /\x1b\[\d*J/;
7679

7780
stream.on("data", (chunk: Buffer) => {
81+
const str = chunk.toString();
7882
if (muted) {
79-
// Look for the clear screen escape sequence
80-
const str = chunk.toString();
81-
if (str.includes("\x1b[2J")) {
83+
if (eraseScreenRe.test(str)) {
8284
muted = false;
85+
// Fall through — send this chunk (contains the clear + anything after)
86+
} else {
87+
return;
8388
}
84-
return;
8589
}
8690
try {
87-
peer.send(JSON.stringify({ type: "output", data: chunk.toString() }));
91+
peer.send(JSON.stringify({ type: "output", data: str }));
8892
} catch {
8993
// Peer disconnected
9094
}

0 commit comments

Comments
 (0)