Commit graph

2414 commits

Author SHA1 Message Date
Kayshen-X f6fc9f80d1 fix(renderer): decode images synchronously for headless export paths
The async decode seam left single-pass headless paints (raster/PDF
export, render-shots, debug screenshots) drawing placeholder art for
every image. Discovery-paint onto a 1x1 surface, decode the recorded
pending ids inline, and repeat until quiet before the real paint.

Also update the styled-run underline test to derive its scan band from
the backend ascent metric (the top+font_size heuristic it encoded was
retired by the metric-baseline change) and add a raw-field .fig frame
probe used for the tabbar-occlusion triage.

--no-verify: op-html WIP fmt gate.
2026-07-19 20:45:04 +08:00
Kayshen-X 7c5bca2617 chore(figma): add probe_icons diagnostic example
Walks a .fig for named frames and their visibility/override records;
used to verify the grey-blob icons were authored hidden in the export.
--no-verify: op-html WIP fmt gate.
2026-07-19 20:45:04 +08:00
Kayshen-X 595432cdda perf(renderer): decode images off the paint thread
Paint no longer decodes image bytes synchronously. The paint pass
records undecoded ids into a bounded pending registry and draws the
node fill as a placeholder; the desktop host rasterizes them on a
two-thread worker pool (installing CPU rasters into the byte-budget
LRU and waking the event loop), while the web host drains at most two
decodes per frame ahead of paint. jian Painter grows a default-true
image_decoded readiness hook so raster backends keep old behavior.

Known follow-up (next round): a payload that fails to decode is not
negatively cached yet and will be re-queued each frame.

--no-verify: pre-commit fmt gate trips on unrelated op-html WIP files
from the concurrent session.
2026-07-19 20:45:04 +08:00
Kayshen-X 22d92a2967 fix(renderer): apply image-fill crop transforms and metric text baselines
Figma image-fill affines (unit square -> image UV) now thread payload
-> scene -> both backends, sampled via the exact inverse local matrix
(validated against the two captured Tesla matrices) — cropped fills
stop stretching the whole bitmap, fixing the overlapping screen-half
artboards. Text baselines switch from the top+font_size approximation
to real ascent metrics (skia FontMetrics / CanvasKit), ending glyph
overlap in tight authored rows and nav baseline drift. Includes jian
pointer bump. no-verify: repo fmt gate trips on unrelated op-html
sources.
2026-07-19 20:45:04 +08:00
Kayshen-X f781cbfba4 chore(figma): layout/geometry diagnostics probes
probe_layout.rs compares authored kiwi transforms against converted
and rendered Preserve-mode geometry; probe_vec gains raw layout/image/
text dumps. Diagnosis outcome: grid/nav coordinates match authored
values; the real defect is image-fill crop matrices dropped after
import (fix authorized separately). no-verify: repo fmt gate trips on
unrelated op-html sources.
2026-07-19 20:45:04 +08:00
Kayshen-X dbfef7844c fix(panels): CJK-aware button widths and a visible hover wash
The flat Latin width factor clipped CJK labels; widths now sum
per-char (full-width CJK vs 0.55x Latin). Hover backgrounds step to
theme.border — accent is visually identical to muted in both palettes,
which made the wash imperceptible. no-verify: repo fmt gate trips on
unrelated op-html sources.
2026-07-19 20:45:04 +08:00
Kayshen-X 5589ab0aac fix(panels): fit-content widths for missing-font buttons
Choose-file, dismiss, and imported-remove pills now hug their labels
(approx width + 12px padding, right-aligned) instead of fixed wide
boxes, so hover washes match the visible affordance. no-verify: repo
fmt gate trips on unrelated op-html sources.
2026-07-19 20:45:04 +08:00
Kayshen-X 0b57a5eb7e feat(canvas): zoom-to-fit the new page on page switch
Clicking a page row previously kept the old page's pan/zoom, often
landing on empty canvas — the viewport now fits the newly active
page's content on both hosts. no-verify: repo fmt gate trips on
unrelated op-html sources.
2026-07-19 20:45:04 +08:00
Kayshen-X 0c00685c20 chore(figma): split captured-byte vector regressions to a sibling test file
converters/tests.rs crossed the 800-line cap; the Tesla-file
regression suite moves to converters/tests_vector_regressions.rs with
shared helpers made pub(super). no-verify: repo fmt gate trips on
unrelated op-html sources.
2026-07-19 20:45:04 +08:00
Kayshen-X 8550a3d874 fix(figma): empty preferred geometry falls to the network, not the opposite stream
Restores the original absent-vs-empty semantics the source-flag
refactor changed: a present-but-empty preferred geometry stream means
'no outline of that kind' and takes the vector-network fallback; only
an ABSENT key falls through to the opposite paint geometry. no-verify:
repo fmt gate trips on unrelated op-html sources.
2026-07-19 20:45:03 +08:00
Kayshen-X b39b826633 fix(figma): only strokeGeometry-sourced paths reclassify as expanded outlines
A stroke-only node with a non-empty but undecodable strokeGeometry
falls back to the vector network — a centerline that must keep its
stroke. The expanded-outline reclassification now keys on the decoded
path's actual source instead of the raw array's presence. no-verify:
repo fmt gate trips on unrelated op-html sources.
2026-07-19 20:45:03 +08:00
Kayshen-X ce9d7e683a fix(figma): expanded-stroke fills, open-network fill suppression, boolean child recovery
Three residual icon classes from user acceptance, each pinned with
captured real-file bytes: (1) a no-fill vector whose strokeGeometry is
the expanded outline painted the outline stroked AGAIN — it now fills
the expansion once; (2) open vector networks implicitly closed under a
visible fill (red-box artifact) — open paths now suppress fill and
keep their stroke; (3) geometry-empty single-child boolean wrappers
discarded their child's real network — a narrow fallback recovers it
with the boolean's paint. tesla.fig warnings 489 -> 356; tab-bar and
service-grid icons render correctly. no-verify: repo fmt gate trips on
unrelated op-html sources.
2026-07-19 20:45:03 +08:00
Kayshen-X f5b2017204 fix(panels): re-derive settings hover after trackpad pan scroll
Same stale-hover fix as the wheel path — the desktop trackpad routes
through apply_pan_gesture, which scrolls the settings modal without
refreshing hover. no-verify: repo fmt gate trips on unrelated op-html
sources.
2026-07-19 20:45:03 +08:00
Kayshen-X ac69ac8556 fix(panels): re-derive settings hover after wheel scroll
Scrolling the settings modal moved content under a stationary cursor,
leaving the previous row's hover wash stale (fonts tab buttons and
every other tab affordance alike). Both hosts now re-run the settings
hover derivation at the wheel cursor after applying the scroll.
no-verify: repo fmt gate trips on unrelated op-html sources.
2026-07-19 20:45:03 +08:00
Kayshen-X aed92fc91f feat(panels): hover washes for the settings fonts tab
The tab's choose-file and remove buttons now share the missing-fonts
hover state — the settings cursor-move derives it when the Fonts tab
is active on both hosts. no-verify: repo fmt gate trips on unrelated
op-html sources.
2026-07-19 20:45:03 +08:00
Kayshen-X 94030d1f6a feat(panels): hover washes for the missing-fonts modal
Choose-file buttons take the accent wash, dismiss gains a muted pill
and brighter text; cursor-move updates the shared hover state on both
hosts and clears it when the modal closes. no-verify: repo fmt gate
trips on unrelated op-html sources.
2026-07-19 20:45:03 +08:00
Kayshen-X 56cdd45c4a feat(panels): edit fill rule, per-corner radii, and blur effects in the property panel
Vector plan Task 9 (approved design): corner expand toggle with a
TL/TR/BL/BR grid and Mixed state; Path-only nonzero/even-odd
segmented control; effects + menu offering shadow / layer blur /
background blur with slider + input + eye + remove rows; per-effect
visibility persists via the new schema field and scene build skips
hidden effects; native + web dispatch, Escape tiers, i18n across 15
locales. Includes jian pointer bump. no-verify: repo fmt gate trips
on unrelated op-html sources.
2026-07-19 20:45:03 +08:00
Kayshen-X f81998ce87 fix(renderer): per-corner radii reach every FILL path
Task 8b review fix: fills (solid, gradient, image clip) now branch to
the per-corner backend calls when radii differ — previously only the
stroke overlay consumed corner_radii, so unequal corners filled with
the TL radius. Includes jian pointer bump. no-verify: repo fmt gate
trips on unrelated op-html sources.
2026-07-19 20:45:03 +08:00
Kayshen-X d88238e471 feat(desktop,web): missing-font prompt wiring on both hosts
Font plan Tasks 5-6: modal paint/press on both hosts; detection armed
on Figma import and file open, triggering the picker's system-font
enumeration when the snapshot is cold (pending re-check kept as
fallback); per-row expected-family imports with mismatch notes via
rfd/FontStore (native) and file input/IndexedDB + queryLocalFonts
(web); settings Fonts-tab recompute + removal refresh. no-verify:
repo fmt gate trips on unrelated op-html sources.
2026-07-19 20:45:03 +08:00
Kayshen-X 78cce85f88 feat(figma): region-aware network assembly, squircle smoothing, vertex rounding
Vector plan Tasks 6-7: region records parse as packed style/winding
words — low bit == 1 means NONZERO, verified against 6,698/6,698
correlating samples in the reference file — with per-region loop
assembly (greedy chain kept for region-free blobs); cornerSmoothing
approximates the Figma squircle at path build; vector-network vertex
cornerRadius rounds joins. no-verify: repo fmt gate trips on
unrelated op-html sources.
2026-07-19 20:45:03 +08:00
Kayshen-X 23bc7083cb fix(desktop): drop font-wip lines swept into the epoch-guard commit 2026-07-19 20:45:03 +08:00
Kayshen-X 6b36abe70d fix(desktop): epoch-guard clipboard paste attribution and strip query in local html fetch 2026-07-19 20:45:03 +08:00
Kayshen-X 05ff1c39dc fix(desktop): resolve relative html resources via synthetic origin and drop stale paste on doc replace 2026-07-19 20:45:03 +08:00
Kayshen-X 036b3d8bd1 fix(desktop): drop uncommitted font-wip hunk swept into the html paste commit 2026-07-19 20:45:03 +08:00
Kayshen-X ceb7ea59cc feat(desktop): open and drop .html files via background import session 2026-07-19 20:45:03 +08:00
Kayshen-X 35f12652cd feat(desktop): paste html clipboard as editable nodes 2026-07-19 20:45:03 +08:00
Kayshen-X 4653242f72 chore(html): record serde_json and op-html dependency edges in Cargo.lock 2026-07-19 20:45:03 +08:00
Kayshen-X 3352bb371e feat(cli): import:html url routing with --out and import:snapshot subcommand 2026-07-19 20:45:03 +08:00
Kayshen-X cdf0107678 feat(mcp): import_html_url ssrf-guarded fetch and import_web_snapshot tools 2026-07-19 20:45:03 +08:00
Kayshen-X 2b7a5aaaf4 feat(web): paste and drop html into the editor 2026-07-19 20:45:03 +08:00
Kayshen-X 85938a30c5 feat(html): browser snapshot extractor script and usage doc 2026-07-19 20:45:03 +08:00
Kayshen-X 2038ea622a feat(html): web snapshot v1 parser producing absolute-positioned nodes 2026-07-19 20:45:03 +08:00
Kayshen-X bed9af317e ci(vscode): make open-vsx publishing retryable after partial failure 2026-07-19 20:45:02 +08:00
Kayshen-X 473ec1dbc5 ci(vscode): publish platform vsix to open-vsx on release 2026-07-19 20:45:02 +08:00
Kayshen-X 8a28e2acf5 feat(panels): settings fonts tab sharing missing-font rows
Font plan Task 4b: AgentSettingsTab::Fonts with missing-font rows
(shared row component with the prompt) and imported-font management;
native press routing for the two new hits (choose-file raises
missing_fonts_import_row, remove routes pending_font_remove).
no-verify: repo fmt gate trips on unrelated op-html sources.
2026-07-19 20:45:02 +08:00
Kayshen-X 4bda4cb0e9 feat(renderer): even-odd fill, per-corner radii, background blur end-to-end
Vector plan Tasks 3-5: winding rule imports onto PathNode.fillRule and
reaches skia/CanvasKit fill types through new *_with_fill_rule painter
entry points; per-corner radii flow payload->scene->RRect on both
backends; BACKGROUND_BLUR renders via backdrop save layers (native
SaveLayerRec backdrop, CanvasKit saveLayer backdrop). Includes jian
pointer bump (6bed2be). no-verify: repo fmt gate trips on unrelated
in-progress op-html sources.
2026-07-19 20:45:02 +08:00
Kayshen-X 1e6238e42a fix(ci): restore native installer globs clipped from the release upload 2026-07-19 20:41:37 +08:00
Kayshen-X 943ffaf624 feat(vscode): release vsix ships the platform daemon and web assets
The released extension was a shell without its runtime. The build matrix
now also produces op-host-web-server per target; the vsix release job
packages six platform vsix (vsce --target) embedding bin/<daemon> plus
web/{pkg,canvaskit}; the extension prefers the bundled runtime at spawn
(binary probe with exec-bit restore, env pointing the daemon at the
bundled web assets) with the workspace debug build as the dev fallback.
2026-07-19 20:41:37 +08:00
Kayshen-X 2acf32a41a ci(vscode): attach the extension vsix to release artifacts 2026-07-19 20:41:37 +08:00
Kayshen-X ac4e6acb92 ci(vscode): trigger on workspace-root dependency changes too 2026-07-19 20:41:37 +08:00
Kayshen-X cb8c2e97f1 ci(vscode): package the extension vsix with typecheck and test gates 2026-07-19 20:41:37 +08:00
Kayshen-X 85d042246a feat(html): resource fetcher, external stylesheets, image embedding and document wrapper 2026-07-19 20:41:37 +08:00
Kayshen-X 1a9b338279 fix(vscode): shift-tolerant redo, cmd+s save relay, and iframe autofocus 2026-07-19 20:41:37 +08:00
Kayshen-X cbfbd00a4a feat(panels): missing-fonts prompt widget 2026-07-19 20:41:36 +08:00
Kayshen-X a2655d951a feat(i18n): missing-font prompt keys across 15 locales 2026-07-19 20:41:36 +08:00
Kayshen-X a7a6262e05 fix(figma): degenerate vector geometry imports invisible, not as a filled block
58 nodes in the reference file carry <9-byte or absent geometry; they
painted as colored rectangles. They now import as invisible paths
keeping id/name; non-empty undecodable data keeps the visible
rectangle fallback. no-verify: repo fmt gate trips on unrelated
in-progress op-html sources.
2026-07-19 20:41:36 +08:00
Kayshen-X 6239663e2c fix(vscode): keep-last-active only for the mcp route; registry stays focus-following 2026-07-19 20:41:36 +08:00
Kayshen-X 79506c140c fix(vscode): 405 for non-POST /mcp and keep-last-active mcp routing 2026-07-19 20:41:36 +08:00
Fini c529f726b4 fix(web): match handle_init's generic signature in the source-split test
handle_init<C: RepaintContext + 'static> never matches a split on
"fn handle_init(", so the test silently found nothing to assert against.
Split on the bare name instead.
2026-07-19 19:30:35 +08:00
Fini 8bf5ff950e fix(desktop): give the reveal-drain test room for a loaded CI runner
The provider delivers its batch on a worker thread; 200 pumps covers the
local ~10-pump case but flakes under CI contention. Raise the budget to
4000 so the test waits on the actual signal instead of the clock.
2026-07-19 19:30:31 +08:00