Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
"scripts": {
"clean": "rm -rf dist && rm -rf es && rm -rf lib",
"prebuild": "npm run clean",
"prefix": "NODE_ENV=production postcss dist/index.css -o dist/index.css",
"prefix": "cross-env NODE_ENV=production postcss dist/index.css -o dist/index.css",
"copy:less": "copyfiles -u 1 src/**/*.less src/**/**/*.less es",
"js:cjs": "BABEL_ENV=cjs babel src -d lib --extensions '.ts,.tsx'",
"js:esm": "BABEL_ENV=esm babel src -d es --extensions '.ts,.tsx'",
"js:cjs": "cross-env BABEL_ENV=cjs babel src -d lib --extensions '.ts,.tsx'",
"js:esm": "cross-env BABEL_ENV=esm babel src -d es --extensions '.ts,.tsx'",
"build:types": "tsc -p tsconfig.build.json",
"build": "npm run js:cjs && npm run js:esm && npm run build:types",
"build:css": "lessc src/styles/index.less dist/index.css && npm run prefix && npm run copy:less",
"build:umd": "BABEL_ENV=umd rollup -c && npm run build:css",
"build:umd": "cross-env BABEL_ENV=umd rollup -c && npm run build:css",
"prepublishOnly": "npm run build && npm run build:umd",
"test": "jest",
"test:watch": "jest --watch",
Expand Down Expand Up @@ -62,6 +62,7 @@
"@typescript-eslint/parser": "^5.60.1",
"autoprefixer": "^10.4.14",
"copyfiles": "^2.4.1",
"cross-env": "^10.0.0",
"cssnano": "^6.0.1",
"eslint": "^8.44.0",
"eslint-config-airbnb": "^19.0.4",
Expand Down
2 changes: 2 additions & 0 deletions src/components/Chat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export const Chat = React.forwardRef<HTMLDivElement, ChatProps>((props, ref) =>
rightAction,
Composer = DComposer,
isX,
scrollBehaviorConfig,
} = props;
const [currentColorScheme, setCurrentColorScheme] = useState<'light' | 'dark'>('light');

Expand Down Expand Up @@ -252,6 +253,7 @@ export const Chat = React.forwardRef<HTMLDivElement, ChatProps>((props, ref) =>
onScroll={onScroll}
onBackBottomShow={onBackBottomShow}
onBackBottomClick={onBackBottomClick}
scrollBehaviorConfig={scrollBehaviorConfig}
/>
<div className="ChatFooter">
{renderQuickReplies ? (
Expand Down
55 changes: 47 additions & 8 deletions src/components/MessageContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ import getToBottom from '../../utils/getToBottom';

const listenerOpts = canUse('passiveListener') ? { passive: true } : false;

const DEFAULT_FOLLOW_SCREEN = 2;

export interface ScrollBehaviorConfig {
/** 是否跟随自己发的消息,默认 true */
followSelf?: boolean;
/** 是否跟随收到的消息,默认 true */
followIncoming?: boolean;
/** 不在底部时是否显示新消息数量,默认 true */
showNewCount?: boolean;
/** 距离多少屏以内才自动跟随,默认 2 */
followScreen?: number;
}

export interface MessageContainerProps {
messages: MessageProps[];
renderMessageContent: (message: MessageProps) => React.ReactNode;
Expand All @@ -19,6 +32,8 @@ export interface MessageContainerProps {
renderBeforeMessageList?: () => React.ReactNode;
onBackBottomShow?: () => void;
onBackBottomClick?: () => void;
/** 滚动行为配置 */
scrollBehaviorConfig?: ScrollBehaviorConfig;
}

export interface MessageContainerHandle {
Expand All @@ -43,6 +58,7 @@ export const MessageContainer = React.forwardRef<MessageContainerHandle, Message
renderMessageContent,
onBackBottomShow,
onBackBottomClick,
scrollBehaviorConfig = {},
} = props;

const [showBackBottom, setShowBackBottom] = useState(false);
Expand All @@ -52,6 +68,7 @@ export const MessageContainer = React.forwardRef<MessageContainerHandle, Message
const messagesRef = useRef<HTMLDivElement>(null);
const scrollerRef = useRef<PullToRefreshHandle>(null);
const lastMessage = messages[messages.length - 1];
const scrollBehaviorConfigRef = useRef<ScrollBehaviorConfig>(scrollBehaviorConfig);

const clearBackBottom = () => {
setNewCount(0);
Expand Down Expand Up @@ -115,23 +132,45 @@ export const MessageContainer = React.forwardRef<MessageContainerHandle, Message
showBackBottomtRef.current = showBackBottom;
}, [showBackBottom]);

useEffect(() => {
scrollBehaviorConfigRef.current = scrollBehaviorConfig;
}, [scrollBehaviorConfig]);

useEffect(() => {
const scroller = scrollerRef.current;
const wrapper = scroller && scroller.wrapperRef.current;

if (!wrapper || !lastMessage || lastMessage.position === 'pop') {
return;
}

const {
followSelf = true,
followIncoming = true,
followScreen = DEFAULT_FOLLOW_SCREEN,
showNewCount = true,
} = scrollBehaviorConfigRef.current;


if (lastMessage.position === 'right') {
// 自己发的消息,强制滚动到底部
scrollToEnd({ force: true });
} else if (isNearBottom(wrapper, 2)) {
const animated = !!wrapper.scrollTop;
scrollToEnd({ animated, force: true });
// 自己发的消息
if (followSelf) {
scrollToEnd({ force: true });
}
} else {
setNewCount((c) => c + 1);
setShowBackBottom(true);
// 收到的消息
if (followIncoming && isNearBottom(wrapper, followScreen)) {
const animated = !!wrapper.scrollTop;
scrollToEnd({ animated, force: true });
} else {
// 防止滚动条较底下的时候出现回到底部的按钮
if (!isNearBottom(wrapper, Math.max(followScreen, DEFAULT_FOLLOW_SCREEN))) {
if (showNewCount) {
setNewCount((c) => c + 1);
}
setShowBackBottom(true);
}
}
}
}, [lastMessage, scrollToEnd]);

Expand Down