import { IS_BROWSER } from "$fresh/runtime.ts"; import { useEffect, useRef, useState } from "preact/hooks"; import { JSX } from "preact/jsx-runtime"; import { Sockpuppet } from "puppet/client"; export function Terminal(props: { channelId: string }) { const puppet = useRef(new Sockpuppet("ws://sockpuppet.cyborggrizzly.com")); const [lines, setLines] = useState([]); const divRef = useRef(null); const storeKey = 'commandHistory'; const [commandHistory, setCommandHistory] = useState(JSON.parse(localStorage.getItem(storeKey) || '[]')); const [historyIndex, setHistoryIndex] = useState(commandHistory.length); const [command, setCommand] = useState(""); const changeHistoryIndex = (by: number) => setHistoryIndex(i => i + by); useEffect(() => { if (!IS_BROWSER) return; puppet.current.joinChannel(props.channelId, (line) => { setLines((l) => [...l, line]); }); document.addEventListener('keyup', (e) => { switch (e.key) { case 'Up': case 'ArrowUp': changeHistoryIndex(-1); break; case 'Down': case 'ArrowDown': changeHistoryIndex(1); break; } }) }, []); useEffect(() => { if (divRef.current) { divRef.current.scrollTop = divRef.current.scrollHeight; } }, [lines]); const sendCommand = (e: Event) => { e.preventDefault(); puppet.current.getChannel(props.channelId)?.send(historyIndex === commandHistory.length ? command : commandHistory[historyIndex]); setCommandHistory(c => [...c, command]); setHistoryIndex(commandHistory.length + 1) setCommand(""); }; const handleCommandUpdate = (e: JSX.TargetedEvent) => { const value = e.currentTarget.value; if (historyIndex !== commandHistory.length) { setHistoryIndex(commandHistory.length); } setCommand(value || '') } useEffect(() => { localStorage.setItem(storeKey, JSON.stringify(commandHistory.slice(0,100))); }, [commandHistory]) return (
{lines.map((l) =>
{l}
)}
); }