|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { useCallback, useEffect, useRef, useState } from 'react'; |
|
|
import { ConsoleMessageItem } from '../types.js'; |
|
|
|
|
|
export interface UseConsoleMessagesReturn { |
|
|
consoleMessages: ConsoleMessageItem[]; |
|
|
handleNewMessage: (message: ConsoleMessageItem) => void; |
|
|
clearConsoleMessages: () => void; |
|
|
} |
|
|
|
|
|
export function useConsoleMessages(): UseConsoleMessagesReturn { |
|
|
const [consoleMessages, setConsoleMessages] = useState<ConsoleMessageItem[]>( |
|
|
[], |
|
|
); |
|
|
const messageQueueRef = useRef<ConsoleMessageItem[]>([]); |
|
|
const messageQueueTimeoutRef = useRef<number | null>(null); |
|
|
|
|
|
const processMessageQueue = useCallback(() => { |
|
|
if (messageQueueRef.current.length === 0) { |
|
|
return; |
|
|
} |
|
|
|
|
|
setConsoleMessages((prevMessages) => { |
|
|
const newMessages = [...prevMessages]; |
|
|
messageQueueRef.current.forEach((queuedMessage) => { |
|
|
if ( |
|
|
newMessages.length > 0 && |
|
|
newMessages[newMessages.length - 1].type === queuedMessage.type && |
|
|
newMessages[newMessages.length - 1].content === queuedMessage.content |
|
|
) { |
|
|
newMessages[newMessages.length - 1].count = |
|
|
(newMessages[newMessages.length - 1].count || 1) + 1; |
|
|
} else { |
|
|
newMessages.push({ ...queuedMessage, count: 1 }); |
|
|
} |
|
|
}); |
|
|
return newMessages; |
|
|
}); |
|
|
|
|
|
messageQueueRef.current = []; |
|
|
messageQueueTimeoutRef.current = null; |
|
|
}, []); |
|
|
|
|
|
const scheduleQueueProcessing = useCallback(() => { |
|
|
if (messageQueueTimeoutRef.current === null) { |
|
|
messageQueueTimeoutRef.current = setTimeout( |
|
|
processMessageQueue, |
|
|
0, |
|
|
) as unknown as number; |
|
|
} |
|
|
}, [processMessageQueue]); |
|
|
|
|
|
const handleNewMessage = useCallback( |
|
|
(message: ConsoleMessageItem) => { |
|
|
messageQueueRef.current.push(message); |
|
|
scheduleQueueProcessing(); |
|
|
}, |
|
|
[scheduleQueueProcessing], |
|
|
); |
|
|
|
|
|
const clearConsoleMessages = useCallback(() => { |
|
|
setConsoleMessages([]); |
|
|
if (messageQueueTimeoutRef.current !== null) { |
|
|
clearTimeout(messageQueueTimeoutRef.current); |
|
|
messageQueueTimeoutRef.current = null; |
|
|
} |
|
|
messageQueueRef.current = []; |
|
|
}, []); |
|
|
|
|
|
useEffect( |
|
|
() => |
|
|
|
|
|
() => { |
|
|
if (messageQueueTimeoutRef.current !== null) { |
|
|
clearTimeout(messageQueueTimeoutRef.current); |
|
|
} |
|
|
}, |
|
|
[], |
|
|
); |
|
|
|
|
|
return { consoleMessages, handleNewMessage, clearConsoleMessages }; |
|
|
} |
|
|
|