fix: lay the screenshot preview out to the image, not to the request
The preview rendered, but with dead space around it. `MdImage.qml` sizes its container to the request rather than to the image, so with no hint it is the full pane width and 200px tall and the image is aspect-fitted inside that. A wide capture sat in a letterbox: measured against the real captures in the support directory, a 4:1 crop wasted about 106px of the 200px container and a 6.7:1 crop about 140px, which is what made the transcript look gappy and put the caption far below the image. - `readAttachment` now reads the PNG `IHDR` chunk, so `Attachment` carries the real dimensions and they are persisted with the turn. - `previewBox` computes an exact box from those dimensions, scaled to fit 400x200 with the scale capped at 1 so a small capture is not upscaled, and `imageSource` emits it as the `raycast-width`/`raycast-height` hints `parseImageSize` looks for. The path is resolved from the URL before the query, so the hints never reach the file name. - The alt text is now "Screenshot". It is drawn centred under the image, so the sentence "Screenshot attached" read as a stray line of prose floating in the middle of the pane. - A pending note no longer stacks on top of the empty-transcript placeholder. Both said the same thing, one line under the other, once a snip was attached. A capture with no readable header simply falls back to the old sizing. Verified: 293 tests, tsc, eslint, prettier, and vici build.
This commit is contained in:
@@ -189,7 +189,11 @@ A few decisions worth knowing about before you change things:
|
||||
|
||||
**The transcript is text plus the attached images, and nothing in it is bold except an error.** The answer is what gets read, so it is plain body text carrying no label; the question is a blockquote, which the renderer draws dimmed, italic, and with a left rule. A `**You**` / `**Lam**` header on each exchange gave both speakers identical weight and made the answer sit behind chrome. Tool calls collapse to one italic line (_Tools: `web_search`_) rather than a bold header plus a list, so they stay below the answer too. Raycast solves the same problem with alignment, but markdown offers no alignment control.
|
||||
|
||||
**An attached screenshot is rendered, not described.** This is a correction: the transcript used to say `_Screenshot attached_` and leave it at that, on the belief that Vicinae could not resolve a local image. It can. `imageProviderUrl` in `markdown-model.cpp` routes `file://` (and a scheme-less string) through `ImageURL::local`, and `MdImage.qml` draws it block-level and centred with the alt text as an italic caption underneath. The one real limit is that the rendered height is capped at 200px regardless of any size hint, so it is a thumbnail rather than something readable, which is why the action panel still offers Open Screenshot for the full image. The alt text is not decoration either: it is what remains if the capture file has since been deleted. A preview of an unsent attachment is shown the same way, so a snip is visible before the question about it exists.
|
||||
**An attached screenshot is rendered, not described.** This is a correction: the transcript used to say `_Screenshot attached_` and leave it at that, on the belief that Vicinae could not resolve a local image. It can. `imageProviderUrl` in `markdown-model.cpp` routes `file://` (and a scheme-less string) through `ImageURL::local`, and `MdImage.qml` draws it block-level and centred with the alt text as an italic caption underneath.
|
||||
|
||||
**The preview is asked for as an exact box, which is why the PNG header is parsed.** `MdImage.qml` sizes its container to the *request* rather than to the image: with no hint it is the full pane width and 200px tall, and the image is aspect-fitted inside that, so a wide capture sits in a letterbox with dead space above and below. Measured on real captures here, a 4:1 crop wasted about 106px of a 200px container and a 6.7:1 crop wasted about 140px. `previewBox` therefore computes a box from the image's real dimensions, scales it to fit 400x200, and emits it as the `raycast-width` and `raycast-height` hints the renderer reads, so the container matches the image and nothing is wasted. The scale is capped at 1 so a small capture is not blown up.
|
||||
|
||||
The rendered height stays capped at 200px whatever is asked for (`Math.min(_rawH, 200, maxImageHeight)`), so this is a thumbnail rather than something readable, which is why the action panel still offers Open Screenshot for the full image. The alt text is short for the same reason it is not empty: whatever is there is drawn centred under the image, so a sentence reads as a stray line of prose, and it is the only thing left if the capture file has since been deleted. A preview of an unsent attachment is shown the same way, so a snip is visible before the question about it exists.
|
||||
|
||||
**Code fences are labelled so Vicinae can colour them.** `MdCodeBlock.qml` already provides the dark panel, a header naming the language, and a Copy button, so none of that is built here. The language string is what turns on highlighting: `syntax::highlight` resolves it with `definitionForName(language)` and then `definitionForFileName("file." + language)`. So `bash` and `ts` colour correctly, while an unrecognised string such as `terminal` still renders a label but produces no highlighting at all, so a wrong label is worse than none. `code.ts` therefore labels bare fences conservatively, only when a signal is clear, and the default prompt asks for a language on every fence.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user