|
44 | 44 | <div class="header-actions"> |
45 | 45 | <button @click="saveActivePane" class="btn" |
46 | 46 | :class="{ 'btn-press': savePressing, 'btn-success': saveSuccess }" |
47 | | - :disabled="!activePane?.filePath">Save</button> |
| 47 | + :disabled="!activePane?.filePath"> |
| 48 | + {{ saveSuccess ? 'Saved' : 'Save' }} |
| 49 | + </button> |
48 | 50 | <button @click="showShare = true" class="btn share-btn" |
49 | 51 | :class="{ 'btn-sharing': isSharing }" |
50 | 52 | :title="isSharing ? (isGuest ? 'Connected to session' : 'Sharing active') : 'Share session'"> |
@@ -648,76 +650,73 @@ async function autoJoinShare(sid: string) { |
648 | 650 | } |
649 | 651 |
|
650 | 652 | // Register callbacks for share lifecycle + relay terminal handling |
651 | | -import { onShareClosed as _onShareClosedSetter, onRelayTerminalCreate as _rtcSetter, onRelayTerminalInput as _rtiSetter, onRelayTerminalResize as _rtrSetter, onRelayTerminalClose as _rtclSetter } from '~/composables/useShare'; |
| 653 | +import { setOnShareClosed, setOnRelayTerminalCreate, setOnRelayTerminalInput, setOnRelayTerminalResize, setOnRelayTerminalClose } from '~/composables/useShare'; |
652 | 654 | // Map of relay terminalId → local WebSocket (desktop host bridges guest terminals to local PTY) |
653 | 655 | const relayTerminalWs = new Map<string, WebSocket>(); |
654 | 656 |
|
655 | 657 | if (import.meta.client) { |
656 | | - (async () => { |
657 | | - const mod = await import('~/composables/useShare'); |
658 | | - mod.onShareClosed = () => { |
659 | | - resetToFolderSelector(); |
660 | | - }; |
| 658 | + setOnShareClosed(() => { |
| 659 | + resetToFolderSelector(); |
| 660 | + }); |
661 | 661 |
|
662 | | - // Desktop host relay: guest creates a terminal → spawn local terminal, pipe I/O through relay WS |
663 | | - mod.onRelayTerminalCreate = (msg: any) => { |
664 | | - const { terminalId, cwd, cols, rows } = msg; |
665 | | - const { getLocalWsUrl, getSessionId } = useApi(); |
666 | | - const { sendRelayMessage } = useShare(); |
667 | | - // Connect to the local terminal WS (bypasses share routing to avoid loop) |
668 | | - const localWs = new WebSocket(getLocalWsUrl()); |
669 | | - relayTerminalWs.set(terminalId, localWs); |
670 | | -
|
671 | | - localWs.onopen = () => { |
672 | | - localWs.send(JSON.stringify({ |
673 | | - type: "create", |
674 | | - cwd: cwd || rootPath.value, |
675 | | - cols: cols || 80, |
676 | | - rows: rows || 24, |
677 | | - sessionId: getSessionId(), |
678 | | - })); |
679 | | - }; |
680 | | -
|
681 | | - localWs.onmessage = (ev) => { |
682 | | - try { |
683 | | - const data = JSON.parse(ev.data); |
684 | | - if (data.type === "output") { |
685 | | - sendRelayMessage({ type: "terminal-output", terminalId, data: data.data }); |
686 | | - } else if (data.type === "exit") { |
687 | | - sendRelayMessage({ type: "terminal-exit", terminalId, code: data.code ?? 0 }); |
688 | | - localWs.close(); |
689 | | - relayTerminalWs.delete(terminalId); |
690 | | - } |
691 | | - } catch {} |
692 | | - }; |
693 | | -
|
694 | | - localWs.onclose = () => { |
695 | | - relayTerminalWs.delete(terminalId); |
696 | | - }; |
| 662 | + // Desktop host relay: guest creates a terminal → spawn local terminal, pipe I/O through relay WS |
| 663 | + setOnRelayTerminalCreate((msg: any) => { |
| 664 | + const { terminalId, cwd, cols, rows } = msg; |
| 665 | + const { getLocalWsUrl, getSessionId } = useApi(); |
| 666 | + const { sendRelayMessage } = useShare(); |
| 667 | + // Connect to the local terminal WS (bypasses share routing to avoid loop) |
| 668 | + const localWs = new WebSocket(getLocalWsUrl()); |
| 669 | + relayTerminalWs.set(terminalId, localWs); |
| 670 | +
|
| 671 | + localWs.onopen = () => { |
| 672 | + localWs.send(JSON.stringify({ |
| 673 | + type: "create", |
| 674 | + cwd: cwd || rootPath.value, |
| 675 | + cols: cols || 80, |
| 676 | + rows: rows || 24, |
| 677 | + sessionId: getSessionId(), |
| 678 | + })); |
697 | 679 | }; |
698 | 680 |
|
699 | | - mod.onRelayTerminalInput = (msg: any) => { |
700 | | - const ws = relayTerminalWs.get(msg.terminalId); |
701 | | - if (ws && ws.readyState === WebSocket.OPEN) { |
702 | | - ws.send(JSON.stringify({ type: "input", data: msg.data })); |
703 | | - } |
| 681 | + localWs.onmessage = (ev) => { |
| 682 | + try { |
| 683 | + const data = JSON.parse(ev.data); |
| 684 | + if (data.type === "output") { |
| 685 | + sendRelayMessage({ type: "terminal-output", terminalId, data: data.data }); |
| 686 | + } else if (data.type === "exit") { |
| 687 | + sendRelayMessage({ type: "terminal-exit", terminalId, code: data.code ?? 0 }); |
| 688 | + localWs.close(); |
| 689 | + relayTerminalWs.delete(terminalId); |
| 690 | + } |
| 691 | + } catch {} |
704 | 692 | }; |
705 | 693 |
|
706 | | - mod.onRelayTerminalResize = (msg: any) => { |
707 | | - const ws = relayTerminalWs.get(msg.terminalId); |
708 | | - if (ws && ws.readyState === WebSocket.OPEN) { |
709 | | - ws.send(JSON.stringify({ type: "resize", cols: msg.cols, rows: msg.rows })); |
710 | | - } |
| 694 | + localWs.onclose = () => { |
| 695 | + relayTerminalWs.delete(terminalId); |
711 | 696 | }; |
| 697 | + }); |
712 | 698 |
|
713 | | - mod.onRelayTerminalClose = (msg: any) => { |
714 | | - const ws = relayTerminalWs.get(msg.terminalId); |
715 | | - if (ws) { |
716 | | - ws.close(); |
717 | | - relayTerminalWs.delete(msg.terminalId); |
718 | | - } |
719 | | - }; |
720 | | - })(); |
| 699 | + setOnRelayTerminalInput((msg: any) => { |
| 700 | + const ws = relayTerminalWs.get(msg.terminalId); |
| 701 | + if (ws && ws.readyState === WebSocket.OPEN) { |
| 702 | + ws.send(JSON.stringify({ type: "input", data: msg.data })); |
| 703 | + } |
| 704 | + }); |
| 705 | +
|
| 706 | + setOnRelayTerminalResize((msg: any) => { |
| 707 | + const ws = relayTerminalWs.get(msg.terminalId); |
| 708 | + if (ws && ws.readyState === WebSocket.OPEN) { |
| 709 | + ws.send(JSON.stringify({ type: "resize", cols: msg.cols, rows: msg.rows })); |
| 710 | + } |
| 711 | + }); |
| 712 | +
|
| 713 | + setOnRelayTerminalClose((msg: any) => { |
| 714 | + const ws = relayTerminalWs.get(msg.terminalId); |
| 715 | + if (ws) { |
| 716 | + ws.close(); |
| 717 | + relayTerminalWs.delete(msg.terminalId); |
| 718 | + } |
| 719 | + }); |
721 | 720 | } |
722 | 721 |
|
723 | 722 | const editorAreaRef = ref<{ splitRatio: number; focusPane: (id: string) => void } | null>(null); |
|
0 commit comments