feat(M6): PDF + image import#10
Merged
Merged
Conversation
Add the ability to import images and PDFs onto a board, replacing the placeholder asset renderer with a real one. Entry points: an Import button in the tool palette and drag-and-drop onto the canvas. - Images become a single YAssetRef; PDFs become one YAssetRef per page laid out in a grid (all pages sharing one asset, discriminated by pageIndex). - Bytes are stored in a public Supabase Storage bucket (board-assets) at the deterministic path <boardId>/<assetId>; a best-effort row is written to the existing assets table. Import is disabled when Supabase isn't configured. - New asset loader resolves a paintable bitmap per (assetId, pageIndex) with in-memory LRU caches, downloading bytes from Storage and lazily rasterizing PDF pages with pdf.js (loaded as a separate chunk via dynamic import). - AssetRefRenderer paints a Konva Image (loading/error placeholders), so M5 transform/rotate/z-order/lock/opacity apply unchanged. A whole import is one transaction, so a single undo reverts it. - Add 0002_assets_storage.sql: board-assets bucket + free-for-all storage RLS mirroring the public-board model. https://claude.ai/code/session_011TMH7eYBb5huhrHTzQf9Kb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Milestone 6 — PDF + image import
Makes the scaffolded asset pipeline real: you can now import images and PDFs onto a board and they render as transformable objects that sync to collaborators. Replaces the placeholder
AssetRefRenderer(dashed box) with a real Konva<Image>renderer.What's included
<input accept="image/*,application/pdf" multiple>) and drag-and-drop files onto the canvas (dropped at the cursor's world position).YAssetRef(scaled to fit), placed at the drop point / viewport centre.YAssetRefper page laid out in a grid (all pages share a single asset, discriminated bypageIndex). Pages rasterize lazily on render via pdf.js.board-assetsbucket at the deterministic path<boardId>/<assetId>; a best-effort row is also written to the existingassetstable. Because the path is deterministic and the shape carriespageIndex(null= image), the renderer needs nothing beyond theYAssetRef+ the Supabase client — no extra metadata channel. Import is disabled in local-only mode (no Supabase) with a tooltip.assets/assetLoader.ts): resolves a paintable bitmap per(assetId, pageIndex)with in-memory LRU caches (bitmaps, blobs, parsed PDF docs) + in-flight dedupe; downloads bytes from Storage and rasterizes PDF pages with pdf.js.@notux/canvas+@notux/weband loaded via dynamicimport(), so the ~365 KB core + ~1.4 MB worker land in separate lazy chunks (verified in the build output), not the initial bundle.ShapesLayer).0002_assets_storage.sql:board-assetsbucket + free-for-allstorage.objectsRLS mirroring the public-board model in0001_init.sql.Verification
pnpm -r typecheck✅pnpm -F @notux/web build✅ (emits separatepdf-*.js+pdf.worker.min-*.mjschunks; no dynamic/static import warning)Notes / trade-offs
🤖 Draft PR — opened automatically after pushing.
https://claude.ai/code/session_011TMH7eYBb5huhrHTzQf9Kb
Generated by Claude Code