����JFIF���������
__ __ __ __ _____ _ _ _____ _ _ _ | \/ | \ \ / / | __ \ (_) | | / ____| | | | | | \ / |_ __\ V / | |__) | __ ___ ____ _| |_ ___ | (___ | |__ ___| | | | |\/| | '__|> < | ___/ '__| \ \ / / _` | __/ _ \ \___ \| '_ \ / _ \ | | | | | | |_ / . \ | | | | | |\ V / (_| | || __/ ____) | | | | __/ | | |_| |_|_(_)_/ \_\ |_| |_| |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1 if you need WebShell for Seo everyday contact me on Telegram Telegram Address : @jackleetFor_More_Tools:
import { AgentMessage } from '@agent/components/messages/AgentMessage';
import { StatusIndicator } from '@agent/components/messages/StatusIndicator';
import { UserMessage } from '@agent/components/messages/UserMessage';
import { WorkflowComponent } from '@agent/components/messages/WorkflowComponent';
import { WorkflowMessage } from '@agent/components/messages/WorkflowMessage';
import { ScrollDownButton } from '@agent/components/ScrollDownButton';
import { ScrollIntoViewOnce } from '@agent/components/ScrollIntoViewOnce';
import { useWhenFinishedToolProps } from '@agent/hooks/useWhenFinishedToolProps';
import { useChatStore } from '@agent/state/chat';
import { useGlobalStore } from '@agent/state/global';
import { useWorkflowStore } from '@agent/state/workflows';
import {
createElement,
useEffect,
useLayoutEffect,
useRef,
useState,
} from '@wordpress/element';
export const ChatMessages = () => {
const { open } = useGlobalStore();
const { messages } = useChatStore();
const { getWorkflow } = useWorkflowStore();
const workflow = getWorkflow();
const whenFinishedToolProps = useWhenFinishedToolProps();
const whenFinishedComponent = workflow?.whenFinished?.component;
const [canScrollDown, setCanScrollDown] = useState(false);
const containerRef = useRef(null);
const isFreshPageLoad = useRef(true);
const [ready, setReady] = useState(false);
// If last message is a user message, move it to the top
const isUserMessage = messages.at(-1)?.details?.role === 'user';
useEffect(() => {
if (!containerRef.current || !open) return;
if (!isFreshPageLoad.current) return;
isFreshPageLoad.current = false;
// Scroll to the bottom of the chat container on load
const c = containerRef.current;
const last = c.querySelector(
'#extendify-agent-chat-scroll-area > :last-child',
);
let id2;
const id = requestAnimationFrame(() => {
id2 = requestAnimationFrame(() => {
last?.scrollIntoView({ behavior: 'auto', block: 'start' });
setReady(true);
});
});
return () => {
cancelAnimationFrame(id);
cancelAnimationFrame(id2);
isFreshPageLoad.current = true;
setReady(false);
};
}, [open]);
// Handles scrolling to the top of the last user message
// TODO: if the user sends in a long message, maybe we scroll to the bottom
// of the message offset by 2-3 lines
useEffect(() => {
if (!containerRef.current) return;
if (!isUserMessage) return;
const c = containerRef.current;
const messages = c.querySelectorAll('[data-agent-message-role="user"]');
const last = messages[messages.length - 1];
if (!last || messages.length < 2) return;
const scrollArea = c.querySelector('#extendify-agent-chat-scroll-area');
const lastRect = last.getBoundingClientRect();
const innerHeight = Array.from(scrollArea.children).reduce(
(sum, child) => sum + child.offsetHeight,
0,
);
const minHeight = innerHeight + c.clientHeight - lastRect.height;
scrollArea.style.minHeight = `${minHeight}px`;
last.scrollIntoView({ behavior: 'smooth', block: 'start' });
}, [isUserMessage, messages]);
// Handles the scroll down button visibility
useLayoutEffect(() => {
const c = containerRef.current;
if (!c) return;
const last = c.querySelector(
'#extendify-agent-chat-scroll-area > :last-child',
);
if (!last) return;
const areWeAtBottom = c.scrollTop + c.clientHeight >= c.scrollHeight - 4;
if (areWeAtBottom) return setCanScrollDown(false);
const observer = new IntersectionObserver(
([entry]) => {
const last = c.querySelector(
'#extendify-agent-chat-scroll-area > :last-child',
);
if (!last) return setCanScrollDown(false);
const areWeAtBottom =
c.scrollTop + c.clientHeight >= c.scrollHeight - 4;
if (areWeAtBottom) return setCanScrollDown(false);
setCanScrollDown(!entry.isIntersecting);
},
{ root: c, threshold: 0.1 },
);
observer.observe(last);
return () => observer.disconnect();
}, [messages]);
return (
<div
ref={containerRef}
style={{ overscrollBehavior: 'contain' }}
className="relative grow overflow-y-auto overflow-x-hidden p-1 pb-0 text-sm text-gray-900 md:p-2 scheme-light"
>
<div
id="extendify-agent-chat-scroll-area"
className={ready ? '' : 'invisible pointer-events-none'}
>
{messages.map((message) => {
const freshLoad = isFreshPageLoad.current;
if (message.details?.role === 'user') {
return <UserMessage key={message.id} message={message} />;
}
if (message.details?.role === 'assistant') {
return (
<AgentMessage
key={message.id}
animate={!freshLoad}
message={message}
/>
);
}
if (message.type === 'workflow') {
return <WorkflowMessage key={message.id} message={message} />;
}
if (message.type === 'workflow-component') {
return <WorkflowComponent key={message.id} message={message} />;
}
return null;
})}
<StatusIndicator />
{!workflow?.needsRedirect?.() &&
whenFinishedToolProps?.id &&
whenFinishedComponent ? (
<ScrollIntoViewOnce>
{createElement(whenFinishedComponent, whenFinishedToolProps)}
</ScrollIntoViewOnce>
) : null}
{workflow?.needsRedirect?.() ? <workflow.redirectComponent /> : null}
</div>
<ScrollDownButton
canScrollDown={canScrollDown}
onClick={() => {
if (!containerRef.current) return;
const c = containerRef.current;
// Scroll the last message into view
const last = c.querySelector(
'#extendify-agent-chat-scroll-area > :last-child',
);
if (!last) return;
last.scrollIntoView({ behavior: 'smooth', block: 'start' });
}}
/>
</div>
);
};
| Name | Type | Size | Permission | Actions |
|---|---|---|---|---|
| buttons | Folder | 0755 |
|
|
| layouts | Folder | 0755 |
|
|
| messages | Folder | 0755 |
|
|
| redirects | Folder | 0755 |
|
|
| ChatInput.jsx | File | 6.88 KB | 0644 |
|
| ChatMessages.jsx | File | 5.55 KB | 0644 |
|
| ChatSuggestions.jsx | File | 3.75 KB | 0644 |
|
| ChatTools.jsx | File | 1.35 KB | 0644 |
|
| DOMHighlighter.jsx | File | 8.25 KB | 0644 |
|
| ErrorMessage.jsx | File | 872 B | 0644 |
|
| GuidedTour.jsx | File | 14.88 KB | 0644 |
|
| ImageUploader.jsx | File | 6.03 KB | 0644 |
|
| OptionsPopover.jsx | File | 5.36 KB | 0644 |
|
| PageDocument.jsx | File | 1.06 KB | 0644 |
|
| Rating.jsx | File | 1.85 KB | 0644 |
|
| ScrollDownButton.jsx | File | 1.1 KB | 0644 |
|
| ScrollIntoViewOnce.jsx | File | 876 B | 0644 |
|