import {
isAudioMimeType as e,
isAudioVoicePath as t,
base64ToWaveform as r,
waveformToBase64 as i,
} from "../../lib/file"
import {
FILE_PREVIEW_MAX_BYTES_MEDIUM as n,
FILE_PREVIEW_MAX_BYTES_SMALL as o,
FILE_PREVIEW_MAX_FRAMES_MEDIUM as a,
FILE_PREVIEW_MAX_FRAMES_SMALL as l,
FILE_PREVIEW_MIME_TYPE as s,
FILE_PREVIEW_SIZE_LARGE as m,
FILE_PREVIEW_SIZE_MEDIUM as u,
FILE_PREVIEW_SIZE_SMALL as p,
FILE_VOICE_MIME_TYPE as h,
} from "./file.constants"
export const getFileId = (e) => {
if (!e) return ""
const { externalBlob: t } = e
if (t) return `${t.id}_${t.blob?.blockOffset}`
const { externalDrive: r } = e
return r ? `${r.id}_${r.path}_${r.version}` : ""
}
export const getFileByteLength = (e) => e?.externalBlob?.blob?.byteLength || 0
export const PREVIEW_SIZE = { SMALL: "small", MEDIUM: "medium", LARGE: "large" }
export const PREVIEW_SIZE_VALUES = Object.values(PREVIEW_SIZE)
export const PREVIEW_PARAMS_BY_SIZE = {
small: { maxHeight: p, maxWidth: p, maxBytes: o, maxFrames: l },
medium: { maxHeight: u, maxWidth: u, maxBytes: n, maxFrames: a },
}
export const PREVIEW_PARAMS_DEFAULT = { maxHeight: m, maxWidth: m }
export function flattenFileWaveForm(i) {
return i && i.userdata && e(i.mimetype) && t(i.name) ? r(i.userdata) : null
}
export const getMaxDimension = (e) => (e ? Math.max(e.height || 0, e.width || 0) : 0)
export function getShouldOverridePreviewPointer(e, t) {
if (e.mimetype !== s) return !1
const { maxHeight: r } = PREVIEW_PARAMS_BY_SIZE[t] || PREVIEW_PARAMS_DEFAULT
return r > getMaxDimension(e)
}
export function flattenFileSource(e, t) {
const r = e.pointer?.inlined
return r ? `data:${e.metadata?.mimetype};base64,${r}` : t?.httpLink
}
export const getIsVoiceNote = (e, t) => Boolean(h === e && t?.startsWith("recording-"))
export function flattenFileMetadata(e, t) {
if (!e || !e.metadata) return null
const { pointer: r, metadata: i } = e,
{ own: n = !1, cleared: o = !1 } = t || {},
{
dimensions: a,
byteLength: l = getFileByteLength(r),
name: s = "",
mimetype: m = "application/octet-stream",
duration: u = 0,
isPreview: p,
} = i,
h = getFileId(r),
c = getIsVoiceNote(m, s)
return {
isPreview: p,
width: a?.width,
height: a?.height,
name: s,
own: n,
duration: u,
byteLength: l,
mimetype: m,
id: h,
pointer: r,
httpLink: flattenFileSource(e, t),
cleared: o,
isVoiceNote: c,
}
}
export function flattenFilePreviews(e) {
const t = e.preview,
r = e.entry?.preview || {}
return t
? {
small: flattenFileMetadata(t.small, r.small),
medium: flattenFileMetadata(t.medium, r.medium),
large: flattenFileMetadata(t.large, r.large),
audio: flattenFileWaveForm(e.metadata),
}
: {}
}
export function flattenFile(e) {
return e ? { ...flattenFileMetadata(e, e.entry), preview: flattenFilePreviews(e) } : null
}
export function restoreFileCoreMetadata(e) {
if (!e) return null
const t = {}
for (const r of Object.keys(e))
["name", "mimetype", "duration", "byteLength", "isPreview"].includes(r) && (t[r] = e[r])
return (
e.preview?.audio && (t.userdata = i(e.preview.audio)),
e.height && e.width && (t.dimensions = { height: e.height, width: e.width }),
t
)
}
export function restoreFileCoreEntry(e) {
if (!e) return null
const { cleared: t, httpLink: r, own: i, byteLength: n } = e
return { cleared: t, httpLink: r, own: i, byteLength: n }
}
export function restoreCoreFileWithoutPreview(e) {
return e
? { pointer: e.pointer, metadata: restoreFileCoreMetadata(e), entry: restoreFileCoreEntry(e) }
: null
}
export function restoreFileCorePreview(e) {
const t = {}
if (!e?.preview) return t
const { preview: r } = e
return (
r.small && (t.small = restoreCoreFileWithoutPreview(r.small)),
r.medium && (t.medium = restoreCoreFileWithoutPreview(r.small)),
r.large && (t.large = restoreCoreFileWithoutPreview(r.small)),
t
)
}
export function restoreCoreFile(e) {
return e ? { ...restoreCoreFileWithoutPreview(e), preview: restoreFileCorePreview(e) } : null
}
export function getHttpLinkPreview(e, t) {
return e?.preview?.[t]?.httpLink
}
export function parseCoreFile(e) {
if (e) {
if (!e.pointer) throw new Error("parseCoreFile: no pointer")
return flattenFile(e)
}
}
export const getCanPreviewFile = (e) =>
Boolean(
"number" == typeof e.height &&
"number" == typeof e.width &&
["image", "video"].includes(e.mimetype.split("/")[0] || ""),
)
export const isFileEntryChanged = (e, t) => {
if (!e || !t) return !!e || !!t
if (e.width !== t.width || e.height !== t.height || e.mimetype !== t.mimetype) return !0
const r = e.pointer?.blob,
i = t.pointer?.blob
return r && i
? r.blockOffset !== i.blockOffset ||
r.blockLength !== i.blockLength ||
r.byteOffset !== i.byteOffset ||
r.byteLength !== i.byteLength
: !!r || !!i
}
export const mergeFileEntry = (e, t) => ({ ...e, ...t, httpLink: t?.httpLink || e?.httpLink })
export const mergeRoomInfoFiles = (e, t) => {
const r = new Map()
return (
e.forEach((e) => r.set(e.id, e)),
t.forEach((e) => r.set(e.id, e)),
Array.from(r.values())
)
}