Skip to content

Add source-aware inline image preview and explicit image export - #2

Merged
Artsen merged 1 commit into
mainfrom
feat/interactive-image-preview
Jul 26, 2026
Merged

Add source-aware inline image preview and explicit image export#2
Artsen merged 1 commit into
mainfrom
feat/interactive-image-preview

Conversation

@Artsen

@Artsen Artsen commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • upload each source image once and address it with an opaque source ID
  • render the original and processed image previews inline without navigation or automatic downloads
  • build one deterministic Recipe v1 payload for debounced previews and explicit exports
  • retain the existing video workflow while modernizing the image workspace
  • add lifecycle-aware source/output stores, validation, cleanup protection, documentation, and independent browser CI

API contracts

  • POST /api/image-sources uploads and validates PNG, JPEG, BMP, or TIFF sources
  • GET /api/image-sources/{source_id}/original serves the original inline
  • POST /api/image-sources/{source_id}/preview returns a processed PNG inline
  • POST /api/image-sources/{source_id}/export creates an explicit PNG output
  • GET /api/image-outputs/{output_id} serves an exported image inline
  • GET /api/image-outputs/{output_id}/download downloads an exported image

Source and output identifiers are opaque. API responses do not expose local paths. Strict Recipe v1 validation rejects unknown or malformed fields, and image validation rejects mismatched formats, animated inputs, decompression-bomb risks, and oversized images.

UX and determinism

The source is uploaded once. Control changes trigger a 175 ms debounced preview request; superseded requests are aborted and revision checks prevent stale responses from replacing newer previews. The previous good preview stays visible while a replacement is generated. A stable seed is reused across previews and export, and export uses the same ordered Recipe v1 payload as preview. Only the explicit Export action creates an output and enables Download.

The responsive, keyboard-accessible comparison workspace supports side-by-side and stacked views from 320 px upward. Errors and status updates remain inline. The existing video panels and endpoints remain available.

Validation

Local validation completed before opening this draft:

  • python check.py: 123 tests passed
  • statement coverage: 97.85% (865/884)
  • branch coverage: 92.06% (116/126)
  • Ruff formatting and linting passed
  • strict Mypy passed across 22 source files
  • Playwright: 5 Chromium workflows passed at 320, 768, 1024, and 1440 px
  • axe: zero serious or critical accessibility violations
  • focused source-store, image-route, legacy/video-route, and effect/contract suites passed
  • git diff --check passed
  • manual image check: preview and explicit export were byte-identical for the same recipe and seed
  • manual video check: preview, full processing, stream, download, progress, and corrupt-input failure behavior passed

GitHub Actions passed: quality in 29 seconds and browser in 1 minute 1 second.

Known limitations

  • source and output records are process-local and are lost when the application restarts
  • previews process the full-resolution source, so very large accepted images can still take noticeable time
  • exported files remain on local storage until normal age-based cleanup removes them
  • jQuery remains only for the legacy video workflow; a broader framework migration is intentionally deferred

@Artsen
Artsen marked this pull request as ready for review July 26, 2026 02:44
@Artsen
Artsen merged commit 991424e into main Jul 26, 2026
2 checks passed
@Artsen
Artsen deleted the feat/interactive-image-preview branch July 26, 2026 02:44
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