Add terminal tabs with read-only main terminal

This commit is contained in:
Torsten Dittmann
2025-05-12 12:04:31 +02:00
parent 67fc822631
commit 00a3a039cf
3 changed files with 49 additions and 5 deletions
+2 -1
View File
@@ -170,4 +170,5 @@ export class Synapse {
}
}
export const synapse = new Synapse('wss://terminal.appwrite.torsten.work');
export const endpoint = 'wss://terminal.appwrite.torsten.work';
export const synapse = new Synapse(endpoint);
+8 -2
View File
@@ -7,8 +7,9 @@
type Props = {
height: number;
synapse: Synapse;
readonly?: boolean;
};
let { height, synapse }: Props = $props();
let { height, synapse, readonly = false }: Props = $props();
const terminal: Action = (node) => {
const init = async () => {
@@ -26,7 +27,12 @@
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);
term.open(node);
term.onKey(({ key }) => {
term.onKey(({ key, domEvent }) => {
if (readonly) {
domEvent.preventDefault();
domEvent.stopPropagation();
return;
}
synapse.dispatch('terminal', {
operation: 'createCommand',
params: {
@@ -25,11 +25,12 @@
saveTerminalHeightToPrefs,
saveTerminalOpenToPrefs
} from '$lib/helpers/studioLayout';
import { synapse } from '$lib/components/studio/synapse.svelte';
import { endpoint, Synapse, synapse } from '$lib/components/studio/synapse.svelte';
import { showChat } from '$lib/stores/chat';
import { default as IconChatLayout } from '../assets/chat-layout.svelte';
import { filesystem } from '$lib/components/editor/filesystem';
import { InputSelect } from '$lib/elements/forms/index.js';
import { SvelteMap } from 'svelte/reactivity';
const { children } = $props();
@@ -51,6 +52,10 @@
hasChildren: true
}
];
const mainTerminalId = Symbol();
const terminals = new SvelteMap<symbol, Synapse>();
let currentTerminal: symbol = $state(mainTerminalId);
synapse.dispatch('synapse', {
operation: 'updateWorkDir',
params: {
@@ -132,6 +137,12 @@
$previewFrameRef.style.pointerEvents = '';
}
}
function createTerminal() {
const symbol = Symbol();
terminals.set(symbol, new Synapse(endpoint));
currentTerminal = symbol;
}
</script>
<Layout.Stack
@@ -196,7 +207,33 @@
<Icon icon={IconChevronDoubleUp} color="--fgcolor-neutral-tertiary" />
</Layout.Stack>
</summary>
<Terminal height={terminalHeight} {synapse}></Terminal>
<Layout.Stack>
<Tabs let:root>
<Tab
{root}
selected={currentTerminal === mainTerminalId}
on:click={() => (currentTerminal = mainTerminalId)}>
Imagine
</Tab>
{#each terminals as [symbol] (symbol)}
<Tab
{root}
on:click={() => (currentTerminal = symbol)}
selected={currentTerminal === symbol}>
Terminal
</Tab>
{/each}
<Tab {root} on:click={createTerminal}>+</Tab>
</Tabs>
</Layout.Stack>
<div style:display={currentTerminal === mainTerminalId ? 'contents' : 'none'}>
<Terminal height={terminalHeight} {synapse} readonly></Terminal>
</div>
{#each terminals as [symbol, synapse] (symbol)}
<div style:display={currentTerminal === symbol ? 'contents' : 'none'}>
<Terminal height={terminalHeight} {synapse}></Terminal>
</div>
{/each}
</details>
</aside>
</Layout.Stack>