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 ElementsUtil from './require/elements-util.js'; import Globals from '../globals'; import { Channel } from '../data-types'; import Q from '../q-module'; import UI from '../ui'; import createUploadOverlayFromPath from './overlay-upload-path'; import createUploadOverlayFromDataTransferItem from './overlay-upload-datatransfer'; import createUploadDropTarget from './overlay-upload-drop-target'; import CombinedGuild from '../guild-combined'; export default function bindTextInputEvents(document: Document, q: Q, ui: UI): void { // Send Current Channel Messages let sendingMessage = false; async function sendCurrentTextMessage() { if (sendingMessage) return; if (ui.activeGuild === null) return; if (ui.activeChannel === null) return; let text = q.$('#text-input').innerText.trim(); // trimming is not done server-side, just a client-side 'feature' if (text == '') return; sendingMessage = true; let guild = ui.activeGuild as CombinedGuild; let channel = ui.activeChannel as Channel; if (!guild.isSocketVerified()) { LOG.warn('client attempted to send message while not verified'); q.$('#send-error').innerText = 'Not Connected to Server'; await ElementsUtil.shakeElement(q.$('#send-error'), 400); sendingMessage = false; return; } if (text.length > Globals.MAX_TEXT_MESSAGE_LENGTH) { LOG.warn('skipping sending oversized message: ' + text.length + ' > ' + Globals.MAX_TEXT_MESSAGE_LENGTH + ' characters'); q.$('#send-error').innerText = 'Message too long: ' + text.length + ' > ' + Globals.MAX_TEXT_MESSAGE_LENGTH + ' characters'; await ElementsUtil.shakeElement(q.$('#send-error'), 400); sendingMessage = false; return; } await ui.lockMessages(guild, channel, async () => { q.$('#text-input').removeAttribute('contenteditable'); q.$('#text-input').classList.add('sending'); try { await guild.requestSendMessage(channel.id, text); q.$('#send-error').innerText = ''; q.$('#text-input').innerText = ''; } catch (e) { LOG.error('Error sending message', e); q.$('#send-error').innerText = 'Error sending message'; await ElementsUtil.shakeElement(q.$('#send-error'), 400); } q.$('#text-input').classList.remove('sending'); q.$('#text-input').setAttribute('contenteditable', 'plaintext-only'); q.$('#text-input').focus(); }); sendingMessage = false; }; q.$('#text-input').addEventListener('keydown', async (e) => { if (!sendingMessage) { q.$('#send-error').innerText = ''; // clear out the sending error if the message changes } if (e.key == 'Enter' && !e.shiftKey) { e.preventDefault(); await sendCurrentTextMessage(); } }); q.$('#text-input').addEventListener('keyup', (e) => { if (e.key == 'Backspace') { if (q.$('#text-input').innerText == '\n') { // sometimes, a \n gets left behind q.$('#text-input').innerText = ''; } } }); q.$('#send-error').addEventListener('click', () => { q.$('#send-error').innerText = ''; }); // Open resource select dialog when resource-input-button is clicked let selectingResources = false; q.$('#resource-input-button').addEventListener('click', async () => { if (ui.activeGuild === null) return; if (ui.activeChannel === null) return; if (selectingResources) { return; } selectingResources = true; let result = await electronRemote.dialog.showOpenDialog({ title: 'Select Resource', defaultPath: 'D:\\development\\cordis\\client-server\\server\\data', // TODO: not hardcoded properties: [ 'openFile' ] }); // TODO: multiple files do consecutive overlays? if (!result.canceled) { let element = createUploadOverlayFromPath(document, ui.activeGuild, ui.activeChannel, result.filePaths[0]); document.body.appendChild(element); q.$$$(element, '.text-input').focus(); } selectingResources = false; }); // Open upload resource dialog when an image is pasted window.addEventListener('paste', (e) => { if (ui.activeGuild === null) return; if (ui.activeChannel === null) return; let fileTransferItem: DataTransferItem | null = null; for (let item of (e as ClipboardEvent).clipboardData?.items ?? []) { if (item.kind == 'file') { e.preventDefault(); // don't continue the paste fileTransferItem = item; break; } } if (fileTransferItem) { let element = createUploadOverlayFromDataTransferItem(document, ui.activeGuild, ui.activeChannel, fileTransferItem); document.body.appendChild(element); q.$$$(element, '.text-input').focus(); } }); // TODO: drag+drop new server files? document.addEventListener('dragenter', () => { if (ui.activeGuild === null) return; if (ui.activeChannel === null) return; if (q.$('.overlay .drop-target')) return; let element = createUploadDropTarget(document, q, ui.activeGuild, ui.activeChannel); if (!element) return; document.body.appendChild(element); }); }