mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-06-25 11:18:43 +00:00
Update MessageBox.tsx
UI/UX improvements to the Reasoning Panel
This commit is contained in:
@ -49,27 +49,37 @@ const MessageBox = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const regex = /\[(\d+)\]/g;
|
const regex = /\[(\d+)\]/g;
|
||||||
|
const thinkRegex = /<think>(.*?)(?:<\/think>|$)(.*)/s;
|
||||||
|
|
||||||
// First check for thinking content
|
// Check for thinking content, including partial tags
|
||||||
const match = message.content.match(/<think>(.*?)<\/think>(.*)/s);
|
const match = message.content.match(thinkRegex);
|
||||||
if (match) {
|
if (match) {
|
||||||
const [_, thinkingContent, answerContent] = match;
|
const [_, thinkingContent, answerContent] = match;
|
||||||
setThinking(thinkingContent.trim());
|
|
||||||
setAnswer(answerContent.trim());
|
|
||||||
|
|
||||||
// Process the answer part for sources if needed
|
// Set thinking content even if </think> hasn't appeared yet
|
||||||
if (message.role === 'assistant' && message?.sources && message.sources.length > 0) {
|
if (thinkingContent) {
|
||||||
setParsedMessage(
|
setThinking(thinkingContent.trim());
|
||||||
answerContent.trim().replace(
|
setIsThinkingExpanded(true); // Auto-expand when thinking starts
|
||||||
regex,
|
}
|
||||||
(_, number) =>
|
|
||||||
`<a href="${message.sources?.[number - 1]?.metadata?.url}" target="_blank" className="bg-light-secondary dark:bg-dark-secondary px-1 rounded ml-1 no-underline text-xs text-black/70 dark:text-white/70 relative">${number}</a>`,
|
// Only set answer content if we have it (after </think>)
|
||||||
),
|
if (answerContent) {
|
||||||
);
|
setAnswer(answerContent.trim());
|
||||||
} else {
|
|
||||||
setParsedMessage(answerContent.trim());
|
// Process the answer part for sources if needed
|
||||||
|
if (message.role === 'assistant' && message?.sources && message.sources.length > 0) {
|
||||||
|
setParsedMessage(
|
||||||
|
answerContent.trim().replace(
|
||||||
|
regex,
|
||||||
|
(_, number) =>
|
||||||
|
`<a href="${message.sources?.[number - 1]?.metadata?.url}" target="_blank" className="bg-light-secondary dark:bg-dark-secondary px-1 rounded ml-1 no-underline text-xs text-black/70 dark:text-white/70 relative">${number}</a>`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setParsedMessage(answerContent.trim());
|
||||||
|
}
|
||||||
|
setSpeechMessage(answerContent.trim().replace(regex, ''));
|
||||||
}
|
}
|
||||||
setSpeechMessage(answerContent.trim().replace(regex, ''));
|
|
||||||
} else {
|
} else {
|
||||||
// No thinking content - process as before
|
// No thinking content - process as before
|
||||||
if (message.role === 'assistant' && message?.sources && message.sources.length > 0) {
|
if (message.role === 'assistant' && message?.sources && message.sources.length > 0) {
|
||||||
@ -105,37 +115,6 @@ const MessageBox = ({
|
|||||||
ref={dividerRef}
|
ref={dividerRef}
|
||||||
className="flex flex-col space-y-6 w-full lg:w-9/12"
|
className="flex flex-col space-y-6 w-full lg:w-9/12"
|
||||||
>
|
>
|
||||||
{thinking && (
|
|
||||||
<div className="flex flex-col space-y-2 mb-4">
|
|
||||||
<button
|
|
||||||
onClick={() => setIsThinkingExpanded(!isThinkingExpanded)}
|
|
||||||
className="flex flex-row items-center space-x-2 group text-black/70 dark:text-white/70 hover:text-black dark:hover:text-white transition duration-200"
|
|
||||||
>
|
|
||||||
<Brain size={20} />
|
|
||||||
<h3 className="font-medium text-xl">View Thinking</h3>
|
|
||||||
<ChevronDown
|
|
||||||
size={16}
|
|
||||||
className={cn(
|
|
||||||
"transition-transform duration-200",
|
|
||||||
isThinkingExpanded ? "rotate-180" : ""
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{isThinkingExpanded && (
|
|
||||||
<div className="rounded-lg bg-light-secondary/50 dark:bg-dark-secondary/50 p-4">
|
|
||||||
<Markdown
|
|
||||||
className={cn(
|
|
||||||
'prose dark:prose-invert text-sm leading-relaxed',
|
|
||||||
'max-w-none break-words'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{thinking}
|
|
||||||
</Markdown>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{message.sources && message.sources.length > 0 && (
|
{message.sources && message.sources.length > 0 && (
|
||||||
<div className="flex flex-col space-y-2">
|
<div className="flex flex-col space-y-2">
|
||||||
<div className="flex flex-row items-center space-x-2">
|
<div className="flex flex-row items-center space-x-2">
|
||||||
@ -147,27 +126,71 @@ const MessageBox = ({
|
|||||||
<MessageSources sources={message.sources} />
|
<MessageSources sources={message.sources} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex flex-col space-y-2">
|
<div className="flex flex-col space-y-4">
|
||||||
<div className="flex flex-row items-center space-x-2">
|
{thinking && (
|
||||||
<Disc3
|
<div className="flex flex-col space-y-2 mb-4">
|
||||||
className={cn(
|
<button
|
||||||
'text-black dark:text-white',
|
onClick={() => setIsThinkingExpanded(!isThinkingExpanded)}
|
||||||
isLast && loading ? 'animate-spin' : 'animate-none',
|
className="flex flex-row items-center space-x-2 group text-black/70 dark:text-white/70 hover:text-black dark:hover:text-white transition duration-200"
|
||||||
|
>
|
||||||
|
<Brain size={20} />
|
||||||
|
<h3 className="font-medium text-xl">Reasoning</h3>
|
||||||
|
<ChevronDown
|
||||||
|
size={16}
|
||||||
|
className={cn(
|
||||||
|
"transition-transform duration-200",
|
||||||
|
isThinkingExpanded ? "rotate-180" : ""
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{isThinkingExpanded && (
|
||||||
|
<div className="rounded-lg bg-light-secondary/50 dark:bg-dark-secondary/50 p-4">
|
||||||
|
{thinking.split('\n\n').map((paragraph, index) => {
|
||||||
|
if (!paragraph.trim()) return null;
|
||||||
|
|
||||||
|
const content = paragraph.replace(/^[•\-\d.]\s*/, '');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={index} className="mb-2 last:mb-0">
|
||||||
|
<details className="group [&_summary::-webkit-details-marker]:hidden">
|
||||||
|
<summary className="flex items-center cursor-pointer list-none text-sm text-black/70 dark:text-white/70 hover:text-black dark:hover:text-white">
|
||||||
|
<span className="arrow mr-2 inline-block transition-transform duration-200 group-open:rotate-90 group-open:self-start group-open:mt-1">▸</span>
|
||||||
|
<p className="relative whitespace-normal line-clamp-1 group-open:line-clamp-none after:content-['...'] after:inline group-open:after:hidden transition-all duration-200 text-ellipsis overflow-hidden group-open:overflow-visible">
|
||||||
|
{content}
|
||||||
|
</p>
|
||||||
|
</summary>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
size={20}
|
</div>
|
||||||
/>
|
)}
|
||||||
<h3 className="text-black dark:text-white font-medium text-xl">
|
|
||||||
Answer
|
<div className="flex flex-col space-y-2">
|
||||||
</h3>
|
<div className="flex flex-row items-center space-x-2">
|
||||||
|
<Disc3
|
||||||
|
className={cn(
|
||||||
|
'text-black dark:text-white',
|
||||||
|
isLast && loading ? 'animate-spin' : 'animate-none',
|
||||||
|
)}
|
||||||
|
size={20}
|
||||||
|
/>
|
||||||
|
<h3 className="text-black dark:text-white font-medium text-xl">
|
||||||
|
Answer
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<Markdown
|
||||||
|
className={cn(
|
||||||
|
'prose prose-h1:mb-3 prose-h2:mb-2 prose-h2:mt-6 prose-h2:font-[800] prose-h3:mt-4 prose-h3:mb-1.5 prose-h3:font-[600] dark:prose-invert prose-p:leading-relaxed prose-pre:p-0 font-[400]',
|
||||||
|
'max-w-none break-words text-black dark:text-white',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{parsedMessage}
|
||||||
|
</Markdown>
|
||||||
</div>
|
</div>
|
||||||
<Markdown
|
|
||||||
className={cn(
|
|
||||||
'prose prose-h1:mb-3 prose-h2:mb-2 prose-h2:mt-6 prose-h2:font-[800] prose-h3:mt-4 prose-h3:mb-1.5 prose-h3:font-[600] dark:prose-invert prose-p:leading-relaxed prose-pre:p-0 font-[400]',
|
|
||||||
'max-w-none break-words text-black dark:text-white',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{parsedMessage}
|
|
||||||
</Markdown>
|
|
||||||
{loading && isLast ? null : (
|
{loading && isLast ? null : (
|
||||||
<div className="flex flex-row items-center justify-between w-full text-black dark:text-white py-4 -mx-2">
|
<div className="flex flex-row items-center justify-between w-full text-black dark:text-white py-4 -mx-2">
|
||||||
<div className="flex flex-row items-center space-x-1">
|
<div className="flex flex-row items-center space-x-1">
|
||||||
|
Reference in New Issue
Block a user