forked from BRETT/BRETT
- Audio/video attachments render as media cards (cover or icon, title/artist/size) instead of plain file chips; image attachments use 3:2 thumbnails matching the audio card height - Players open in a Popover (autoplay on open) with a dimming overlay; AudioPlayerDialog/VideoPlayerDialog removed - New useMediaVolume composable shares volume/mute between all audio players and Plyr via the 4brett-player storage key - Player buttons and Plyr controls follow the theme border radius - Portrait videos: aspect is applied even when metadata loaded before hydration, and the raw video is height-capped pre-JS Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
export interface AttachmentAudioMeta {
|
|
title: string | null
|
|
artist: string | null
|
|
album: string | null
|
|
voice?: boolean
|
|
}
|
|
|
|
export interface CommentAttachment {
|
|
id: number
|
|
name: string
|
|
url: string
|
|
mimeType: string | null
|
|
size: number | null
|
|
cover?: string | null
|
|
meta?: AttachmentAudioMeta | null
|
|
}
|
|
|
|
export const MAX_COMMENT_ATTACHMENTS = 8
|
|
export const MAX_ATTACHMENT_SIZE = 200 * 1024 * 1024 // 200 MB
|
|
|
|
export function isImageAttachment(a: { mimeType?: string | null, name?: string }): boolean {
|
|
return !!a.mimeType?.startsWith('image/')
|
|
|| (!!a.name && /\.(avif|bmp|gif|jpe?g|png|svg|webp)$/i.test(a.name))
|
|
}
|
|
|
|
export function isAudioAttachment(a: { mimeType?: string | null, name?: string }): boolean {
|
|
return !!a.mimeType?.startsWith('audio/')
|
|
|| (!!a.name && /\.(mp3|flac|ogg|wav|m4a|aac|opus)$/i.test(a.name))
|
|
}
|
|
|
|
export function isVideoAttachment(a: { mimeType?: string | null, name?: string }): boolean {
|
|
return !!a.mimeType?.startsWith('video/')
|
|
|| (!!a.name && /\.(mp4|webm|mov|mkv|avi|m4v|mpg|mpeg|ts|mts)$/i.test(a.name))
|
|
}
|
|
|
|
export function isVoiceAttachment(a: { meta?: { voice?: boolean } | null }): boolean {
|
|
return a.meta?.voice === true
|
|
}
|
|
|
|
export function formatFileSize(bytes: number | null | undefined): string {
|
|
if (!bytes || bytes <= 0) return ''
|
|
return bytes >= 1024 * 1024
|
|
? `${(bytes / 1024 / 1024).toFixed(1)} MB`
|
|
: `${Math.max(1, Math.round(bytes / 1024))} KB`
|
|
}
|