147 lines
5.1 KiB
TypeScript
147 lines
5.1 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 ElementsUtil from './require/elements-util.js';
|
|
import Globals from '../globals';
|
|
|
|
import { Channel } from '../data-types';
|
|
import ClientController from '../client-controller';
|
|
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';
|
|
|
|
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.activeServer === 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 server = ui.activeServer as ClientController;
|
|
let channel = ui.activeChannel as Channel;
|
|
|
|
if (!server.isVerified) {
|
|
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(server, channel, async () => {
|
|
q.$('#text-input').removeAttribute('contenteditable');
|
|
q.$('#text-input').classList.add('sending');
|
|
try {
|
|
await server.sendMessage(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.activeServer === 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.activeServer, 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.activeServer === 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.activeServer, ui.activeChannel, fileTransferItem);
|
|
document.body.appendChild(element);
|
|
q.$$$(element, '.text-input').focus();
|
|
}
|
|
});
|
|
|
|
// TODO: drag+drop new server files?
|
|
document.addEventListener('dragenter', () => {
|
|
if (ui.activeServer === null) return;
|
|
if (ui.activeChannel === null) return;
|
|
|
|
if (q.$('.overlay .drop-target')) return;
|
|
let element = createUploadDropTarget(document, q, ui.activeServer, ui.activeChannel);
|
|
if (!element) return;
|
|
document.body.appendChild(element);
|
|
});
|
|
}
|