docs: record renderContent, leafer renderer, and crop tool planning notes
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+17
@@ -236,3 +236,20 @@
|
||||
- The existing `VectorizedImageToolbar` already matches the requested compact `矢量` plus download UI. Its caller only identifies `layerRole === "vectorized-image"`, so normal uploaded SVGs and CAD-derived SVGs incorrectly receive the raster `image-node-toolbar`.
|
||||
- SVG export already preserves SVG-backed source content through `downloadSvgSource`; vector detection can route the toolbar without changing the download implementation.
|
||||
- Browser inspection of the second DWG reproduced the tiny-content symptom after the performance fix. Its extreme bounds come from one `MTEXT` entity around 550,000 drawing units away from the actual plans; the source marks that entity `isInvisible`, but the third-party SVG writer ignores CAD visibility. Excluding invisible/off/frozen-layer entities from both SVG output and bounds is the generic display fix.
|
||||
|
||||
## Leafer Renderer Implementation (2026-07-16)
|
||||
- The resumed worktree contains only the Phase 32 API-spec field and its regenerated Go type; `leafer-ui` is not yet installed and no persistence or frontend render-preview plumbing exists.
|
||||
- `CanvasNode` crosses both a compressed frontend snapshot and explicit server API/domain/PostgreSQL mappings. PostgreSQL uses ordered SQLC column/parameter lists, so `render_content` must be added consistently to schema, select, upsert, generated SQLC parameters, repository save/map, and mapper paths.
|
||||
- Canvas covers currently derive from `node.content`; this should remain source-based for durable semantics/export unless a dedicated thumbnail consumer needs the preview texture.
|
||||
- Canvas import currently creates one optimistic node per prepared file and uploads only its source. The extension point is `PreparedCanvasImportAsset`: add an optional WebP file, keep the local SVG object URL as optimistic content, and mark the node successful only when both source and preview uploads resolve.
|
||||
- Existing SVG-to-transparent-WebP conversion already validates SVG, derives dimensions from `viewBox`, clears the canvas, and encodes WebP at up to 2048 px. It can be reused for render textures with a render-specific filename while leaving model-reference behavior unchanged.
|
||||
- `ArtboardPreview` is a source-only DOM renderer today. Preview consumers can prefer `node.renderContent`, but crop/export/model paths must keep reading `node.content`.
|
||||
- Leafer's `around: "center"` interprets `x/y` as the transform center. Passing the domain's top-left coordinates shifts the rendered image up and left by half its width/height while the React selection overlay stays at the correct domain bounds; retained visuals must pass center coordinates and convert imperative drag positions the same way.
|
||||
- The apparent rectangular canvas boundary was a real initialization race: the renderer's async import completed after the stage resize state update, then applied the stale `1100 x 760` fallback captured by the project effect. The stage was actually `1685 x 1670`, so Leafer clipped everything outside the smaller internal canvas. Initial sizing must read the mounted layer's live `clientWidth/clientHeight` when the renderer becomes ready.
|
||||
|
||||
## Workspace Crop Drag Selection (2026-07-16)
|
||||
- The clarified interaction is a two-stage tool: the workspace Crop button arms a crosshair without opening `CropOverlay`; the next click or drag chooses the initial region, then the existing editor opens.
|
||||
- A click analyzes the displayed raster/WebP texture with bounded connected-color region growth. If no enclosing color boundary exists, the result becomes the maximum currently visible image region.
|
||||
- A drag bypasses color analysis and maps the pointer rectangle directly into normalized source coordinates, clamped to the same visible-region maximum. This remains correct under canvas pan and zoom because mapping uses current screen bounds.
|
||||
- Color analysis is capped at a 640-pixel edge and measured about 22ms for a fully connected 640 x 480 image in the local Node benchmark.
|
||||
- CAD/SVG source and semantic metadata are untouched: the preview texture is used only for click analysis, while the established source-based crop path creates the final result and crop-specific CAD context.
|
||||
|
||||
+16
@@ -181,6 +181,22 @@
|
||||
- Started the production implementation after user approval, using the existing `CanvasNode[]` and SVG/CAD semantic contracts as the source of truth.
|
||||
- Chosen boundary: persist a separate render-preview URL, render supported visual nodes through LeaferJS, and keep React UI/overlays plus source-based crop/export/model behavior.
|
||||
- Traced the explicit canvas-node field through the API/domain/PostgreSQL/snapshot layers and the paired source/preview upload changes needed for atomic vector imports.
|
||||
- Resumed Phase 32 with a clean two-file partial diff: the API spec and generated Go type already expose optional `renderContent`; persistence, preview generation, and renderer work remain outstanding.
|
||||
- Completed `renderContent` plumbing through the frontend domain/snapshot normalizer, Go domain/API mappers, PostgreSQL schema/queries/repository, SQLC generation, mapper regression coverage, and API documentation.
|
||||
- Added one-time transparent WebP generation for imported SVG/CAD sources, paired source/texture uploads with partial-upload cleanup, optimistic local texture display, and preview-preference helpers for the canvas and thumbnail surfaces.
|
||||
- Installed `leafer-ui@2.2.2` and added a retained Leafer renderer for successful image nodes and manual frames. Vector nodes enter Leafer only when their transparent WebP texture is present; React remains the hit-target, selection, toolbar, crop, and text-edit overlay.
|
||||
- Moved wheel zoom, canvas pan, and ordinary node drag frames onto imperative Leafer/DOM transforms. React viewport/node state now commits after interaction settles or ends, and drag alignment guides render imperatively.
|
||||
- Focused/full verification passes after the renderer migration: 29 frontend tests, strict TypeScript compilation, and the complete Go test suite.
|
||||
|
||||
### Phase 33: Workspace Crop Drag Selection
|
||||
- **Status:** complete
|
||||
- Implemented the clarified two-stage workspace Crop tool: activation now enters a crosshair preselection state instead of immediately opening a full crop selection.
|
||||
- A click selects the connected color-bounded area under the pointer from the displayed raster/WebP texture; the selection can never exceed the currently visible part of the image.
|
||||
- Holding the left button and dragging draws a live rule-of-thirds selection, clamps it to the visible target bounds, and opens the existing crop editor on release.
|
||||
- The existing source-preserving CAD/SVG crop, crop-specific semantic context, raster replacement behavior, presets, resizing, and confirm/cancel flow remain unchanged.
|
||||
- Added synthetic color-boundary and visible-range drag regressions. All 35 frontend tests, strict TypeScript compilation, `git diff --check`, and the Next/Vite production build pass.
|
||||
- Benchmarked the maximum fully connected 640 x 480 color analysis at about 22ms and confirmed the updated single preview server responds at `http://127.0.0.1:5175`.
|
||||
- The configured in-app browser backend remained unavailable, so final interactive visual inspection is left to the running local preview; source-level interaction coverage and HTTP verification pass.
|
||||
|
||||
### Phase 30: Native-Resolution Vector Crop Fidelity
|
||||
- **Status:** in_progress
|
||||
|
||||
@@ -205,6 +205,14 @@ Phase 32
|
||||
- [ ] Add focused regression/performance coverage and run full frontend/backend/build/browser verification
|
||||
- **Status:** in_progress
|
||||
|
||||
### Phase 33: Workspace Crop Drag Selection
|
||||
- [x] Enter a crosshair preselection state after activating the workspace Crop tool
|
||||
- [x] Select a connected color-bounded region on click, capped to the visible image area
|
||||
- [x] Map a held left-button drag into normalized image coordinates across pan and zoom
|
||||
- [x] Preserve the existing crop editor, vector semantics, and source-preservation behavior
|
||||
- [x] Add focused regression coverage and run frontend verification
|
||||
- **Status:** complete
|
||||
|
||||
## Invariants
|
||||
- Brand Kits are owned and queried only through the authenticated user ID from request context.
|
||||
- A project may reference zero or one Brand Kit owned by the same user.
|
||||
@@ -255,6 +263,12 @@ Phase 32
|
||||
| Next 16 Turbopack emitted the module worker as raw `.ts` instead of executable bundled JavaScript | 1 | Run Next dev/build through its supported webpack mode, which handles `new Worker(new URL(...))`; retain Vite's native worker bundling. |
|
||||
| Used nonexistent Playwright CLI command `network` | 1 | Use the CLI's documented `requests` and `response-body` commands for network inspection. |
|
||||
| First Vite DXF upload triggered dependency pre-bundling and a development-page reload | 1 | Retry after Vite finishes one-time dependency optimization; production worker output is already bundled. |
|
||||
| Node's strip-only TypeScript test loader rejected a constructor parameter property in the Leafer adapter | 1 | Replace the parameter property with an explicit class field so production TypeScript and the repository's Node test runner share supported syntax. |
|
||||
| The Leafer descriptor test could not resolve frontend `@/` runtime aliases under Node's native loader | 1 | Keep the descriptor dependency-free at runtime with local source/adjustment checks; type-only aliases remain erased and production bundling is unchanged. |
|
||||
| DOM `window.setTimeout` returned `number` but the viewport timer ref inferred Node's `Timeout` type | 1 | Declare the browser-owned timer ref as `number | null`, matching the existing browser timeout usage. |
|
||||
| Combined render-preview cleanup/thumbnail patch assumed `mainCanvasPreviewImage` lived in `project_thumbnail.go` | 1 | Locate the function in `design_service.go` and split the patch across exact current file contexts. |
|
||||
| The first crop preselection integration patch used one stale keyboard-handler context and failed atomically | 1 | Split the integration into small patches against the exact current source; no production file received a partial edit. |
|
||||
| A diagnostic `rg` command contained an unmatched quote around a template-literal search | 1 | Use separate fixed-string searches without shell-sensitive backticks. |
|
||||
| Real upstream DXF fixture parsed to an empty model space in `@node-projects/acad-ts` | 1 | Validate the library's document assembly in Node, then replace the DXF path or reader entirely if real fixtures remain empty. |
|
||||
| Directory-wide listing of the WeChat file folder stalled on container-managed storage | 1 | Use the exact user-provided path directly; metadata access confirms the file is readable. |
|
||||
| The exact R12 DXF crashed while serializing the first inherited-color POINT | 1 | Resolve non-renderable ByLayer/ByBlock colors through the entity and layer before calling the third-party SVG writer; lock the case with a minimal R12 regression test. |
|
||||
|
||||
Reference in New Issue
Block a user