@jsxc/jsxc
Version:
Real-time XMPP chat application with video calls, file transfer and encrypted communication
217 lines (163 loc) • 5.26 kB
text/typescript
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<void>;
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 = $('<div>');
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 = $('<img alt="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<void> {
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);
});
}
}