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; }