| 1 | import type { EnvironmentThreadShell } from "@t3tools/client-runtime/state/shell"; |
| 2 | import { THREAD_JUMP_KEYBINDING_COMMANDS } from "@t3tools/contracts"; |
| 3 | import { useCallback } from "react"; |
| 4 | |
| 5 | import type { ThreadListV2ListItem } from "../threads/threadListV2"; |
| 6 | import { |
| 7 | useHardwareKeyboardCommand, |
| 8 | type HardwareKeyboardCommand, |
| 9 | } from "./hardwareKeyboardCommands"; |
| 10 | |
| 11 | type ThreadShortcutListItem = ThreadListV2ListItem | { readonly type: "v2-show-more" }; |
| 12 | |
| 13 | export function threadJumpIndex(command: HardwareKeyboardCommand) { |
| 14 | return THREAD_JUMP_KEYBINDING_COMMANDS.findIndex((candidate) => candidate === command); |
| 15 | } |
| 16 | |
| 17 | /** Uses the rendered list so filters and shelves keep their order. */ |
| 18 | export function threadJumpTarget( |
| 19 | items: ReadonlyArray<ThreadShortcutListItem>, |
| 20 | command: HardwareKeyboardCommand, |
| 21 | ) { |
| 22 | let index = threadJumpIndex(command); |
| 23 | if (index < 0) return null; |
| 24 | for (const item of items) { |
| 25 | const thread = item.type === "v2-thread" ? item.item.thread : null; |
| 26 | if (thread !== null && index-- === 0) return thread; |
| 27 | } |
| 28 | return null; |
| 29 | } |
| 30 | |
| 31 | export function useThreadJumpShortcuts( |
| 32 | items: ReadonlyArray<ThreadShortcutListItem>, |
| 33 | onSelectThread: (thread: EnvironmentThreadShell) => void, |
| 34 | ) { |
| 35 | const jumpToThread = useCallback( |
| 36 | (command: HardwareKeyboardCommand) => { |
| 37 | const thread = threadJumpTarget(items, command); |
| 38 | if (thread !== null) onSelectThread(thread); |
| 39 | return true; |
| 40 | }, |
| 41 | [items, onSelectThread], |
| 42 | ); |
| 43 | useHardwareKeyboardCommand(THREAD_JUMP_KEYBINDING_COMMANDS, jumpToThread); |
| 44 | } |