tldraw/apps/dotcom/src/utils/assetHandler.ts
Mime Čuvalo 73c2b1088a
image: follow-up fixes for LOD (#3934)
couple fixes and improvements for the LOD work.

- add `format=auto` for Cloudflare to send back more modern image
formats
- fix the broken asset logic that regressed (should not have looked at
`url`)
- fix stray parenthesis, omg
- rm the `useValueDebounced` function in lieu of just debouncing the
resolver. the problem was that the initial load in a multiplayer room
has a zoom of 1 but then the real zoom comes in (via the url) and so we
would double load all images 😬. this switches the debouncing to the
resolving stage, not making it tied to the zoom specifically.


### Change Type

<!--  Please select a 'Scope' label ️ -->

- [x] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff

<!--  Please select a 'Type' label ️ -->

- [x] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
2024-06-14 10:01:50 +00:00

40 lines
1.7 KiB
TypeScript

import { AssetContextProps, MediaHelpers, TLAsset } from 'tldraw'
import { ASSET_BUCKET_ORIGIN, ASSET_UPLOADER_URL } from './config'
export async function resolveAsset(asset: TLAsset | null | undefined, context: AssetContextProps) {
if (!asset || !asset.props.src) return null
// We don't deal with videos at the moment.
if (asset.type === 'video') return asset.props.src
// Assert it's an image to make TS happy.
if (asset.type !== 'image') return null
// Don't try to transform data: URLs, yikes.
if (!asset.props.src.startsWith('http:') && !asset.props.src.startsWith('https:'))
return asset.props.src
// Don't try to transform animated images.
if (MediaHelpers.isAnimatedImageType(asset?.props.mimeType) || asset.props.isAnimated)
return asset.props.src
// Assets that are under a certain file size aren't worth transforming (and incurring cost).
if (asset.props.fileSize === -1 || asset.props.fileSize < 1024 * 1024 * 1.5 /* 1.5 MB */)
return asset.props.src
// N.B. navigator.connection is only available in certain browsers (mainly Blink-based browsers)
// 4g is as high the 'effectiveType' goes and we can pick a lower effective image quality for slower connections.
const networkCompensation =
!context.networkEffectiveType || context.networkEffectiveType === '4g' ? 1 : 0.5
const width = Math.ceil(asset.props.w * context.steppedScreenScale * networkCompensation)
if (process.env.NODE_ENV === 'development') {
return asset.props.src
}
// On preview, builds the origin for the asset won't be the right one for the Cloudflare transform.
const src = asset.props.src.replace(ASSET_UPLOADER_URL, ASSET_BUCKET_ORIGIN)
return `${ASSET_BUCKET_ORIGIN}/cdn-cgi/image/format=auto,width=${width},dpr=${context.dpr},fit=scale-down,quality=92/${src}`
}