107 lines
4.4 KiB
TypeScript
107 lines
4.4 KiB
TypeScript
import * as electronRemote from '@electron/remote';
|
|
const electronConsole = electronRemote.getGlobal('console') as Console;
|
|
import Logger from '../../../logger/logger';
|
|
const LOG = Logger.create(__filename, electronConsole);
|
|
|
|
import * as moment from 'moment';
|
|
import * as FileType from 'file-type';
|
|
|
|
import ElementsUtil from './require/elements-util.js';
|
|
|
|
import { Message, Member } from '../data-types';
|
|
import ClientController from '../client-controller';
|
|
import Q from '../q-module';
|
|
import createImageOverlay from './overlay-image';
|
|
import createImageContextMenu from './context-menu-image';
|
|
|
|
class ShouldNeverHappenError extends Error {
|
|
constructor(...args: any[]) {
|
|
super(...args);
|
|
this.name = 'ShouldNeverHappenError';
|
|
}
|
|
}
|
|
|
|
export default function createImageResourceMessage(document: Document, q: Q, server: ClientController, message: Message) {
|
|
if (!message.resourceId || !message.resourcePreviewId || !message.resourceName) {
|
|
throw new ShouldNeverHappenError('Message is not a resource message');
|
|
}
|
|
|
|
// Scale down the image to the proper width/height
|
|
// max width is 400px, max height is 300px
|
|
if (message.resourceWidth && message.resourceHeight) {
|
|
if (message.resourceWidth > 400) {
|
|
let scale = 400 / message.resourceWidth;
|
|
message.resourceWidth *= scale;
|
|
message.resourceHeight *= scale;
|
|
}
|
|
if (message.resourceHeight > 300) {
|
|
let scale = 300 / message.resourceHeight;
|
|
message.resourceWidth *= scale;
|
|
message.resourceHeight *= scale;
|
|
}
|
|
message.resourceWidth = Math.floor(message.resourceWidth);
|
|
message.resourceHeight = Math.floor(message.resourceHeight);
|
|
}
|
|
|
|
let memberInfo: {
|
|
roleColor: string | null,
|
|
displayName: string,
|
|
avatarResourceId: string | null
|
|
};
|
|
if (message.member instanceof Member) {
|
|
memberInfo = {
|
|
roleColor: message.member.roleColor,
|
|
displayName: message.member.displayName,
|
|
avatarResourceId: message.member.avatarResourceId
|
|
};
|
|
} else {
|
|
memberInfo = {
|
|
roleColor: null,
|
|
displayName: 'Unknown Member',
|
|
avatarResourceId: null
|
|
};
|
|
}
|
|
|
|
let nameStyle = memberInfo.roleColor != null ? 'color: ' + memberInfo.roleColor : '';
|
|
let element = q.create({ class: 'message', 'meta-id': message.id, 'meta-member-id': message.member.id, 'meta-server-id': server.id, content: [
|
|
{ class: 'member-avatar', content: { tag: 'img', src: './img/loading.svg', alt: memberInfo.displayName } },
|
|
{ class: 'right', content: [
|
|
{ class: 'header', content: [
|
|
{ class: 'member-name', style: nameStyle, content: memberInfo.displayName },
|
|
{ class: 'timestamp', content: moment(message.sent).calendar(ElementsUtil.calendarFormats) }
|
|
] },
|
|
{ class: 'content image', style: `width: ${message.resourceWidth}px; height: ${message.resourceHeight}px;`, content:
|
|
{ tag: 'img', src: './img/loading.svg', alt: message.resourceName } }, // src will be replaced later
|
|
{ class: 'content text', content: ElementsUtil.parseMessageText(message.text ?? '') }
|
|
] }
|
|
] }) as HTMLElement;
|
|
q.$$$(element, '.content.image').addEventListener('click', (e) => {
|
|
document.body.appendChild(createImageOverlay(document, q, server, message.resourceId as string, message.resourceName as string));
|
|
});
|
|
(async () => {
|
|
(q.$$$(element, '.member-avatar img') as HTMLImageElement).src =
|
|
await ElementsUtil.getImageBufferFromResourceFailSoftly(server, memberInfo.avatarResourceId);
|
|
})();
|
|
(async () => {
|
|
try {
|
|
let buffer = await server.fetchResource(message.resourcePreviewId as string);
|
|
let src = await ElementsUtil.getImageBufferSrc(buffer);
|
|
(q.$$$(element, '.content.image img') as HTMLImageElement).src = src;
|
|
|
|
let { mime, ext } = (await FileType.fromBuffer(buffer)) ?? { mime: null, ext: null };
|
|
if (mime === null || ext === null) throw new Error('unable to get mime/ext');
|
|
|
|
q.$$$(element, '.content.image').addEventListener('contextmenu', (e) => {
|
|
let contextMenu = createImageContextMenu(document, q, server, message.resourceName as string, buffer, mime as string, ext as string, true);
|
|
document.body.appendChild(contextMenu);
|
|
let relativeTo = { x: e.pageX, y: e.pageY };
|
|
ElementsUtil.alignContextElement(contextMenu, relativeTo, { top: 'centerY', left: 'right' });
|
|
});
|
|
} catch (e) {
|
|
LOG.error('error loading preview image', e);
|
|
(q.$$$(element, '.content.image img') as HTMLImageElement).src = './img/error.png';
|
|
}
|
|
})();
|
|
return element;
|
|
}
|