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