A React Native app for the ultimate thinking partner.
at sdk-v1-upgrade 99 lines 2.9 kB view raw
1/** 2 * useMessageInteractions Hook 3 * 4 * Manages state and handlers for message interactions: 5 * - Expanding/collapsing reasoning blocks 6 * - Expanding/collapsing compaction summaries 7 * - Expanding/collapsing orphaned tool returns 8 * - Copying message content to clipboard 9 * 10 * Uses Set data structure for O(1) lookups and efficient state management. 11 */ 12 13import { useState, useCallback } from 'react'; 14import * as Clipboard from 'expo-clipboard'; 15 16export function useMessageInteractions() { 17 // State - using Sets for efficient O(1) lookups 18 const [expandedReasoning, setExpandedReasoning] = useState<Set<string>>(new Set()); 19 const [expandedCompaction, setExpandedCompaction] = useState<Set<string>>(new Set()); 20 const [expandedToolReturns, setExpandedToolReturns] = useState<Set<string>>(new Set()); 21 const [copiedMessageId, setCopiedMessageId] = useState<string | null>(null); 22 23 // Toggle reasoning expansion for a message 24 const toggleReasoning = useCallback((messageId: string) => { 25 setExpandedReasoning((prev) => { 26 const next = new Set(prev); 27 if (next.has(messageId)) { 28 next.delete(messageId); 29 } else { 30 next.add(messageId); 31 } 32 return next; 33 }); 34 }, []); 35 36 // Toggle compaction expansion for a message 37 const toggleCompaction = useCallback((messageId: string) => { 38 setExpandedCompaction((prev) => { 39 const next = new Set(prev); 40 if (next.has(messageId)) { 41 next.delete(messageId); 42 } else { 43 next.add(messageId); 44 } 45 return next; 46 }); 47 }, []); 48 49 // Toggle tool return expansion for a message 50 const toggleToolReturn = useCallback((messageId: string) => { 51 setExpandedToolReturns((prev) => { 52 const next = new Set(prev); 53 if (next.has(messageId)) { 54 next.delete(messageId); 55 } else { 56 next.add(messageId); 57 } 58 return next; 59 }); 60 }, []); 61 62 // Copy message content to clipboard with 2-second confirmation 63 const copyToClipboard = useCallback(async (content: string, messageId?: string) => { 64 try { 65 await Clipboard.setStringAsync(content); 66 if (messageId) { 67 setCopiedMessageId(messageId); 68 setTimeout(() => setCopiedMessageId(null), 2000); 69 } 70 } catch (error) { 71 console.error('Failed to copy to clipboard:', error); 72 } 73 }, []); 74 75 // Auto-expand reasoning for a message (doesn't toggle, just adds) 76 const expandReasoning = useCallback((messageId: string) => { 77 setExpandedReasoning((prev) => { 78 if (prev.has(messageId)) return prev; // Already expanded 79 const next = new Set(prev); 80 next.add(messageId); 81 return next; 82 }); 83 }, []); 84 85 return { 86 // State 87 expandedReasoning, 88 expandedCompaction, 89 expandedToolReturns, 90 copiedMessageId, 91 92 // Handlers 93 toggleReasoning, 94 toggleCompaction, 95 toggleToolReturn, 96 copyToClipboard, 97 expandReasoning, 98 }; 99}