Carry over the drawn image from outline to details
This commit is contained in:
1 parent
8803d17f11
commit
3fdce23929
3 files changed
+62
-7
No files matched your search
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user