From b11016c6ea96014f8d702b9417ba52d4daf3878b Mon Sep 17 00:00:00 2001 From: AliReza Date: Wed, 7 Oct 2026 17:05:52 +0330 Subject: [PATCH] LoadingState appears only after 300ms: fast API answers no longer flash the loader (packs screen and every other data screen) Co-Authored-By: Claude Sonnet 5.5 --- src/app/MainApp.tsx | 17 +---------------- src/components/ui.tsx | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/app/MainApp.tsx b/src/app/MainApp.tsx index 6765620..03a5aed 100644 --- a/src/app/MainApp.tsx +++ b/src/app/MainApp.tsx @@ -67,21 +67,6 @@ export function MainApp({ profile, grades, payment, onSignedOut }: Props) { ); } -/** - * صفحه‌ها از قبل گرفته شده‌اند، ولی `lazy` حتی برای ماژولِ آماده هم یک رندرِ تهی می‌گیرد؛ نشان دادنِ - * «یه لحظه صبر کن» در همان یک-دو فریم همان پرشِ ریزِ بینِ صفحه‌ها بود. لودر فقط اگر بارگیری - * واقعاً طول کشید (شبکه‌ی کند، پیش از تمام شدنِ preload) پس از ۳۰۰ms ظاهر می‌شود. - * با مرورگر دیده نشده؛ فقط از روی کد. - */ -function DelayedLoading() { - const [show, setShow] = useState(false); - useEffect(() => { - const t = setTimeout(() => setShow(true), 300); - return () => clearTimeout(t); - }, []); - return show ? : null; -} - function Screens({ onSignedOut }: Pick) { const nav = useNav(); const { route } = nav; @@ -99,7 +84,7 @@ function Screens({ onSignedOut }: Pick) { exit={{ opacity: 0, x: 18 }} transition={{ duration: 0.18 }} > - }> + }> diff --git a/src/components/ui.tsx b/src/components/ui.tsx index eabab70..aeabac9 100644 --- a/src/components/ui.tsx +++ b/src/components/ui.tsx @@ -1,4 +1,4 @@ -import type { ButtonHTMLAttributes, CSSProperties, ReactNode } from 'react'; +import { useEffect, useState, type ButtonHTMLAttributes, type CSSProperties, type ReactNode } from 'react'; import { ChevronRight, RotateCw } from 'lucide-react'; import { SeyarMascot } from '@/mascots/SeyarMascot'; import type { SeyarChar, SeyarMood } from '@/mascots/seyar'; @@ -130,8 +130,19 @@ function StateBox({ char, mood, text, children }: { char: SeyarChar; mood: Seyar ); } -export function LoadingState({ text = 'یه لحظه صبر کن…', char = 'sigma' as SeyarChar }) { - return ; +/** + * لودر فقط بعد از `delayMs` دیده می‌شود. پاسخِ API معمولاً زیرِ ۳۰۰ms می‌رسد و نشان دادنِ لودر برای + * همان چند فریم، پرشِ ریزِ «لودر ← محتوا» می‌ساخت؛ حالا تا آن لحظه جای خالی می‌ماند. اگر پاسخ + * کند باشد کاربر باز هم لودر را می‌بیند. در مرورگر با شبکه‌ی کند آزموده نشده. + */ +export function LoadingState({ text = 'یه لحظه صبر کن…', char = 'sigma' as SeyarChar, delayMs = 300 }) { + const [show, setShow] = useState(delayMs <= 0); + useEffect(() => { + if (delayMs <= 0) return; + const t = setTimeout(() => setShow(true), delayMs); + return () => clearTimeout(t); + }, [delayMs]); + return show ? : null; } export function ErrorState({ error, onRetry, text }: { error?: unknown; onRetry?: () => void; text?: string }) {