154 lines
6.4 KiB
TypeScript
154 lines
6.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 { Channel } from '../data-types';
|
|
import ClientController from '../client-controller.js';
|
|
import Globals from '../globals.js';
|
|
|
|
import BaseElements from './require/base-elements.js';
|
|
import ElementsUtil from './require/elements-util.js';
|
|
import Q from '../q-module';
|
|
|
|
export default function createModifyChannelOverlay(document: Document, q: Q, server: ClientController, channel: Channel): HTMLElement {
|
|
// See also overlay-create-channel
|
|
|
|
let element = BaseElements.createOverlay(document, { class: 'content submit-dialog modify-channel', content: [
|
|
{ class: 'preview channel-title', content: [
|
|
{ class: 'channel-icon', content: BaseElements.TEXT_CHANNEL_ICON },
|
|
{ class: 'channel-name', content: channel.name },
|
|
{ class: 'channel-flavor-divider' },
|
|
{ class: 'channel-flavor-text', content: channel.flavorText || '' }
|
|
] },
|
|
{ class: 'text-input channel-name', placeholder: 'channel-name', content: channel.name, contenteditable: 'plaintext-only' },
|
|
{ class: 'text-input channel-flavor-text', placeholder: 'Flavor Text (optional)', content: channel.flavorText || '', contenteditable: 'plaintext-only' },
|
|
{ class: 'lower', content: [
|
|
{ class: 'error' },
|
|
{ class: 'buttons', content: [
|
|
{ class: 'button submit', content: 'Save Changes' }
|
|
] }
|
|
] }
|
|
] });
|
|
|
|
let newName = channel.name;
|
|
let newFlavorText = channel.flavorText;
|
|
function updatePreview() {
|
|
newName = q.$$$(element, '.text-input.channel-name').innerText;
|
|
newFlavorText = q.$$$(element, '.text-input.channel-flavor-text').innerText;
|
|
q.$$$(element, '.channel-title .channel-name').innerText = newName;
|
|
q.$$$(element, '.channel-title .channel-flavor-text').innerText = newFlavorText;
|
|
|
|
if (newFlavorText != '') {
|
|
q.$$$(element, '.channel-title .channel-flavor-divider').style.visibility = 'visible';
|
|
} else {
|
|
q.$$$(element, '.channel-title .channel-flavor-divider').style.visibility = 'hidden';
|
|
}
|
|
}
|
|
updatePreview();
|
|
|
|
let submitting = false;
|
|
async function submit() {
|
|
if (submitting) return;
|
|
submitting = true;
|
|
|
|
q.$$$(element, '.error').innerText = '';
|
|
q.$$$(element, '.button.submit').innerText = 'Submitting...';
|
|
q.$$$(element, '.text-input.channel-name').removeAttribute('contenteditable');
|
|
q.$$$(element, '.text-input.channel-flavor-text').removeAttribute('contenteditable');
|
|
|
|
let success = false;
|
|
if (newName == channel.name && (newFlavorText || '') == (channel.flavorText || '')) {
|
|
success = true; // nothing changed
|
|
} else if (newName.length == 0) {
|
|
LOG.warn('attempted to set empty channel name');
|
|
q.$$$(element, '.error').innerText = 'Channel name cannot be empty';
|
|
q.$$$(element, '.button.submit').innerText = 'Try Again';
|
|
await ElementsUtil.shakeElement(q.$$$(element, '.button.submit'), 400);
|
|
} else if (newName.length > Globals.MAX_CHANNEL_NAME_LENGTH) {
|
|
LOG.warn('attempted to set too long channel name');
|
|
q.$$$(element, '.error').innerText = 'Channel name is too long. ' + newName.length + ' > ' + Globals.MAX_CHANNEL_NAME_LENGTH;
|
|
q.$$$(element, '.button.submit').innerText = 'Try Again';
|
|
await ElementsUtil.shakeElement(q.$$$(element, '.button.submit'), 400);
|
|
} else if (!(/^[A-Za-z0-9-]+$/.exec(newName))) {
|
|
LOG.warn('attempted to set channel name with illegal characters');
|
|
q.$$$(element, '.error').innerText = 'Please use only [A-Za-z0-9-]+ in channel name';
|
|
q.$$$(element, '.button.submit').innerText = 'Try Again';
|
|
await ElementsUtil.shakeElement(q.$$$(element, '.button.submit'), 400);
|
|
} else if (newFlavorText != null && newFlavorText.length > Globals.MAX_CHANNEL_FLAVOR_TEXT_LENGTH) {
|
|
LOG.warn('attempted to set too long flavor text');
|
|
q.$$$(element, '.error').innerText = 'Flavor text is too long. ' + newName.length + ' > ' + Globals.MAX_CHANNEL_NAME_LENGTH;
|
|
q.$$$(element, '.button.submit').innerText = 'Try Again';
|
|
await ElementsUtil.shakeElement(q.$$$(element, '.button.submit'), 400);
|
|
} else {
|
|
if (newFlavorText != null && newFlavorText.length == 0) {
|
|
newFlavorText = null;
|
|
}
|
|
try {
|
|
await server.updateChannel(channel.id, newName, newFlavorText);
|
|
success = true;
|
|
} catch (e) {
|
|
LOG.error('error updating channel', e);
|
|
q.$$$(element, '.error').innerText = 'Error updating channel';
|
|
q.$$$(element, '.button.submit').innerText = 'Try Again';
|
|
await ElementsUtil.shakeElement(q.$$$(element, '.button.submit'), 400);
|
|
}
|
|
}
|
|
|
|
if (success) {
|
|
element.removeSelf();
|
|
}
|
|
|
|
q.$$$(element, '.text-input.channel-name').setAttribute('contenteditable', 'plaintext-only');
|
|
q.$$$(element, '.text-input.channel-flavor-text').setAttribute('contenteditable', 'plaintext-only');
|
|
|
|
submitting = false;
|
|
}
|
|
|
|
let textInputs = q.$$$$(element, '.text-input');
|
|
for (let textInput of textInputs) {
|
|
textInput.addEventListener('input', () => {
|
|
updatePreview();
|
|
});
|
|
}
|
|
|
|
q.$$$(element, '.text-input.channel-name').addEventListener('keydown', async (e) => {
|
|
if (e.key == 'Backspace' || e.key == 'Escape' || e.key == 'F4') {
|
|
// these keys are good
|
|
} else if (e.key == 'Tab') {
|
|
// have to hard-code this one because otherwise, it just picks the beginning of the next input
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
q.$$$(element, '.text-input.channel-flavor-text').focus();
|
|
ElementsUtil.setCursorToEnd(q.$$$(element, '.text-input.channel-flavor-text'));
|
|
} else if (e.key == 'Enter') {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
await submit();
|
|
} else if (!/^[A-Za-z0-9-]$/.exec(e.key)) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
});
|
|
|
|
q.$$$(element, '.text-input.channel-flavor-text').addEventListener('keydown', async (e) => {
|
|
if (e.key == 'Tab' && e.shiftKey) {
|
|
// have to hard-code this one because otherwise, it just picks the beginning of the next input
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
q.$$$(element, '.text-input.channel-name').focus();
|
|
ElementsUtil.setCursorToEnd(q.$$$(element, '.text-input.channel-name'));
|
|
} else if (e.key == 'Enter') {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
await submit();
|
|
}
|
|
});
|
|
|
|
q.$$$(element, '.button.submit').addEventListener('click', async () => {
|
|
await submit();
|
|
});
|
|
|
|
return element;
|
|
}
|