fix(app): terminal issues/regression

This commit is contained in:
Adam
2026-01-21 13:23:45 -06:00
parent 6f7a1c69a5
commit 3ba1111ed0
3 changed files with 52 additions and 13 deletions

View File

@@ -18,12 +18,22 @@ export function SortableTerminalTab(props: { terminal: LocalPTY; onClose?: () =>
const [menuPosition, setMenuPosition] = createSignal({ x: 0, y: 0 })
const [blurEnabled, setBlurEnabled] = createSignal(false)
const isDefaultTitle = () => {
const number = props.terminal.titleNumber
if (!Number.isFinite(number) || number <= 0) return false
const match = props.terminal.title.match(/^Terminal (\d+)$/)
if (!match) return false
const parsed = Number(match[1])
if (!Number.isFinite(parsed) || parsed <= 0) return false
return parsed === number
}
const label = () => {
language.locale()
if (props.terminal.title && !isDefaultTitle()) return props.terminal.title
const number = props.terminal.titleNumber
if (Number.isFinite(number) && number > 0) {
return language.t("terminal.title.numbered", { number })
}
if (Number.isFinite(number) && number > 0) return language.t("terminal.title.numbered", { number })
if (props.terminal.title) return props.terminal.title
return language.t("terminal.title")
}
@@ -102,8 +112,15 @@ export function SortableTerminalTab(props: { terminal: LocalPTY; onClose?: () =>
}
return (
// @ts-ignore
<div use:sortable classList={{ "h-full": true, "opacity-0": sortable.isActiveDraggable }}>
<div
// @ts-ignore
use:sortable
class="outline-none focus:outline-none focus-visible:outline-none"
classList={{
"h-full": true,
"opacity-0": sortable.isActiveDraggable,
}}
>
<div class="relative h-full">
<Tabs.Trigger
classes={{ button: "border-0" }}
@@ -111,6 +128,8 @@ export function SortableTerminalTab(props: { terminal: LocalPTY; onClose?: () =>
onClick={focus}
onMouseDown={(e) => e.preventDefault()}
onContextMenu={menu}
class="!shadow-none"
classes={{ button: "outline-none focus:outline-none focus-visible:outline-none !shadow-none !ring-0" }}
closeButton={
<IconButton
icon="close"

View File

@@ -10,6 +10,7 @@ export interface TerminalProps extends ComponentProps<"div"> {
pty: LocalPTY
onSubmit?: () => void
onCleanup?: (pty: LocalPTY) => void
onConnect?: () => void
onConnectError?: (error: unknown) => void
}
@@ -40,7 +41,7 @@ export const Terminal = (props: TerminalProps) => {
const settings = useSettings()
const theme = useTheme()
let container!: HTMLDivElement
const [local, others] = splitProps(props, ["pty", "class", "classList", "onConnectError"])
const [local, others] = splitProps(props, ["pty", "class", "classList", "onConnect", "onConnectError"])
let ws: WebSocket | undefined
let term: Term | undefined
let ghostty: Ghostty
@@ -241,6 +242,7 @@ export const Terminal = (props: TerminalProps) => {
// console.log("Scroll position:", ydisp)
// })
socket.addEventListener("open", () => {
local.onConnect?.()
sdk.client.pty
.update({
ptyID: local.pty.id,
@@ -255,10 +257,12 @@ export const Terminal = (props: TerminalProps) => {
t.write(event.data)
})
socket.addEventListener("error", (error) => {
if (disposed) return
console.error("WebSocket error:", error)
local.onConnectError?.(error)
})
socket.addEventListener("close", (event) => {
if (disposed) return
// Normal closure (code 1000) means PTY process exited - server event handles cleanup
// For other codes (network issues, server restart), trigger error handler
if (event.code !== 1000) {
@@ -268,6 +272,7 @@ export const Terminal = (props: TerminalProps) => {
})
onCleanup(() => {
disposed = true
if (handleResize) {
window.removeEventListener("resize", handleResize)
}