| 99 | // It renders stdin and stdout contexts, so that children can access them if needed |
| 100 | // It also handles Ctrl+C exiting and cursor visibility |
| 101 | export default class App extends PureComponent<Props, State> { |
| 102 | static displayName = 'InternalApp'; |
| 103 | static getDerivedStateFromError(error: Error) { |
| 104 | return { |
| 105 | error |
| 106 | }; |
| 107 | } |
| 108 | override state = { |
| 109 | error: undefined |
| 110 | }; |
| 111 | |
| 112 | // Count how many components enabled raw mode to avoid disabling |
| 113 | // raw mode until all components don't need it anymore |
| 114 | rawModeEnabledCount = 0; |
| 115 | internal_eventEmitter = new EventEmitter(); |
| 116 | keyParseState = INITIAL_STATE; |
| 117 | // Timer for flushing incomplete escape sequences |
| 118 | incompleteEscapeTimer: NodeJS.Timeout | null = null; |
| 119 | // Timeout durations for incomplete sequences (ms) |
| 120 | readonly NORMAL_TIMEOUT = 50; // Short timeout for regular esc sequences |
| 121 | readonly PASTE_TIMEOUT = 500; // Longer timeout for paste operations |
| 122 | |
| 123 | // Terminal query/response dispatch. Responses arrive on stdin (parsed |
| 124 | // out by parse-keypress) and are routed to pending promise resolvers. |
| 125 | querier = new TerminalQuerier(this.props.stdout); |
| 126 | |
| 127 | // Multi-click tracking for double/triple-click text selection. A click |
| 128 | // within MULTI_CLICK_TIMEOUT_MS and MULTI_CLICK_DISTANCE of the previous |
| 129 | // click increments clickCount; otherwise it resets to 1. |
| 130 | lastClickTime = 0; |
| 131 | lastClickCol = -1; |
| 132 | lastClickRow = -1; |
| 133 | clickCount = 0; |
| 134 | // Deferred hyperlink-open timer — cancelled if a second click arrives |
| 135 | // within MULTI_CLICK_TIMEOUT_MS (so double-clicking a hyperlink selects |
| 136 | // the word without also opening the browser). DOM onClick dispatch is |
| 137 | // NOT deferred — it returns true from onClickAt and skips this timer. |
| 138 | pendingHyperlinkTimer: ReturnType<typeof setTimeout> | null = null; |
| 139 | // Last mode-1003 motion position. Terminals already dedupe to cell |
| 140 | // granularity but this also lets us skip dispatchHover entirely on |
| 141 | // repeat events (drag-then-release at same cell, etc.). |
| 142 | lastHoverCol = -1; |
| 143 | lastHoverRow = -1; |
| 144 | |
| 145 | // Timestamp of last stdin chunk. Used to detect long gaps (tmux attach, |
| 146 | // ssh reconnect, laptop wake) and trigger terminal mode re-assert. |
| 147 | // Initialized to now so startup doesn't false-trigger. |
| 148 | lastStdinTime = Date.now(); |
| 149 | |
| 150 | // Determines if TTY is supported on the provided stdin |
| 151 | isRawModeSupported(): boolean { |
| 152 | return this.props.stdin.isTTY; |
| 153 | } |
| 154 | override render() { |
| 155 | return <TerminalSizeContext.Provider value={{ |
| 156 | columns: this.props.terminalColumns, |
| 157 | rows: this.props.terminalRows |
| 158 | }}> |
nothing calls this directly
no test coverage detected