Skip to content

Commit

Permalink
feat: useXAgent (#125)
Browse files Browse the repository at this point in the history
* chore: bubble variant

* chore: customize

* chore: lock typing if first render

* chore: tmp record

* chore: seq list

* docs: add api doc

* test: coverage

* test: update snapshot

* chore: defaultMessages no need fill all

* refactor: rename

* chore: tmp of ts def

* chore: base fin

* chore: demo of it

* chore: arr return

* docs: demo of streaming

* docs: api

* test: of useXAgent

* test: coverage

* chore: fix demo
  • Loading branch information
zombieJ authored Sep 26, 2024
1 parent 6f253ad commit 25d0490
Show file tree
Hide file tree
Showing 47 changed files with 2,920 additions and 101 deletions.
4 changes: 3 additions & 1 deletion .dumi/theme/themeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export default {
'Data Display': 4,
Feedback: 5,
Other: 6,
Deprecated: 7,
Runtime: 7,
Deprecated: 8,

组件总览: -1,
通用: 0,
Expand All @@ -30,6 +31,7 @@ export default {
数据展示: 4,
反馈: 5,
其他: 6,
运行时: 8,
废弃: 7,

// Design
Expand Down
21 changes: 19 additions & 2 deletions components/bubble/Bubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const Bubble: React.ForwardRefRenderFunction<BubbleRef, BubbleProps> = (props, r
typing,
content = '',
messageRender,
variant = 'filled',
onTypingComplete,
...otherHtmlProps
} = props;

Expand Down Expand Up @@ -68,6 +70,20 @@ const Bubble: React.ForwardRefRenderFunction<BubbleRef, BubbleProps> = (props, r
onUpdate?.();
}, [typedContent]);

const triggerTypingCompleteRef = React.useRef(false);
React.useEffect(() => {
if (!isTyping && !loading) {
// StrictMode will trigger this twice,
// So we need a flag to avoid that
if (!triggerTypingCompleteRef.current) {
triggerTypingCompleteRef.current = true;
onTypingComplete?.();
}
} else {
triggerTypingCompleteRef.current = false;
}
}, [isTyping, loading]);

// ============================ Styles ============================
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);

Expand All @@ -89,7 +105,7 @@ const Bubble: React.ForwardRefRenderFunction<BubbleRef, BubbleProps> = (props, r
const avatarNode = React.isValidElement(avatar) ? avatar : <Avatar {...avatar} />;

// =========================== Content ============================
const mergedContent = messageRender ? messageRender(typedContent) : typedContent;
const mergedContent = messageRender ? messageRender(typedContent as any) : typedContent;

// ============================ Render ============================
return wrapCSSVar(
Expand Down Expand Up @@ -127,11 +143,12 @@ const Bubble: React.ForwardRefRenderFunction<BubbleRef, BubbleProps> = (props, r
}}
className={classnames(
`${prefixCls}-content`,
`${prefixCls}-content-${variant}`,
contextConfig.classNames.content,
classNames.content,
)}
>
{loading ? <Loading prefixCls={prefixCls} /> : mergedContent}
{loading ? <Loading prefixCls={prefixCls} /> : (mergedContent as React.ReactNode)}
</div>
</div>,
);
Expand Down
28 changes: 23 additions & 5 deletions components/bubble/BubbleList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as React from 'react';
import { useXProviderContext } from '../x-provider';
import Bubble, { BubbleContext } from './Bubble';
import type { BubbleRef } from './Bubble';
import useDisplayData from './hooks/useDisplayData';
import useListData from './hooks/useListData';
import type { BubbleProps } from './interface';
import useStyle from './style';
Expand Down Expand Up @@ -64,9 +65,21 @@ const BubbleList: React.ForwardRefRenderFunction<BubbleListRef, BubbleListProps>

const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);

// ============================ Typing ============================
const [initialized, setInitialized] = React.useState(false);

React.useEffect(() => {
setInitialized(true);
return () => {
setInitialized(false);
};
}, []);

// ============================= Data =============================
const mergedData = useListData(items, roles);

const [displayData, onTypingComplete] = useDisplayData(mergedData);

// ============================ Scroll ============================
// Is current scrollTop at the end. User scroll will make this false.
const [scrollReachEnd, setScrollReachEnd] = React.useState(true);
Expand All @@ -91,7 +104,7 @@ const BubbleList: React.ForwardRefRenderFunction<BubbleListRef, BubbleListProps>
React.useEffect(() => {
if (autoScroll) {
// New date come, the origin last one is the second last one
const lastItemKey = mergedData[mergedData.length - 2]?.key;
const lastItemKey = displayData[displayData.length - 2]?.key;
const bubbleInst = bubbleRefs.current[lastItemKey!];

// Auto scroll if last 2 item is visible
Expand All @@ -107,7 +120,7 @@ const BubbleList: React.ForwardRefRenderFunction<BubbleListRef, BubbleListProps>
}
}
}
}, [mergedData.length]);
}, [displayData.length]);

// ========================== Outer Ref ===========================
React.useImperativeHandle(ref, () => ({
Expand All @@ -125,8 +138,8 @@ const BubbleList: React.ForwardRefRenderFunction<BubbleListRef, BubbleListProps>

if (bubbleInst) {
// Block current auto scrolling
const index = mergedData.findIndex((dataItem) => dataItem.key === key);
setScrollReachEnd(index === mergedData.length - 1);
const index = displayData.findIndex((dataItem) => dataItem.key === key);
setScrollReachEnd(index === displayData.length - 1);

// Do native scroll
bubbleInst.nativeElement.scrollIntoView({
Expand Down Expand Up @@ -164,7 +177,7 @@ const BubbleList: React.ForwardRefRenderFunction<BubbleListRef, BubbleListProps>
ref={listRef}
onScroll={onInternalScroll}
>
{mergedData.map(({ key, ...bubble }) => (
{displayData.map(({ key, ...bubble }) => (
<Bubble
{...bubble}
key={key}
Expand All @@ -175,6 +188,11 @@ const BubbleList: React.ForwardRefRenderFunction<BubbleListRef, BubbleListProps>
delete bubbleRefs.current[key];
}
}}
typing={initialized ? bubble.typing : false}
onTypingComplete={() => {
bubble.onTypingComplete?.();
onTypingComplete(key);
}}
/>
))}
</div>
Expand Down
Loading

0 comments on commit 25d0490

Please sign in to comment.