Skip to content

feat(demo): add image upload to try your own images - #17

Merged
adeelraza merged 1 commit into
mainfrom
claude/demo-image-upload-72f4b3
Aug 5, 2026
Merged

feat(demo): add image upload to try your own images#17
adeelraza merged 1 commit into
mainfrom
claude/demo-image-upload-72f4b3

Conversation

@adeelraza

Copy link
Copy Markdown
Contributor

Summary

Adds an "Upload image…" action to the demo sidebar so users can try the editor with their own images (requested follow-up to the sample-image rotation).

  • demo/src/Sidebar.tsx — new Actions button backed by a hidden <input type="file" accept="image/*">; input value is cleared before the callback so re-selecting the same file always fires onChange.
  • demo/src/App.tsxuploadImage() reads the file client-side via FileReader.readAsDataURL and passes the data URL through the existing image prop / serialized reset chain. No server, no persistence — the image never leaves the visitor's browser, so this works unchanged on static hosting (Vercel).

Hardening from adversarial review (cross-model confirmed findings, fixed in-branch):

  • MIME + size gate: accept is only a picker hint — non-image/* files and files > 20 MB are rejected with a status message before any read.
  • Stale-read guard: a monotonic token + reader.abort() ensures a slow read of a large file can never overwrite a newer pick (upload or "Change image") after the fact.
  • reader.error is logged on failure; previously it was silently discarded.

Test Coverage

Tests: 2 → 2 (+0 new) — all 8 new code paths live in demo/, which is intentionally outside the library's test boundary (vitest scopes to src/**). Verified manually in the running demo instead: valid upload, non-image rejection, oversize rejection, picker cancel, same-file re-select, and "Change image" recovery all confirmed in-browser.

CODE PATHS                                            USER FLOWS
[+] demo/src/App.tsx
  ├── uploadImage(file)
  │   ├── [INTENTIONAL — demo] MIME guard reject                 — verified in browser
  │   ├── [INTENTIONAL — demo] size guard reject (>20 MB)        — verified in browser
  │   ├── [INTENTIONAL — demo] onload → setImage + status        — verified in browser
  │   ├── [INTENTIONAL — demo] onerror → error status + log
  │   └── [INTENTIONAL — demo] stale-token bail (race guard)
[+] demo/src/Sidebar.tsx
  ├── [INTENTIONAL — demo] button → fileInputRef click           — verified in browser
  ├── [INTENTIONAL — demo] onChange file present → callback      — verified in browser
  └── [INTENTIONAL — demo] onChange cancel / value reset         — verified in browser
COVERAGE: demo dev harness — untested by repo convention; manual QA plan artifact written

Pre-Landing Review

No issues found. (Small diff — specialists skipped per policy.)

Adversarial Review

Claude adversarial subagent + Codex (model_reasoning_effort=high), both ran:

  • [FIXED] Stale FileReader race — found by both models
  • [FIXED] Missing type/size validation (tab OOM risk) — found by both models
  • [FIXED] reader.error swallowed; input value cleared after callback (Claude)
  • [SKIPPED] Editor reset before decode-validation, optimistic "Loaded" status, stale saved-preview (Codex) — pre-existing demo idioms shared with the "Change image" action; the demo intentionally exercises the library's onLoadError path.

Eval Results

No prompt-related files changed — evals skipped.

Scope Drift

Scope Check: CLEAN — intent was "add image upload to the demo"; the diff touches exactly the two demo files.

Plan Completion

No plan file detected.

Verification Results

Manual browser verification against the live dev server (post-fix): 6 PASS, 0 FAIL — valid image load, .txt rejection ("is not an image"), 21 MB file rejection ("too large (max 20 MB)"), same-file re-select, picker cancel no-op, sample-image cycling after upload.

Documentation

Documentation is current — README doesn't enumerate demo sidebar actions (pre-existing convention). Flagged as optional debt for /document-generate.

Test plan

  • Vitest: 41 tests pass (2 files) — re-run after adversarial fixes
  • tsc --noEmit clean (root + demo)
  • Prettier check clean
  • Live browser QA of all upload paths (see Verification Results)

🤖 Generated with Claude Code

Adds an "Upload image…" action to the demo sidebar backed by a hidden
file input. The file is read client-side via FileReader.readAsDataURL
and flows through the existing image prop / serialized reset chain —
no server involved.

Hardening from adversarial review:
- MIME + 20 MB size gate (accept="image/*" is only a picker hint)
- read token + abort so a slow read can't overwrite a newer pick
- reader.error logged; input value cleared before the callback so
  re-selecting the same file always fires onChange

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-image-editor Ready Ready Preview Aug 5, 2026 4:54am

Request Review

@adeelraza
adeelraza merged commit b5992ff into main Aug 5, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant