MCPcopy Create free account
hub / github.com/DTStack/dt-react-component / useTyping

Function useTyping

src/useTyping/index.ts:20–148  ·  view source on GitHub ↗
({ onTyping }: { onTyping: (post: string) => void })

Source from the content-addressed store, hash-verified

18 * ```
19 */
20export default function useTyping({ onTyping }: { onTyping: (post: string) => void }) {
21 const interval = useRef<number>();
22 const queue = useRef<string>('');
23 const typingCountOnTime = useRef<number>(1);
24 const beginIndex = useRef<number>(0);
25 const isStart = useRef<boolean>(false);
26 const [isTyping, toggleIsTyping] = useState<boolean>(false);
27
28 const closeSignal = useRef(false);
29 const closeInterval = useRef<number>(0);
30
31 function getTypingWordCount() {
32 const remainWordsLength = queue.current.length - beginIndex.current - 1;
33 const typingTimes = 1000 / typingInterval;
34 // 保证剩余内容在一秒内输出完
35 typingCountOnTime.current = Math.ceil(remainWordsLength / typingTimes);
36 }
37
38 function getNextChunkPosition() {
39 const rest = queue.current.slice(beginIndex.current);
40 const chunk = rest.slice(0, typingCountOnTime.current);
41 const validHTMLTagRegex = /<[a-zA-Z]{0,4}\s[^<]*>/;
42 // 确保在 typing 的过程中,HTML 标签不被分割
43 if (validHTMLTagRegex.test(rest) && !validHTMLTagRegex.test(chunk)) {
44 const match = rest.match(validHTMLTagRegex)!;
45 const tag = match[0];
46 const index = rest.indexOf(tag);
47 return beginIndex.current + index + tag.length;
48 }
49 return beginIndex.current + typingCountOnTime.current;
50 }
51
52 function startTyping() {
53 if (interval.current) return;
54 interval.current = window.setInterval(() => {
55 if (beginIndex.current < queue.current.length) {
56 const str = queue.current;
57 const idx = getNextChunkPosition();
58 const next = str.slice(0, idx);
59 onTyping(next);
60 beginIndex.current = next.length;
61 } else if (!isStart.current) {
62 // 如果发送了全部的消息且信号关闭,则清空队列
63 window.clearInterval(interval.current);
64 interval.current = 0;
65 toggleIsTyping(false);
66 closeSignal.current = false;
67 }
68 // 如果发送了全部的消息,但是信号没有关闭,则什么都不做继续轮训等待新的消息
69 }, typingInterval);
70 }
71
72 useEffect(() => {
73 return () => {
74 window.clearInterval(interval.current);
75 window.clearInterval(closeInterval.current);
76 interval.current = 0;
77 };

Callers 3

useChatFunction · 0.85
basic.tsxFile · 0.85
useTyping.test.tsFile · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected