import Log from './util/Log'; import UUID from './util/UUID'; import PersistentMap from './util/PersistentMap'; import Client from './Client'; import beautifyBytes from './ui/util/ByteBeautifier'; import ImageHelper from '@util/ImageHelper'; import FileHelper from '@util/FileHelper'; export type AttachmentHandler = (attachment: Attachment, active: boolean) => Promise; export default class Attachment { private static handlers: { [key: string]: AttachmentHandler } = {}; public static registerHandler(key: string, handler: AttachmentHandler) { Attachment.handlers[key] = handler; } private data: string; private file: File; private uid: string; private properties: PersistentMap; constructor(name: string, mimeType: string, data: string); constructor(file: File); constructor(uid: string); constructor() { if (arguments.length === 1 && typeof arguments[0] === 'string') { this.uid = arguments[0]; } let storage = Client.getStorage(); this.properties = new PersistentMap(storage, this.getUid()); if (arguments[0] instanceof File) { this.file = arguments[0]; this.properties.set({ mimeType: this.file.type, name: this.file.name, size: this.file.size, }); } else if (arguments.length === 3) { this.properties.set({ mimeType: arguments[1], name: arguments[0], }); this.data = arguments[2]; } if (this.isImage() && this.file && !this.hasThumbnailData()) { this.generateThumbnail(); } } public delete() { this.properties.delete(); } public getUid(): string { if (!this.uid) { this.uid = UUID.v4(); } return this.uid; } public getData() { if (!this.data) { this.data = this.properties.get('data'); } return this.data; } public setData(data: string): boolean { this.data = data; if (typeof data === 'string' && data.length < 1024) { this.properties.set('data', data); return true; } Log.warn('Data to large to store'); return false; } public setProcessed(processed: boolean) { this.properties.set('processed', processed); } public isProcessed(): boolean { return !!this.properties.get('processed'); } public getSize(): number { return this.properties.get('size'); } public getMimeType(): string { return this.properties.get('mimeType'); } public setThumbnailData(thumbnail: string) { this.properties.set('thumbnail', thumbnail); } public getThumbnailData() { return this.properties.get('thumbnail'); } public getName() { return this.properties.get('name'); } public getHandler() { let handlerKey = this.properties.get('handler'); return handlerKey && Attachment.handlers[handlerKey]; } public setHandler(key: string) { this.properties.set('handler', key); } public setFile(file: File) { this.file = file; } public getFile(): File { return this.file; } public isPersistent(): boolean { return !!this.properties.get('data'); } public isImage(): boolean { return /^image\/(jpeg|jpg|gif|png|svg)/i.test(this.getMimeType()); } public hasThumbnailData(): boolean { return !!this.getThumbnailData(); } public hasData(): boolean { return !!this.getData(); } public clearData() { this.data = null; } public getElement() { let type = this.getMimeType(); let name = this.getName(); let size = beautifyBytes(this.getSize()); let wrapperElement = $('
'); wrapperElement.addClass('jsxc-attachment'); wrapperElement.addClass('jsxc-' + type.replace(/\//, '-')); wrapperElement.addClass('jsxc-' + type.replace(/^([^/]+)\/.*/, '$1')); let title = `${name} (${size})`; if (FileReader && this.isImage() && this.file) { // show image preview let img = $('preview'); img.attr('title', title); // img.attr('src', jsxc.options.get('root') + '/img/loading.gif'); FileHelper.getDataURLFromFile(this.file).then(src => { img.attr('src', src); }); return wrapperElement.append(img); } else { return wrapperElement.text(title); } } public registerThumbnailHook = (hook: (thumbnail?: string) => void) => { this.properties.registerHook('thumbnail', hook); }; public generateThumbnail(force: boolean = false): Promise { if (typeof Image === 'undefined') { return; } if (!this.isImage() || /^image\/svg/i.test(this.getMimeType())) { return; } if (force || !this.hasData()) { if (this.file) { FileHelper.getDataURLFromFile(this.file).then(data => { this.data = data; this.generateThumbnail(); }); } return; } return ImageHelper.scaleDown(this.data).then(thumbnailData => { this.properties.set('thumbnail', thumbnailData); }); } }