feat(media): extract workspace package
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import type { MediaAsset, MediaFolder, MediaId } from "./types"
|
||||
|
||||
export const MEDIA_ACCEPT =
|
||||
"image/png,image/jpeg,image/webp,image/gif,video/mp4,video/webm,video/ogg,video/quicktime"
|
||||
|
||||
export function formatMediaFileSize(bytes: number): string {
|
||||
if (bytes < 1024) return `${bytes} B`
|
||||
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
|
||||
return `${(bytes / 1024 / 1024).toFixed(1)} MB`
|
||||
}
|
||||
|
||||
export function isMediaFile(file: File): boolean {
|
||||
return file.type.startsWith("image/") || file.type.startsWith("video/")
|
||||
}
|
||||
|
||||
export function mediaKindForFile(file: File): MediaAsset["kind"] | undefined {
|
||||
if (file.type.startsWith("image/")) return "image"
|
||||
if (file.type.startsWith("video/")) return "video"
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function getChildMediaFolders(
|
||||
folders: readonly MediaFolder[],
|
||||
parentId: MediaId | null
|
||||
): MediaFolder[] {
|
||||
const childFolders = folders.filter((folder) => folder.parentId === parentId)
|
||||
childFolders.sort(
|
||||
(left, right) =>
|
||||
(left.sortOrder ?? 0) - (right.sortOrder ?? 0) ||
|
||||
left.name.localeCompare(right.name)
|
||||
)
|
||||
return childFolders
|
||||
}
|
||||
|
||||
export function getMediaFolderPath(
|
||||
folder: MediaFolder,
|
||||
folders: readonly MediaFolder[]
|
||||
): string {
|
||||
const names = [folder.name]
|
||||
const seen = new Set<MediaId>([folder.id])
|
||||
let current = folder
|
||||
|
||||
while (current.parentId !== null) {
|
||||
const parent = folders.find((item) => item.id === current.parentId)
|
||||
if (!parent || seen.has(parent.id)) break
|
||||
seen.add(parent.id)
|
||||
names.unshift(parent.name)
|
||||
current = parent
|
||||
}
|
||||
|
||||
return names.join(" / ")
|
||||
}
|
||||
|
||||
export function getMediaFolderDepth(
|
||||
folder: MediaFolder,
|
||||
folders: readonly MediaFolder[]
|
||||
): number {
|
||||
let depth = 0
|
||||
const seen = new Set<MediaId>([folder.id])
|
||||
let current = folder
|
||||
|
||||
while (current.parentId !== null) {
|
||||
const parent = folders.find((item) => item.id === current.parentId)
|
||||
if (!parent || seen.has(parent.id)) break
|
||||
seen.add(parent.id)
|
||||
depth += 1
|
||||
current = parent
|
||||
}
|
||||
|
||||
return depth
|
||||
}
|
||||
|
||||
export function splitMediaName(name: string) {
|
||||
const extensionIndex = name.lastIndexOf(".")
|
||||
if (extensionIndex <= 0 || extensionIndex === name.length - 1) {
|
||||
return { baseName: name, extension: "" }
|
||||
}
|
||||
|
||||
return {
|
||||
baseName: name.slice(0, extensionIndex),
|
||||
extension: name.slice(extensionIndex),
|
||||
}
|
||||
}
|
||||
|
||||
export function defaultMediaReference(asset: MediaAsset): string {
|
||||
if (
|
||||
asset.kind !== "image" ||
|
||||
!asset.width ||
|
||||
!asset.height ||
|
||||
asset.width <= 0 ||
|
||||
asset.height <= 0
|
||||
) {
|
||||
return asset.url
|
||||
}
|
||||
|
||||
const hashIndex = asset.url.indexOf("#")
|
||||
const url = hashIndex === -1 ? asset.url : asset.url.slice(0, hashIndex)
|
||||
const hash = hashIndex === -1 ? "" : asset.url.slice(hashIndex)
|
||||
const separator = url.includes("?")
|
||||
? url.endsWith("?") || url.endsWith("&")
|
||||
? ""
|
||||
: "&"
|
||||
: "?"
|
||||
|
||||
return `${url}${separator}w=${asset.width}&h=${asset.height}${hash}`
|
||||
}
|
||||
Reference in New Issue
Block a user