feat(media): extract workspace package

This commit is contained in:
Maofeng
2026-09-20 16:44:15 +08:00
parent 2a6284d1b0
commit c519d4e74b
29 changed files with 112 additions and 16 deletions
+59
View File
@@ -0,0 +1,59 @@
export interface MediaDimensions {
height: number
width: number
}
const METADATA_TIMEOUT_MS = 10_000
function waitForDimensions(
file: File,
element: HTMLImageElement | HTMLVideoElement,
successEvent: "load" | "loadedmetadata"
): Promise<MediaDimensions | undefined> {
return new Promise((resolve) => {
const objectUrl = URL.createObjectURL(file)
let settled = false
const timeout = window.setTimeout(finish, METADATA_TIMEOUT_MS)
function finish(dimensions?: MediaDimensions) {
if (settled) return
settled = true
window.clearTimeout(timeout)
URL.revokeObjectURL(objectUrl)
resolve(dimensions)
}
element.addEventListener(
successEvent,
() => {
const width =
element instanceof HTMLVideoElement
? element.videoWidth
: element.naturalWidth
const height =
element instanceof HTMLVideoElement
? element.videoHeight
: element.naturalHeight
finish(width > 0 && height > 0 ? { height, width } : undefined)
},
{ once: true }
)
element.addEventListener("error", () => finish(), { once: true })
element.src = objectUrl
})
}
/** Reads intrinsic dimensions before an adapter uploads an image or video. */
export function readMediaDimensions(
file: File
): Promise<MediaDimensions | undefined> {
if (file.type.startsWith("image/")) {
return waitForDimensions(file, new Image(), "load")
}
if (file.type.startsWith("video/")) {
const video = document.createElement("video")
video.preload = "metadata"
return waitForDimensions(file, video, "loadedmetadata")
}
return Promise.resolve(undefined)
}