Commit ff3b422
authored
feat(files): preview HEIC photos in the file viewer (#6350)
* feat(files): preview HEIC photos in the file viewer
The agent can read HEIC since #6346, but the Files page still showed 'Preview
not available' — an <img> pointed at the serve route got the stored HEIF under
nosniff, which no browser outside Safari renders.
The serve route now resolves a JPEG derivative for HEIF bytes, cached in the
artifact store and keyed by the source's storage key. Workspace keys are
regenerated on every content replacement, so the key is already a content
version and using it avoids streaming the original just to hash it. Caching
matters here in a way it did not for the vision path: a preview is re-fetched
on every view and the WASM decode costs roughly a second for a phone photo.
The original stays the stored object — downloads and raw=1 serve it untouched,
so this never changes what a user gets back.
compileDocumentIfNeeded becomes resolveServableBytes, since it now resolves
images as well as generated documents. .tif/.tiff stay download-only: nothing
decodes those on either side.
* fix(files): make the preview derivative opt-in and never show a broken image
Five issues from review, all interlocking around one decision.
The derivative is now requested with preview=1 rather than suppressed with
raw=1. raw=1 would have corrupted generated-document downloads: every
non-markdown workspace download routes through the serve route and relies on
resolveServableDocBytes compiling stored source into the real binary. Opt-in
separates the three consumers cleanly — previews get the JPEG, downloads get
untouched stored bytes, and doc compilation stays unconditional.
- Public shares resolve the derivative too, with the same preview/download
split; the viewer requests it, the download button does not.
- Split the brand predicate. isHeifContainer stays broad for the vision path,
where it only runs after sharp has already failed. The serve path runs
first, so it uses isHevcHeifContainer — an AVIF was costing a storage
round-trip, a WASM load and a misleading warn per request.
- A derivative that cannot be produced (past the 20MB ceiling, or a decode
failure) now falls back to 'Preview not available' instead of a broken
image. UnsupportedPreview moved to preview-shared to avoid a module cycle.
- The chat composer chip requests the derivative, so HEIC attachments stop
rendering as broken thumbnails.
* fix(files): reset the image preview when the file is overwritten
An overwrite preserves the storage key, which is what the parent keys this
component on, so only the URL version changes and it never remounts. The
previous bytes' outcome therefore stuck, leaving a replaced image parked on
'Preview not available' until something else forced a remount.
Reset on URL change during render rather than in an effect — this is derived
state, and an effect would render the stale outcome first.
* improvement(files): drop the dead preview reset and cap the ftyp brand scan
- Content writes mint a new storage key, so the parent's key={file.key}
already remounts ImagePreview; the render-phase reset was unreachable and
made renames flash a loading overlay.
- Clamp the ftyp compatible-brand scan to a real box size. The declared size
is attacker-controlled and this now runs on every preview request.
- UnsupportedPreview takes a primitive name so memo is load-bearing.
- Fix the hardcoded ? in the public preview URL builder.
* improvement(copilot): only ask for a preview derivative on image thumbnails
A video has no derivative path, so preview=1 there only spent a brand sniff
per request. Adds the missing test coverage for the helper.1 parent a512a26 commit ff3b422
17 files changed
Lines changed: 547 additions & 103 deletions
File tree
- apps/sim
- app
- api/files
- public/[token]/content
- serve/[...path]
- workspace/[workspaceId]/files/components/file-viewer
- hooks
- lib
- api/contracts
- copilot/chat
- uploads/server
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
34 | | - | |
35 | | - | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
36 | 39 | | |
37 | 40 | | |
38 | 41 | | |
| |||
45 | 48 | | |
46 | 49 | | |
47 | 50 | | |
| 51 | + | |
48 | 52 | | |
49 | 53 | | |
50 | 54 | | |
| |||
77 | 81 | | |
78 | 82 | | |
79 | 83 | | |
80 | | - | |
81 | 84 | | |
82 | 85 | | |
83 | 86 | | |
84 | | - | |
85 | | - | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
86 | 98 | | |
87 | 99 | | |
88 | 100 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
| |||
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
28 | 38 | | |
29 | | - | |
30 | | - | |
31 | | - | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
32 | 46 | | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
39 | 54 | | |
40 | | - | |
41 | | - | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
42 | 66 | | |
43 | 67 | | |
44 | 68 | | |
| |||
117 | 141 | | |
118 | 142 | | |
119 | 143 | | |
| 144 | + | |
120 | 145 | | |
121 | 146 | | |
122 | | - | |
123 | | - | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
124 | 152 | | |
125 | 153 | | |
126 | 154 | | |
| |||
135 | 163 | | |
136 | 164 | | |
137 | 165 | | |
138 | | - | |
| 166 | + | |
139 | 167 | | |
140 | 168 | | |
141 | | - | |
| 169 | + | |
142 | 170 | | |
143 | 171 | | |
144 | 172 | | |
| |||
165 | 193 | | |
166 | 194 | | |
167 | 195 | | |
168 | | - | |
169 | | - | |
| 196 | + | |
170 | 197 | | |
171 | 198 | | |
172 | 199 | | |
| |||
198 | 225 | | |
199 | 226 | | |
200 | 227 | | |
201 | | - | |
202 | | - | |
203 | | - | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
204 | 232 | | |
205 | | - | |
| 233 | + | |
206 | 234 | | |
207 | | - | |
208 | | - | |
| 235 | + | |
| 236 | + | |
209 | 237 | | |
210 | 238 | | |
211 | 239 | | |
212 | 240 | | |
213 | 241 | | |
214 | 242 | | |
215 | 243 | | |
216 | | - | |
| 244 | + | |
217 | 245 | | |
218 | 246 | | |
219 | 247 | | |
| |||
224 | 252 | | |
225 | 253 | | |
226 | 254 | | |
227 | | - | |
228 | | - | |
229 | | - | |
| 255 | + | |
| 256 | + | |
230 | 257 | | |
231 | 258 | | |
232 | 259 | | |
| |||
260 | 287 | | |
261 | 288 | | |
262 | 289 | | |
263 | | - | |
264 | | - | |
265 | | - | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
266 | 294 | | |
267 | | - | |
| 295 | + | |
268 | 296 | | |
269 | | - | |
270 | | - | |
| 297 | + | |
| 298 | + | |
271 | 299 | | |
272 | 300 | | |
273 | 301 | | |
| |||
280 | 308 | | |
281 | 309 | | |
282 | 310 | | |
283 | | - | |
| 311 | + | |
284 | 312 | | |
285 | 313 | | |
286 | 314 | | |
| |||
Lines changed: 4 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
227 | 227 | | |
228 | 228 | | |
229 | 229 | | |
| 230 | + | |
| 231 | + | |
230 | 232 | | |
231 | 233 | | |
232 | 234 | | |
233 | 235 | | |
234 | 236 | | |
235 | | - | |
236 | | - | |
| 237 | + | |
| 238 | + | |
237 | 239 | | |
238 | 240 | | |
239 | 241 | | |
| |||
Lines changed: 10 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
51 | 53 | | |
52 | 54 | | |
53 | 55 | | |
| |||
58 | 60 | | |
59 | 61 | | |
60 | 62 | | |
| 63 | + | |
| 64 | + | |
61 | 65 | | |
62 | 66 | | |
63 | 67 | | |
| |||
68 | 72 | | |
69 | 73 | | |
70 | 74 | | |
| 75 | + | |
| 76 | + | |
71 | 77 | | |
72 | 78 | | |
73 | 79 | | |
| |||
Lines changed: 4 additions & 22 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
| |||
170 | 171 | | |
171 | 172 | | |
172 | 173 | | |
173 | | - | |
| 174 | + | |
174 | 175 | | |
175 | 176 | | |
176 | 177 | | |
| |||
259 | 260 | | |
260 | 261 | | |
261 | 262 | | |
262 | | - | |
| 263 | + | |
263 | 264 | | |
264 | 265 | | |
265 | 266 | | |
| |||
421 | 422 | | |
422 | 423 | | |
423 | 424 | | |
424 | | - | |
425 | | - | |
426 | | - | |
427 | | - | |
428 | | - | |
429 | | - | |
430 | | - | |
431 | | - | |
432 | | - | |
433 | | - | |
434 | | - | |
435 | | - | |
436 | | - | |
437 | | - | |
438 | | - | |
439 | | - | |
440 | | - | |
441 | | - | |
442 | | - | |
0 commit comments