()
| 195 | } |
| 196 | |
| 197 | function App() { |
| 198 | const route = useRoute() |
| 199 | const dimensions = useTerminalDimensions() |
| 200 | const renderer = useRenderer() |
| 201 | renderer.disableStdoutInterception() |
| 202 | const dialog = useDialog() |
| 203 | const local = useLocal() |
| 204 | const kv = useKV() |
| 205 | const command = useCommandDialog() |
| 206 | const { event, client: sdk } = useSDK() |
| 207 | const toast = useToast() |
| 208 | const { theme, mode, setMode } = useTheme() |
| 209 | const sync = useSync() |
| 210 | const exit = useExit() |
| 211 | const promptRef = usePromptRef() |
| 212 | const keybind = useKeybind() |
| 213 | |
| 214 | const [showCopyButton, setShowCopyButton] = createSignal(false) |
| 215 | const copyButtonEnabled = () => kv.get("copy_button_enabled", false) |
| 216 | const [copyButtonPos, setCopyButtonPos] = createSignal({ x: 0, y: 0 }) |
| 217 | const [exitConfirmation, setExitConfirmation] = createSignal(false) |
| 218 | let lastSelectionText = "" |
| 219 | let lastMousePos = { x: 0, y: 0 } |
| 220 | let lastCtrlCPress = 0 |
| 221 | const multiClickDetector = DoubleClick.createMultiClick() |
| 222 | |
| 223 | onMount(() => { |
| 224 | // Re-apply keyboard protocol modes after renderer setup. |
| 225 | renderer.enableKittyKeyboard() |
| 226 | process.stdout.write("\x1b[>4;1m") |
| 227 | process.stdout.write("\x1b[>4;2m") |
| 228 | // Re-enable bracketed paste mode |
| 229 | process.stdout.write("\x1b[?2004h") |
| 230 | |
| 231 | // Handle terminal focus events (e.g., switching tabs) |
| 232 | // Focus-in events trigger a repaint to fix rendering issues |
| 233 | let savedFocus: any = null |
| 234 | const handleStdinData = (data: Buffer) => { |
| 235 | const str = data.toString() |
| 236 | // Check for focus-out escape sequence (\x1b[O) |
| 237 | if (str.includes("\x1b[O")) { |
| 238 | savedFocus = renderer.currentFocusedRenderable |
| 239 | } |
| 240 | // Check for focus-in escape sequence (\x1b[I) |
| 241 | if (str.includes("\x1b[I")) { |
| 242 | renderer.currentRenderBuffer.clear() |
| 243 | renderer.requestRender() |
| 244 | // restore focus to the previously focused element after render completes |
| 245 | // try multiple times with increasing delays to work around opentui 0.1.77 focus tracking bug |
| 246 | const restoreFocus = () => { |
| 247 | const target = savedFocus || promptRef.current |
| 248 | if (target && typeof target.focus === "function") { |
| 249 | try { |
| 250 | if (typeof target.blur === "function") { |
| 251 | target.blur() |
| 252 | } |
| 253 | target.focus() |
| 254 | } catch {} |
no test coverage detected