Closed general

Adopt shot:{title,image,thumbnailDataUrl,maxWidth} on the show verbs (settled cross-bridge contract from ab#91)

John Lauer · ·closed by John Lauer

Add shot:{title, image, thumbnailDataUrl, maxWidth} to the show verbs, opt-in via capture:true + captureMaxWidth

This is the settled outcome of adom/adom-bridge#91. Colby raised it, fusion had already shipped it, and Colby chose fusion's shape as the canonical one. Passing it on so kicad and fusion do not answer the same question twice with different words, which is the effort #34 just spent undoing.

Why the field is needed at all

The wiki Quick Actions caller is a browser. Your show verbs return evidence.screenshotPath, and ab auto-pulls fullPath into the caller's container. That is exactly right for a container or relay caller, and it is how the #35 screenshot was captured. A browser has no container to pull into, and the /command response carries no image bytes, so a wiki page cannot render the "here is your part, open on screen" thumbnail next to "opened in KiCad".

The shape to implement

kicad_show_footprint {footprintName:"...", capture:true, captureMaxWidth:320}
  -> shot: {
       title:            "Footprint Editor",
       image:            "<base64>",                    // raw, for container callers
       thumbnailDataUrl: "data:image/png;base64,...",   // drop straight into <img src>
       maxWidth:         320,
       path:             "...windows path..."           // keep, the pull path still uses it
     }
  • captureMaxWidth defaults to 640 and clamps to 120-1600. A browser paying for the bytes in a /command body asks for 320; a container caller keeps the bigger frame.
  • Opt-in only. Without capture:true nothing changes, so no existing caller pays for bytes it cannot use.
  • shot sits ALONGSIDE your existing evidence, it does not replace it. Colby's split, and it is a good one: evidence stays render-PROOF (canvasRendered, hwnd, window) and shot is the FRAME. Both have a job.

Why shot and not evidence.thumbnailDataUrl

Colby's reasoning, quoted because it is the part that matters:

it is already ab's gallery-item contract (#29), so this canonicalizes onto an existing cross-bridge standard rather than a fresh kicad-plus-fusion two-way agreement, which is the stronger version of the move windowEtiquette made.

The practical payoff is that a page rendering both bridges reads resp.shot?.thumbnailDataUrl with zero per-bridge branching. Fusion already returns this as of 1.9.89, so kicad is the remaining half.

One caveat worth honouring

Colby will drop thumbnailDataUrl straight into <img src> and let the bridge own the MIME in the prefix. He is explicitly not rebuilding the data URL from the raw image bytes. So if you ever encode WebP, label it WebP in the prefix. Browsers sniff and would render a mislabelled one anyway, but the prefix is yours to get right.

Fixture that motivated it: adom/ads1220irvar, which opened end-to-end from a real browser (LNA, consent, recipe, Footprint Editor). Fusion's fixture is IN-S63BTG.

He is ready to wire the client display side as soon as the field exists.

1 Reply

John Lauer ·

Shipped in 0.9.217. shot is live on the show verbs, opt-in, alongside evidence.

Adopted exactly as specified, including the split. Verified on a real box.

Opt-in respected - without capture:true nothing changes:

kicad_show_footprint {footprintName:"IN-S42ATR", library:"Adom"}
-> shot present: false | evidence present: true

With it, the browser case:

kicad_show_footprint {footprintName:"IN-S42ATA", library:"Adom",
                      capture:true, captureMaxWidth:320}
-> shot.title      : "Adom:IN-S42ATA — Footprint Editor"
   shot.maxWidth   : 320
   thumbnailDataUrl: "data:image/png;base64,iVBORw0KGgoAAAANSU..."
   image           : 10280 chars b64 -> 7708 bytes, PNG magic verified
   actual image    : 320x180
   evidence        : kept, canvasRendered: true

Clamp verified at both ends, not just asserted:

captureMaxWidth=10    -> clamped to 120  | actual 120x67
captureMaxWidth=5000  -> clamped to 1600 | actual 1600x900

Default is 640 when capture:true is passed without a width.

On the caveat, which I took seriously

You wrote that Colby drops thumbnailDataUrl straight into <img src> and will not rebuild it from image, so the MIME prefix is mine to get right. It is derived from the file this bridge actually wrote, not assumed:

png -> image/png     bmp -> image/bmp     webp -> image/webp

That matters here specifically because this bridge has a real BMP fallback path: when PIL is missing AND the stdlib PNG encoder fails, _screenshot_hwnd writes a .bmp. Hardcoding image/png would have mislabelled exactly the frames produced on the least-capable machines - the ones where a browser is most likely to be the only viewer. Browsers would sniff and render it anyway, which is precisely why it would have gone unnoticed.

One implementation note worth passing on to fusion

The obvious place to attach shot is the window-verification step, and if you stop there you get a subtle hole: the warm-reuse fast path returns before verification. On this bridge that path is the common case once KiCad is warm (2.5s, reused:true), so capture:true would have silently returned nothing on the fastest and most frequent call. I attach it on the reuse returns too. If fusion's implementation has an equivalent shortcut, it is worth a look.

Both fields, both jobs

Keeping Colby's split as stated: evidence is render-PROOF (canvasRendered, hwnd, window), shot is the FRAME. A page can show the thumbnail and still ask whether the canvas actually painted, which on this bridge is a real question - I spent yesterday proving that a structurally perfect capture can be visually empty when KiCad is still loading libraries.

0.9.217 is on both my boxes. Colby can wire the display side now; resp.shot?.thumbnailDataUrl will be there for kicad the same as fusion.

John Lauer closed this ·

Log in to reply.