forked from Tadrisino/MathApp_frontend
Smooth screen transitions: new screen waits hidden until its data arrives, no half-built flash
- Navigator stage: the next screen mounts hidden under the current one and is revealed only when its first data has arrived (ScreenGate held by useAsync/useGateHold), at most 450 ms; a thin top bar shows after 120 ms of waiting. Push slides from the left, back from the right, tabs only fade. - Session cache (stale-while-revalidate) for screen GETs: revisited screens draw instantly. - Home map and stats are fetched during the splash, so the first screen arrives complete. - Entrance pop-ins (mascot, islands, lesson cards) run on first view only, not on every revisit. - Shop status card shows placeholders instead of a wrong «نداری» while loading. - Re-tapping the open tab scrolls to top instead of reloading; sheets close with a swipe down. - Quiz: «۱ از ۴» instead of «۱/۴» (read as a fraction), varied praise, «N تا پشتِ هم درست», growth-mindset copy after a weak round, zero-reward tiles hidden. - Streak: a concrete next step when the streak is 0 or today is still empty. Checked in headless Chrome against the local backend (frame captures at 150 ms and 700 ms latency, rapid tab tapping, full quiz run). Not checked on a real phone or iOS Safari. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import { EmptyState, ErrorState, LoadingState, ProgressBar, Screen, ScreenHeader
|
||||
import { iconFor } from '@/components/NodeIcon';
|
||||
import { toFa } from '@/lib/format';
|
||||
import { MathText } from '@/lib/MathText';
|
||||
import { useFirstVisit } from '@/lib/firstVisit';
|
||||
|
||||
/**
|
||||
* تبِ «درسها»: فصل ← جزیره ← درس. فصلها اول بستهاند و بالای صفحه یک کارتِ «ادامه بده» هست.
|
||||
@@ -117,9 +118,10 @@ function UnitCard({
|
||||
const Icon = iconFor(unit.nodes[0]?.icon, index);
|
||||
const nav = useNav();
|
||||
const premium = unit.requiresSubscription;
|
||||
const intro = useFirstVisit(`unit-card:${unit.id}`);
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
initial={intro ? { opacity: 0, y: 12 } : { opacity: 1, y: 0 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: Math.min(index, 8) * 0.04 }}
|
||||
className="overflow-hidden rounded-2xl bg-white"
|
||||
|
||||
Reference in New Issue
Block a user