forked from Tadrisino/MathApp_frontend
tutor wait: the thinking bubble moves through stages instead of one fixed line
The model provider holds the whole answer and sends it at once; a full answer with a diagram took about 30 s on 2026-09-29. A fixed 'thinking' line for that long looked stuck. The stage times are approximate and not tied to what the server is actually doing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -212,6 +212,42 @@ function Bubble({ role, children, extra }: { role: 'user' | 'assistant'; childre
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* منتظرِ جوابِ دستیار. سرویسِ مدل کلِ جواب را نگه میدارد و یکجا میفرستد؛ جوابِ
|
||||||
|
* کامل با شکل در ۲۰۲۶-۰۹-۲۹ حدودِ ۳۰ ثانیه طول کشید. پیامِ ثابت در آن مدت شبیهِ
|
||||||
|
* گیر کردن بود، پس متن با زمان جلو میرود. زمانها تقریبیاند و به مرحلهی واقعیِ
|
||||||
|
* سرور وصل نیستند.
|
||||||
|
*/
|
||||||
|
const THINKING_STEPS: [number, string][] = [
|
||||||
|
[0, 'پی داره تو کتابت میگرده'],
|
||||||
|
[4, 'پی داره حلش میکنه'],
|
||||||
|
[15, 'داره قدمها رو مرتب مینویسه'],
|
||||||
|
[28, 'جوابِ کامل یه کم طول میکشه، الان میرسه'],
|
||||||
|
];
|
||||||
|
|
||||||
|
function Thinking() {
|
||||||
|
const [seconds, setSeconds] = useState(0);
|
||||||
|
useEffect(() => {
|
||||||
|
const started = Date.now();
|
||||||
|
const timer = setInterval(() => setSeconds((Date.now() - started) / 1000), 1000);
|
||||||
|
return () => clearInterval(timer);
|
||||||
|
}, []);
|
||||||
|
const text = [...THINKING_STEPS].reverse().find(([at]) => seconds >= at)![1];
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="flex h-8 w-8 flex-shrink-0 items-center justify-center overflow-hidden rounded-full bg-[#f5f1ff]">
|
||||||
|
<SeyarMascot char="pi" mood="idle" size={32} />
|
||||||
|
</span>
|
||||||
|
<div className="flex items-center gap-2 rounded-2xl border border-line bg-white px-4 py-3 text-xs text-muted" aria-live="polite">
|
||||||
|
{text}
|
||||||
|
{[0, 1, 2].map((i) => (
|
||||||
|
<motion.span key={i} className="h-1.5 w-1.5 rounded-full bg-violet/60" animate={{ y: [0, -4, 0] }} transition={{ duration: 0.6, repeat: Infinity, delay: i * 0.15 }} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function Message({
|
function Message({
|
||||||
message, last, busy, onRetry, onFollowUp,
|
message, last, busy, onRetry, onFollowUp,
|
||||||
}: {
|
}: {
|
||||||
@@ -225,21 +261,7 @@ function Message({
|
|||||||
|
|
||||||
if (message.role === 'user') return <Bubble role="user"><MathText text={message.text} /></Bubble>;
|
if (message.role === 'user') return <Bubble role="user"><MathText text={message.text} /></Bubble>;
|
||||||
|
|
||||||
if (!message.text) {
|
if (!message.text) return <Thinking />;
|
||||||
return (
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<span className="flex h-8 w-8 flex-shrink-0 items-center justify-center overflow-hidden rounded-full bg-[#f5f1ff]">
|
|
||||||
<SeyarMascot char="pi" mood="idle" size={32} />
|
|
||||||
</span>
|
|
||||||
<div className="flex items-center gap-2 rounded-2xl border border-line bg-white px-4 py-3 text-xs text-muted">
|
|
||||||
پی داره فکر میکنه
|
|
||||||
{[0, 1, 2].map((i) => (
|
|
||||||
<motion.span key={i} className="h-1.5 w-1.5 rounded-full bg-violet/60" animate={{ y: [0, -4, 0] }} transition={{ duration: 0.6, repeat: Infinity, delay: i * 0.15 }} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function rate(helpful: boolean) {
|
async function rate(helpful: boolean) {
|
||||||
if (!message.messageId || message.feedback) return;
|
if (!message.messageId || message.feedback) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user