MCPcopy Create free account
hub / github.com/codeaashu/claude-code / useMessageActions

Function useMessageActions

src/components/messageActions.tsx:217–271  ·  view source on GitHub ↗
(cursor: MessageActionsState | null, setCursor: React.Dispatch<React.SetStateAction<MessageActionsState | null>>, navRef: RefObject<MessageActionsNav | null>, caps: MessageActionCaps)

Source from the content-addressed store, hash-verified

215
216// Can't call useKeybindings here — hook runs outside <KeybindingSetup> provider. Returns handlers instead.
217export function useMessageActions(cursor: MessageActionsState | null, setCursor: React.Dispatch<React.SetStateAction<MessageActionsState | null>>, navRef: RefObject<MessageActionsNav | null>, caps: MessageActionCaps): {
218 enter: () => void;
219 handlers: Record<string, () => void>;
220} {
221 // Refs keep handlers stable — no useKeybindings re-register per message append.
222 const cursorRef = useRef(cursor);
223 cursorRef.current = cursor;
224 const capsRef = useRef(caps);
225 capsRef.current = caps;
226 const handlers = useMemo(() => {
227 const h: Record<string, () => void> = {
228 'messageActions:prev': () => navRef.current?.navigatePrev(),
229 'messageActions:next': () => navRef.current?.navigateNext(),
230 'messageActions:prevUser': () => navRef.current?.navigatePrevUser(),
231 'messageActions:nextUser': () => navRef.current?.navigateNextUser(),
232 'messageActions:top': () => navRef.current?.navigateTop(),
233 'messageActions:bottom': () => navRef.current?.navigateBottom(),
234 'messageActions:escape': () => setCursor(c => c?.expanded ? {
235 ...c,
236 expanded: false
237 } : null),
238 // ctrl+c skips the collapse step — from expanded-during-streaming, two-stage
239 // would mean 3 presses to interrupt (collapse→null→cancel).
240 'messageActions:ctrlc': () => setCursor(null)
241 };
242 for (const key of new Set(MESSAGE_ACTIONS.map(a_1 => a_1.key))) {
243 h[`messageActions:${key}`] = () => {
244 const c_0 = cursorRef.current;
245 if (!c_0) return;
246 const a_0 = MESSAGE_ACTIONS.find(a => a.key === key && isApplicable(a, c_0));
247 if (!a_0) return;
248 if (a_0.stays) {
249 setCursor(c_1 => c_1 ? {
250 ...c_1,
251 expanded: !c_1.expanded
252 } : null);
253 return;
254 }
255 const m = navRef.current?.getSelected();
256 if (!m) return;
257 (a_0.run as (m: NavigableMessage, c_0: MessageActionCaps) => void)(m, capsRef.current);
258 setCursor(null);
259 };
260 }
261 return h;
262 }, [setCursor, navRef]);
263 const enter = useCallback(() => {
264 logEvent('tengu_message_actions_enter', {});
265 navRef.current?.enterCursor();
266 }, [navRef]);
267 return {
268 enter,
269 handlers
270 };
271}
272
273// Must mount inside <KeybindingSetup>.
274export function MessageActionsKeybindings(t0) {

Callers 1

REPLFunction · 0.85

Calls 2

isApplicableFunction · 0.85
logEventFunction · 0.85

Tested by

no test coverage detected