dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 1 | import type { ImagePack, PackImage } from './types'; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 2 | |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 3 | export const MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 4 | |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 5 | export interface StagedAttachment { |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 6 | id: number; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 7 | file: File; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 8 | previewUrl: string | null; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 9 | } |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 10 | |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 11 | export interface StickerHandlers { |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 12 | onSend: (pack: ImagePack, image: PackImage) => void; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 13 | onClone: (pack: ImagePack, image: PackImage, x: number, y: number) => void; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 14 | onClonePack: (pack: ImagePack, x: number, y: number) => void; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 15 | onManage: () => void; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 16 | roomName: (roomId: string) => string; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 17 | } |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 18 | |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 19 | let nextId = 1; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 20 | |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 21 | /** Files outside the homeserver-friendly size range are reported through `reject` and skipped. */ |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 22 | export function stageFiles(files: File[], reject: (message: string) => void): StagedAttachment[] { |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 23 | const accepted: StagedAttachment[] = []; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 24 | for (const file of files) { |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 25 | if (file.size === 0 || file.size > MAX_ATTACHMENT_BYTES) { |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 26 | reject(`${file.name || 'File'} must be between 1 byte and 20 MiB.`); |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 27 | continue; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 28 | } |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 29 | accepted.push({ id: nextId++, file, previewUrl: file.type.startsWith('image/') ? URL.createObjectURL(file) : null }); |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 30 | } |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 31 | return accepted; |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 32 | } |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 33 | |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 34 | export function releaseStaged(list: StagedAttachment[]): void { |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 35 | for (const attachment of list) if (attachment.previewUrl) URL.revokeObjectURL(attachment.previewUrl); |
dda384a360e0 | atagen | 2026-10-25 10:27 UTC | 36 | } |