Carry over the drawn image from outline to details

This commit is contained in:
iamdoubz committed 2026-06-17 20:51:41 -05:00
1 parent 8803d17f11
commit 3fdce23929
3 files changed
+62 -7

No files matched your search

+36 -6
View File
@@ -16,8 +16,9 @@ const SIZES = [4, 8, 16];
interface Point { x: number; y: number }
interface Stroke { color: string; size: number; points: Point[] }
export default function TraceRunner({ meta, steps, loggedIn, username, completedSteps, alreadyEarned }: {
export default function TraceRunner({ meta, steps, loggedIn, username, completedSteps, alreadyEarned, carryImage = "", nextHref = "", nextLabel = "" }: {
meta: Meta; steps: StepData[]; loggedIn: boolean; username: string; completedSteps: number[]; alreadyEarned: boolean;
carryImage?: string; nextHref?: string; nextLabel?: string;
}) {
const lastIndex = steps.length - 1;
const [idx, setIdx] = useState(Math.min(completedSteps.length, lastIndex));
@@ -69,9 +70,14 @@ export default function TraceRunner({ meta, steps, loggedIn, username, completed
useEffect(() => {
if (!loggedIn || alreadyEarned) return; let alive = true;
loadProgressDrawing(meta.level, meta.sublevel).then((img) => { if (!img || !alive) return; const im = new Image(); im.onload = () => { baseImgRef.current = im; redraw(); }; im.src = img; });
loadProgressDrawing(meta.level, meta.sublevel).then((img) => {
// Use this lesson's own saved canvas if any; otherwise carry over the previous lesson's drawing
const src = img || carryImage;
if (!src || !alive) return;
const im = new Image(); im.onload = () => { baseImgRef.current = im; redraw(); }; im.src = src;
});
return () => { alive = false; };
}, [loggedIn, alreadyEarned, meta.level, meta.sublevel, redraw]);
}, [loggedIn, alreadyEarned, meta.level, meta.sublevel, carryImage, redraw]);
// Auto-play the line video whenever the step changes
useEffect(() => { setPlaying(true); setPlayKey((k) => k + 1); }, [idx]);
@@ -95,8 +101,14 @@ export default function TraceRunner({ meta, steps, loggedIn, username, completed
function prev() { flushSave(); if (idx > 0) setIdx(idx - 1); }
async function finish() {
await saveStep(step.n, meta.badgeKey || undefined);
const c = canvasRef.current;
if (c && hasContent()) { const data = exportCanvasToDataURL(c); setFinalImage(data); if (loggedIn) await saveFinalDrawing(meta.level, meta.sublevel, "canvas", data); }
// Only completing the level (the badge lesson) saves to the profile gallery.
// Earlier lessons (e.g. Outline) keep their working canvas so it carries forward, but aren't saved as finals.
if (meta.badgeKey) {
const c = canvasRef.current;
if (c && hasContent()) { const data = exportCanvasToDataURL(c); setFinalImage(data); if (loggedIn) await saveFinalDrawing(meta.level, meta.sublevel, "canvas", data); }
} else {
flushSave(); // persist the outline canvas so the Details lesson can carry it over
}
setEarned(loggedIn && !!meta.badgeKey);
setFinished(true);
}
@@ -122,6 +134,23 @@ export default function TraceRunner({ meta, steps, loggedIn, username, completed
}
async function downloadBadge() { const b = await rasterizeBadge(); if (b) downloadBlob(b, "drawit-badge.png"); }
if (finished && !meta.badgeKey) {
// Outline (or any non-badge step): completed, but the level isn't finished — no profile saving here.
return (
<div className="form-narrow center">
<div className="card">
<h1>✏️ Outline complete!</h1>
<p className="muted">Awesome lines! Your outline carries over to the next lesson, so you can add the details right on top.</p>
{nextHref && <Link className="btn big" href={nextHref}>{nextLabel || "Next"} →</Link>}
<div className="row" style={{ justifyContent: "center", marginTop: 16 }}>
<button className="btn ghost" onClick={() => { clearCanvas(); setIdx(0); setFinished(false); }}>↺ Draw it again</button>
<Link className="btn ghost" href="/learn">Back to lessons</Link>
</div>
</div>
</div>
);
}
if (finished) {
return (
<div className="form-narrow center">
@@ -152,7 +181,8 @@ export default function TraceRunner({ meta, steps, loggedIn, username, completed
<button className="btn secondary" onClick={() => uploadRef.current?.click()}>📷 Upload my paper drawing</button>
{uploadMsg && <p className="muted" style={{ marginTop: 8 }}>{uploadMsg}</p>}
</div>
<div className="row" style={{ justifyContent: "center", marginTop: 18 }}>
{nextHref && <div className="row" style={{ justifyContent: "center", marginTop: 14 }}><Link className="btn accent big" href={nextHref}>{nextLabel || "Next"} →</Link></div>}
<div className="row" style={{ justifyContent: "center", marginTop: 14 }}>
{loggedIn && <Link className="btn ghost" href="/profile">🖼️ My drawings</Link>}
<button className="btn ghost" onClick={() => { clearCanvas(); setFinalImage(null); setUploadMsg(""); setIdx(0); setFinished(false); }}>↺ Try again</button>
<Link className="btn ghost" href="/learn">Back to lessons</Link>