mcgrizz/islands/terminal.tsx

49 lines
1.3 KiB
TypeScript

import { IS_BROWSER } from "$fresh/runtime.ts";
import { useEffect, useRef, useState } from "preact/hooks";
import { Sockpuppet } from "puppet/client";
export function Terminal(props: { channelId: string }) {
const puppet = useRef(new Sockpuppet("ws://sockpuppet.cyborggrizzly.com"));
const [lines, setLines] = useState<string[]>([]);
const divRef = useRef<HTMLDivElement>(null);
const [command, setCommand] = useState("");
useEffect(() => {
if (!IS_BROWSER) return;
puppet.current.joinChannel(props.channelId, (line) => {
setLines((l) => [...l, line]);
});
}, []);
useEffect(() => {
if (divRef.current) {
divRef.current.scrollTop = divRef.current.scrollHeight;
}
}, [lines]);
const sendCommand = (e: Event) => {
e.preventDefault();
puppet.current.getChannel(props.channelId)?.send(command);
setCommand("");
};
return (
<div>
<div ref={divRef} class="flex flex-col h-[600px] w-full overflow-auto">
{lines.map((l) => <div class="font-mono w-full">{l}</div>)}
</div>
<div>
<form onSubmit={sendCommand}>
<input
type="text"
class="w-full bg-smoke-600 text-white"
value={command}
onInput={(e) => setCommand((e.target as HTMLInputElement).value)}
/>
</form>
</div>
</div>
);
}