forked from 77media/video-flow
chatbox 修复自动滚动问题
This commit is contained in:
parent
670be3cbbb
commit
27fd4b3a14
@ -44,14 +44,19 @@ export function InputBar({ onSend }: InputBarProps) {
|
|||||||
|
|
||||||
const onFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
const onFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const file = e.target.files?.[0];
|
const file = e.target.files?.[0];
|
||||||
|
// 保存对 input 元素的引用
|
||||||
|
const inputElement = e.currentTarget;
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
if (!file.type.startsWith('image/')) {
|
if (!file.type.startsWith('image/')) {
|
||||||
alert('请选择图片文件');
|
alert('请选择图片文件');
|
||||||
|
inputElement.value = ""; // 重置 input
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await handleFileUpload(file);
|
await handleFileUpload(file);
|
||||||
|
// 使用保存的引用重置 input
|
||||||
|
inputElement.value = "";
|
||||||
}
|
}
|
||||||
e.currentTarget.value = ""; // reset
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeImage = () => {
|
const removeImage = () => {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export function LoadMoreButton({ onClick, loading = false }: LoadMoreButtonProps
|
|||||||
<button
|
<button
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="w-full flex items-center justify-center gap-2 text-sm text-gray-400 hover:text-gray-300 hover:bg-gray-800/30 transition-colors disabled:opacity-50"
|
className="w-full flex items-center justify-center gap-2 text-sm text-gray-400 hover:text-gray-300 hover:bg-gray-800/30 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
data-alt="load-more-button"
|
data-alt="load-more-button"
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
|
|||||||
@ -143,6 +143,7 @@ export function useMessages({ config, onMessagesUpdate }: UseMessagesProps): [Me
|
|||||||
if (timeoutIdRef.current) {
|
if (timeoutIdRef.current) {
|
||||||
clearTimeout(timeoutIdRef.current);
|
clearTimeout(timeoutIdRef.current);
|
||||||
}
|
}
|
||||||
|
isPollingRef.current = true; // 设置轮询标志,防止其他轮询启动
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 立即添加用户消息(临时显示)
|
// 立即添加用户消息(临时显示)
|
||||||
@ -157,13 +158,19 @@ export function useMessages({ config, onMessagesUpdate }: UseMessagesProps): [Me
|
|||||||
|
|
||||||
// 无论是否在查看历史,发送消息后都切换到最新视图
|
// 无论是否在查看历史,发送消息后都切换到最新视图
|
||||||
isViewingHistoryRef.current = false;
|
isViewingHistoryRef.current = false;
|
||||||
setDisplayMessages(prev => mergeMessages(prev, [userMessage]));
|
setDisplayMessages(prev => {
|
||||||
|
const newMessages = mergeMessages(prev, [userMessage]);
|
||||||
|
// 在 setState 的回调中触发滚动,确保消息已更新到界面
|
||||||
|
setTimeout(() => onMessagesUpdate?.(true), 0);
|
||||||
|
return newMessages;
|
||||||
|
});
|
||||||
|
|
||||||
// 发送到服务器
|
// 发送到服务器
|
||||||
await sendMessage(blocks, configRef.current);
|
await sendMessage(blocks, configRef.current);
|
||||||
|
|
||||||
// 立即获取最新的消息列表
|
// 立即获取最新的消息列表
|
||||||
await updateMessages(false);
|
await updateMessages(false);
|
||||||
|
onMessagesUpdate?.(true);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("发送消息失败:", err);
|
console.error("发送消息失败:", err);
|
||||||
setError(err instanceof Error ? err : new Error("发送消息失败"));
|
setError(err instanceof Error ? err : new Error("发送消息失败"));
|
||||||
@ -172,9 +179,10 @@ export function useMessages({ config, onMessagesUpdate }: UseMessagesProps): [Me
|
|||||||
|
|
||||||
// 恢复轮询
|
// 恢复轮询
|
||||||
if (systemPush) {
|
if (systemPush) {
|
||||||
|
isPollingRef.current = false;
|
||||||
|
// 延迟一个轮询间隔后再开始轮询
|
||||||
timeoutIdRef.current = setTimeout(() => {
|
timeoutIdRef.current = setTimeout(() => {
|
||||||
isPollingRef.current = false;
|
poll();
|
||||||
updateMessages(false);
|
|
||||||
}, POLLING_INTERVAL);
|
}, POLLING_INTERVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,24 +231,25 @@ export function useMessages({ config, onMessagesUpdate }: UseMessagesProps): [Me
|
|||||||
});
|
});
|
||||||
}, [latestMessages, filterMessages]);
|
}, [latestMessages, filterMessages]);
|
||||||
|
|
||||||
|
// 定义轮询函数
|
||||||
|
const poll = useCallback(async () => {
|
||||||
|
if (isPollingRef.current) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
isPollingRef.current = true;
|
||||||
|
await updateMessages(false);
|
||||||
|
} finally {
|
||||||
|
isPollingRef.current = false;
|
||||||
|
if (systemPush) {
|
||||||
|
timeoutIdRef.current = setTimeout(poll, POLLING_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [systemPush, updateMessages]);
|
||||||
|
|
||||||
// 轮询获取最新消息
|
// 轮询获取最新消息
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!systemPush) return;
|
if (!systemPush) return;
|
||||||
|
|
||||||
const poll = async () => {
|
|
||||||
if (isPollingRef.current) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
isPollingRef.current = true;
|
|
||||||
await updateMessages(false);
|
|
||||||
} finally {
|
|
||||||
isPollingRef.current = false;
|
|
||||||
if (systemPush) {
|
|
||||||
timeoutIdRef.current = setTimeout(poll, POLLING_INTERVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
poll();
|
poll();
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@ -248,7 +257,7 @@ export function useMessages({ config, onMessagesUpdate }: UseMessagesProps): [Me
|
|||||||
clearTimeout(timeoutIdRef.current);
|
clearTimeout(timeoutIdRef.current);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [systemPush, updateMessages]);
|
}, [systemPush, poll]);
|
||||||
|
|
||||||
// 初始加载
|
// 初始加载
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user