From 0378978b1fc573a9db0c0a688a62dc8c4a412f47 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 11:45:39 +0000 Subject: [PATCH] =?UTF-8?q?kasuti:=20don't=20autoplay=20on=20completion;?= =?UTF-8?q?=20default=20GIF=20to=200.5=C3=97=20pace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Completion now fires confetti and leaves both fabrics on the final tour (replayIdx = totalStitches, paused). The user drives the replay from the control strip. - Exported GIF frames render at 400 ms each (vs 200 ms on-screen) with a 1200 ms hold on the first and last frame — half speed by default, easier to follow when a platform auto-loops the preview. https://claude.ai/code/session_01KNdXjQczMCRGMK7K3Qderw --- src/components/interactives/KasutiEmbroidery.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/interactives/KasutiEmbroidery.tsx b/src/components/interactives/KasutiEmbroidery.tsx index 6a7b2bd..39e9c54 100644 --- a/src/components/interactives/KasutiEmbroidery.tsx +++ b/src/components/interactives/KasutiEmbroidery.tsx @@ -974,9 +974,10 @@ const KasutiEmbroidery: React.FC = () => { const encoder = GIFEncoder(); const totalFrames = stitches.length + 1; - // Timings: slightly longer hold on the first and last frames. - const frameDelayMs = 200; - const holdDelayMs = 900; + // Export at 0.5× the on-screen replay pace — easier to follow in a loop + // and friendlier when the GIF auto-plays in a social-media preview. + const frameDelayMs = 400; + const holdDelayMs = 1200; for (let k = 0; k <= stitches.length; k++) { const stitchesUpTo = stitches.slice(0, k); @@ -1023,19 +1024,20 @@ const KasutiEmbroidery: React.FC = () => { patternId, ]); - // On first completion: confetti + kick off an autoplay replay from step 0. + // On first completion: confetti + leave both fabrics showing the final tour. + // Replay stays paused until the user presses play or scrubs the slider. // When the tour is un-completed (undo/reset/pattern change), tear down replay. useEffect(() => { if (completed && !celebratedRef.current) { celebratedRef.current = true; confetti({ particleCount: 180, spread: 90, origin: { y: 0.6 } }); - setReplayIdx(0); - setReplayPlaying(true); + setReplayIdx(stitches.length); + setReplayPlaying(false); } else if (!completed) { setReplayIdx(0); setReplayPlaying(false); } - }, [completed]); + }, [completed, stitches.length]); // Hydrate from ?replay=... on mount. Runs once client-side; if the payload // parses and the pattern is known (preset or carried inline), rebuild the