cordis/client/webapp/elements/events-text-input.ts

145 lines
5.7 KiB
TypeScript
Raw Normal View History

2021-10-30 17:26:41 +00:00
import * as electronRemote from '@electron/remote';
const electronConsole = electronRemote.getGlobal('console') as Console;
import Logger from '../../../logger/logger';
const LOG = new Logger(__filename, electronConsole);
import Elements from '../elements';
import ElementsUtil from './require/elements-util.js';
import Globals from '../globals';
import { $, $$, $$$, $$$$ } from './require/q-module';
import IState from './require/elements-state';
import { Channel } from '../data-types';
import ClientController from '../client-controller';
export default function bindTextInputEvents(state: IState): void {
const { document, ui } = state;
$.setDocument(document);
// Send Current Channel Messages
let sendingMessage = false;
async function sendCurrentTextMessage() {
if (sendingMessage) return;
if (!ui.hasActiveServer()) return;
if (!ui.hasActiveChannel()) return;
let text = $('#text-input').innerText.trim(); // trimming is not done server-side, just a client-side 'feature'
if (text == '') return;
sendingMessage = true;
let server = ui.activeServer as ClientController;
let channel = ui.activeChannel as Channel;
if (!server.isVerified) {
LOG.warn('client attempted to send message while not verified');
$('#send-error').innerText = 'Not Connected to Server';
await ElementsUtil.shakeElement($('#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');
$('#send-error').innerText = 'Message too long: ' + text.length + ' > ' + Globals.MAX_TEXT_MESSAGE_LENGTH + ' characters';
await ElementsUtil.shakeElement($('#send-error'), 400);
sendingMessage = false;
return;
}
await ui.lockMessages(server, channel, async () => {
$('#text-input').removeAttribute('contenteditable');
$('#text-input').classList.add('sending');
try {
await server.sendMessage(channel.id, text);
$('#send-error').innerText = '';
$('#text-input').innerText = '';
} catch (e) {
LOG.error('Error sending message', e);
$('#send-error').innerText = 'Error sending message';
await ElementsUtil.shakeElement($('#send-error'), 400);
}
$('#text-input').classList.remove('sending');
$('#text-input').setAttribute('contenteditable', 'plaintext-only');
$('#text-input').focus();
});
sendingMessage = false;
};
$('#text-input').addEventListener('keydown', async (e) => {
if (!sendingMessage) {
$('#send-error').innerText = ''; // clear out the sending error if the message changes
}
if (e.key == 'Enter' && !e.shiftKey) {
e.preventDefault();
await sendCurrentTextMessage();
}
});
$('#text-input').addEventListener('keyup', (e) => {
if (e.key == 'Backspace') {
if ($('#text-input').innerText == '\n') { // sometimes, a \n gets left behind
$('#text-input').innerText = '';
}
}
});
$('#send-error').addEventListener('click', () => {
$('#send-error').innerText = '';
});
// Open resource select dialog when resource-input-button is clicked
let selectingResources = false;
$('#resource-input-button').addEventListener('click', async () => {
if (!ui.hasActiveServer()) return;
if (!ui.hasActiveChannel()) 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 = Elements.createUploadOverlayFromPath(ui.activeServer as ClientController, ui.activeChannel as Channel, result.filePaths[0]);
document.body.appendChild(element);
$$$(element, '.text-input').focus();
}
selectingResources = false;
});
// Open upload resource dialog when an image is pasted
window.addEventListener('paste', (e) => {
if (!ui.hasActiveServer()) return;
if (!ui.hasActiveChannel()) 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 = Elements.createUploadOverlayFromDataTransferItem(ui.activeServer as ClientController, ui.activeChannel as Channel, fileTransferItem);
document.body.appendChild(element);
$$$(element, '.text-input').focus();
}
});
// TODO: drag+drop new server files?
document.addEventListener('dragenter', () => {
if ($('.overlay .drop-target')) return;
let element = Elements.createUploadDropTarget(ui.activeServer as ClientController, ui.activeChannel as Channel);
if (!element) return;
document.body.appendChild(element);
});
}