File size: 2,175 Bytes
064bfd6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | import { useContext, useEffect, useRef } from 'react'
import {
CLEAR_TAB_STATUS,
supportsTabStatus,
tabStatus,
wrapForMultiplexer,
} from '../termio/osc.js'
import type { Color } from '../termio/types.js'
import { TerminalWriteContext } from '../useTerminalNotification.js'
export type TabStatusKind = 'idle' | 'busy' | 'waiting'
const rgb = (r: number, g: number, b: number): Color => ({
type: 'rgb',
r,
g,
b,
})
// Per the OSC 21337 usage guide's suggested mapping.
const TAB_STATUS_PRESETS: Record<
TabStatusKind,
{ indicator: Color; status: string; statusColor: Color }
> = {
idle: {
indicator: rgb(0, 215, 95),
status: 'Idle',
statusColor: rgb(136, 136, 136),
},
busy: {
indicator: rgb(255, 149, 0),
status: 'Working…',
statusColor: rgb(255, 149, 0),
},
waiting: {
indicator: rgb(95, 135, 255),
status: 'Waiting',
statusColor: rgb(95, 135, 255),
},
}
/**
* Declaratively set the tab-status indicator (OSC 21337).
*
* Emits a colored dot + short status text to the tab sidebar. Terminals
* that don't support OSC 21337 discard the sequence silently, so this is
* safe to call unconditionally. Wrapped for tmux/screen passthrough.
*
* Pass `null` to opt out. If a status was previously set, transitioning to
* `null` emits CLEAR_TAB_STATUS so toggling off mid-session doesn't leave
* a stale dot. Process-exit cleanup is handled by ink.tsx's unmount path.
*/
export function useTabStatus(kind: TabStatusKind | null): void {
const writeRaw = useContext(TerminalWriteContext)
const prevKindRef = useRef<TabStatusKind | null>(null)
useEffect(() => {
// When kind transitions from non-null to null (e.g. user toggles off
// showStatusInTerminalTab mid-session), clear the stale dot.
if (kind === null) {
if (prevKindRef.current !== null && writeRaw && supportsTabStatus()) {
writeRaw(wrapForMultiplexer(CLEAR_TAB_STATUS))
}
prevKindRef.current = null
return
}
prevKindRef.current = kind
if (!writeRaw || !supportsTabStatus()) return
writeRaw(wrapForMultiplexer(tabStatus(TAB_STATUS_PRESETS[kind])))
}, [kind, writeRaw])
}
|