
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
40 lines
1.7 KiB
TypeScript
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}`
|
|
}
|