107 lines
2.9 KiB
TypeScript
107 lines
2.9 KiB
TypeScript
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}`
|
|
}
|