( key: KeyEvent, state: ChatKeyboardState, )
| 119 | * This implements the priority-based keyboard handling logic. |
| 120 | */ |
| 121 | export function resolveChatKeyboardAction( |
| 122 | key: KeyEvent, |
| 123 | state: ChatKeyboardState, |
| 124 | ): ChatKeyboardAction { |
| 125 | const isEscape = key.name === 'escape' |
| 126 | const isCtrlC = key.ctrl && key.name === 'c' |
| 127 | const isCtrlV = key.ctrl && key.name === 'v' |
| 128 | const isBackspace = key.name === 'backspace' |
| 129 | const isUp = key.name === 'up' && !hasModifier(key) |
| 130 | const isDown = key.name === 'down' && !hasModifier(key) |
| 131 | const isTab = key.name === 'tab' && !hasModifier(key) |
| 132 | const isShiftTab = |
| 133 | key.name === 'tab' && key.shift && !key.ctrl && !key.meta && !key.option |
| 134 | const isEnter = isPlainEnterKey(key) |
| 135 | const isPageUp = key.name === 'pageup' && !hasModifier(key) |
| 136 | const isPageDown = key.name === 'pagedown' && !hasModifier(key) |
| 137 | |
| 138 | // Priority 0: Out of credits mode - Enter opens buy credits page |
| 139 | if (state.inputMode === 'outOfCredits') { |
| 140 | if (isEnter) { |
| 141 | return { type: 'open-buy-credits' } |
| 142 | } |
| 143 | // Allow Escape or Ctrl+C to exit out-of-credits mode (return to normal input) |
| 144 | if (isEscape || isCtrlC) { |
| 145 | return { type: 'exit-input-mode' } |
| 146 | } |
| 147 | // Block most other inputs in this mode |
| 148 | return { type: 'none' } |
| 149 | } |
| 150 | |
| 151 | // Priority 1: Feedback mode - block global keys except Escape/Ctrl-C/Ctrl-V |
| 152 | if (state.feedbackMode) { |
| 153 | if (isEscape) { |
| 154 | return { type: 'exit-feedback-mode' } |
| 155 | } |
| 156 | if (isCtrlC) { |
| 157 | return state.inputValue.length === 0 |
| 158 | ? { type: 'exit-feedback-mode' } |
| 159 | : { type: 'clear-feedback-input' } |
| 160 | } |
| 161 | if (isCtrlV) { |
| 162 | return { type: 'paste' } |
| 163 | } |
| 164 | return { type: 'none' } |
| 165 | } |
| 166 | |
| 167 | // Priority 2: Non-default input mode escape |
| 168 | // Escape should exit the current mode BEFORE interrupting streams |
| 169 | // Exception: modes with blockKeyboardExit cannot be escaped |
| 170 | const modeConfig = getInputModeConfig(state.inputMode) |
| 171 | if (isEscape && state.inputMode !== 'default' && !modeConfig.blockKeyboardExit) { |
| 172 | return { type: 'exit-input-mode' } |
| 173 | } |
| 174 | |
| 175 | // Priority 3: Clear input with ctrl-c when there's text |
| 176 | if (isCtrlC && state.inputValue.trim().length > 0) { |
| 177 | return { type: 'clear-input' } |
| 178 | } |
no test coverage detected