diff --git a/src/mami.css/input.css b/src/mami.css/input.css index f68d0bb..a16d8da 100644 --- a/src/mami.css/input.css +++ b/src/mami.css/input.css @@ -5,12 +5,12 @@ .input__main { display: flex; - height: 40px; - max-height: 140px; } .input__text { flex-grow: 1; + height: 40px; + max-height: 140px; resize: none; } @@ -32,37 +32,15 @@ cursor: pointer } -.input__button:before { - font-family: "Font Awesome 5 Free"; - font-weight: 900 -} - -.input__button--markup:before { - content: "\f121" -} - -.input__button--emotes:before { - content: "\f118" -} - -.input__button--upload:before { - content: "\f574" -} - -.input__button--send:before { - content: "\f1d8" -} - .input__menus { - max-height: 100px; - overflow: auto } .input__menu { + display: flex; + flex-wrap: wrap; + gap: 2px; + padding: 2px; +} +.input__menu:empty { display: none; - padding: 1px -} - -.input__menu--active { - display: block } diff --git a/src/mami.css/main.css b/src/mami.css/main.css index 7a9ee02..b211d3e 100644 --- a/src/mami.css/main.css +++ b/src/mami.css/main.css @@ -37,6 +37,7 @@ a:hover { .hidden { display: none !important; + visibility: none !important; } .sjis { diff --git a/src/mami.css/markup.css b/src/mami.css/markup.css index 6a3596f..0301564 100644 --- a/src/mami.css/markup.css +++ b/src/mami.css/markup.css @@ -1,21 +1,22 @@ .markup__button { border: 0; background: transparent; - font-family: Verdana, Tahoma, Geneva, Arial, Helvetica, sans-serif; + font-family: inherit; cursor: pointer; padding: 4px 8px; - margin: 2px; - transition: background .1s + transition: background .1s; + min-width: 26px; + text-align: center; } .markup__link { color: #1e90ff; - text-decoration: none + text-decoration: none; } .markup__link:hover, .markup__link:focus { - text-decoration: underline + text-decoration: underline; } .chat:not(.mami-do-not-mark-links-as-visited) .markup__link--visited, diff --git a/src/mami.js/chatform/form.jsx b/src/mami.js/chatform/form.jsx new file mode 100644 index 0000000..7660ece --- /dev/null +++ b/src/mami.js/chatform/form.jsx @@ -0,0 +1,30 @@ +#include chatform/input.jsx +#include chatform/markup.jsx + +const MamiChatForm = function(eventTarget) { + const input = new MamiChatFormInput(eventTarget); + const markup = new MamiChatFormMarkup; + + const html =
; + + return { + get element() { return html; }, + get markup() { return markup; }, + get input() { return input; }, + + focus: () => { + input.focus(); + }, + }; +}; diff --git a/src/mami.js/chatform/input.jsx b/src/mami.js/chatform/input.jsx new file mode 100644 index 0000000..f2fdf86 --- /dev/null +++ b/src/mami.js/chatform/input.jsx @@ -0,0 +1,174 @@ +#include emotes.js +#include users.js + +const MamiChatFormInput = function(eventTarget) { + const textElem = ; + let submitButton; + + const html ={0}', - button: true, - }, - { - tag: 'code', - replace: '{0}', - button: true, - }, - { - tag: 'sjis', - replace: '{0}', - }, - { - tag: 'color', - hasArg: true, - stripArg: ';:{}<>&|\\/~\'"', - replace: '{1}', - isToggle: true, - button: true, - }, - { - tag: 'img', - stripText: '"\'', - replace: '{0} [Embed]', - button: true, - }, - { - tag: 'url', - stripText: '"\'', - replace: '{0}', - }, - { - tag: 'url', - hasArg: true, - stripArg: '"\'', - replace: '{1}', - button: true, - }, - { - tag: 'video', - stripText: '"\'', - replace: '{0} [Embed]', - button: true, - }, - { - tag: 'audio', - stripText: '"\'', - replace: '{0} [Embed]', - button: true, - }, - { - tag: 'spoiler', - stripText: '"\'', - replace: '*** HIDDEN *** [Reveal]', - button: true, - } - ]; +const UmiBBCodes = [ + { + tag: 'b', + text: 'B', + style: 'font-weight: 700', + replace: '{0}', + }, + { + tag: 'i', + text: 'I', + style: 'font-style: italic', + replace: '{0}', + }, + { + tag: 'u', + text: 'U', + style: 'text-decoration: underline', + replace: '{0}', + }, + { + tag: 's', + text: 'S', + style: 'text-decoration: line-through', + replace: '
{0}', + }, + { + tag: 'code', + text: 'Code', + replace: '{0}', + }, + { + tag: 'sjis', + replace: '{0}', + }, + { + tag: 'color', + text: 'Colour', + hasArg: true, + stripArg: ';:{}<>&|\\/~\'"', + replace: '{1}', + }, + { + tag: 'img', + text: 'Image', + stripText: '"\'', + replace: '{0} [Embed]', + }, + { + tag: 'url', + stripText: '"\'', + replace: '{0}', + }, + { + tag: 'url', + text: 'URL', + hasArg: true, + stripArg: '"\'', + replace: '{1}', + }, + { + tag: 'video', + text: 'Video', + stripText: '"\'', + replace: '{0} [Embed]', + }, + { + tag: 'audio', + text: 'Audio', + stripText: '"\'', + replace: '{0} [Embed]', + }, + { + tag: 'spoiler', + text: 'Spoiler', + stripText: '"\'', + replace: '*** HIDDEN *** [Reveal]', + }, +]; +Umi.Parsing = (function() { const replaceAll = function(haystack, needle, replace, ignore) { return haystack.replace( new RegExp( @@ -362,21 +364,9 @@ Umi.Parsing = (function() { Umi.Parser.SockChatBBcode.ToggleSpoiler = toggleSpoiler; return { - Init: function() { - for (let i = 0; i < bbCodes.length; i++) { - const bbCode = bbCodes[i]; - if(!bbCode.button) - continue; - - const start = '[{0}]'.replace('{0}', bbCode.tag + (bbCode.arg ? '=' : '')), end = '[/{0}]'.replace('{0}', bbCode.tag); - const text = (bbCode.tag.length > 1 ? bbCode.tag.substring(0, 1).toUpperCase() + bbCode.tag.substring(1) : bbCode.tag).replace('Color', 'Colour'); - - Umi.UI.Markup.Add(bbCode.tag, text, start, end); - } - }, Parse: function(element, message) { - for(let i = 0; i < bbCodes.length; i++) { - const bbCode = bbCodes[i]; + for(let i = 0; i < UmiBBCodes.length; i++) { + const bbCode = UmiBBCodes[i]; if(!bbCode.hasArg) { let at = 0; diff --git a/src/mami.js/sidebar/pan-settings.jsx b/src/mami.js/sidebar/pan-settings.jsx index 4b7692c..7a67e67 100644 --- a/src/mami.js/sidebar/pan-settings.jsx +++ b/src/mami.js/sidebar/pan-settings.jsx @@ -113,6 +113,8 @@ const MamiSidebarPanelSettings = function(settings, msgBox) { options: undefined, confirm: undefined, disabled: info.immutable, + trueValue: true, + falseValue: false, }; const detectType = () => { @@ -151,6 +153,20 @@ const MamiSidebarPanelSettings = function(settings, msgBox) { setting.options = value; return pub; }, + on: value => { + if(typeof value === undefined) + value = true; + + setting.trueValue = value; + return pub; + }, + off: value => { + if(typeof value === undefined) + value = false; + + setting.falseValue = value; + return pub; + }, confirm: value => { if(!Array.isArray(value) && typeof value !== 'string' && value !== undefined) throw 'value must be an array or a string'; @@ -200,7 +216,15 @@ const MamiSidebarPanelSettings = function(settings, msgBox) { label.append(title, input); if(setting.type === 'checkbox') { - settings.watch(info.name, ev => input.checked = ev.detail.value); + settings.watch(info.name, ev => input.checked = ev.detail.value !== setting.falseValue); + + const toggle = () => { + settings.set( + info.name, + settings.get(info.name) !== setting.falseValue ? setting.falseValue : setting.trueValue + ); + }; + input.addEventListener('change', () => { if(setting.confirm !== undefined && input.checked !== info.fallback) { msgBox.show({ @@ -208,12 +232,12 @@ const MamiSidebarPanelSettings = function(settings, msgBox) { yes: { primary: false }, no: { primary: true }, }).then(() => { - settings.toggle(info.name); + toggle(); }).catch(() => { input.checked = info.fallback; }); } else { - settings.toggle(info.name); + toggle(); } }); } else { diff --git a/src/mami.js/sockchat/client.js b/src/mami.js/sockchat/client.js index 6bfb3b9..d4bbcf0 100644 --- a/src/mami.js/sockchat/client.js +++ b/src/mami.js/sockchat/client.js @@ -1,6 +1,5 @@ #include compat.js #include mszauth.js -#include ui/hooks.js const MamiSockChat = function(protoWorker) { const events = protoWorker.eventTarget('sockchat'); @@ -23,8 +22,6 @@ const MamiSockChat = function(protoWorker) { client = await protoWorker.root.create('sockchat', { ping: futami.get('ping') }); await client.setDumpPackets(dumpPackets); - Umi.UI.Hooks.SetCallbacks(client.sendMessage); - MamiCompat('Umi.Server', { get: () => client, configurable: true }); MamiCompat('Umi.Server.SendMessage', { value: text => client.sendMessage(text), configurable: true }); MamiCompat('Umi.Protocol.SockChat.Protocol.Instance.SendMessage', { value: text => client.sendMessage(text), configurable: true }); diff --git a/src/mami.js/sockchat/handlers.js b/src/mami.js/sockchat/handlers.js index d1484d2..6cfb060 100644 --- a/src/mami.js/sockchat/handlers.js +++ b/src/mami.js/sockchat/handlers.js @@ -5,7 +5,6 @@ #include notices/baka.jsx #include sockchat/modal.js #include ui/emotes.js -#include ui/markup.js #include ui/messages.jsx const MamiSockChatHandlers = function( @@ -103,9 +102,6 @@ const MamiSockChatHandlers = function( sbUsers.createEntry(ev.detail.user); - Umi.UI.Markup.Reset(); - Umi.Parsing.Init(); - if(ctx.views.count > 1) ctx.views.pop(); }; diff --git a/src/mami.js/ui/chat-input-main.js b/src/mami.js/ui/chat-input-main.js deleted file mode 100644 index 4dd0f98..0000000 --- a/src/mami.js/ui/chat-input-main.js +++ /dev/null @@ -1,34 +0,0 @@ -#include utility.js - -Umi.UI.ChatInputMain = function() { - const html = $e({ - attrs: { - id: 'umi-msg-container', - className: 'input__main', - }, - child: [ - { - tag: 'textarea', - attrs: { - id: 'umi-msg-text', - name: 'text', - className: 'input__text', - autofocus: true, - }, - }, - { - tag: 'button', - attrs: { - id: 'umi-msg-send', - className: 'input__button input__button--send', - }, - }, - ], - }); - - return { - getElement: function() { - return html; - }, - }; -}; diff --git a/src/mami.js/ui/chat-input-menus.js b/src/mami.js/ui/chat-input-menus.js deleted file mode 100644 index 27f8190..0000000 --- a/src/mami.js/ui/chat-input-menus.js +++ /dev/null @@ -1,16 +0,0 @@ -#include utility.js - -Umi.UI.ChatInputMenus = function() { - const html = $e({ - attrs: { - id: 'umi-msg-menu', - className: 'input__menus', - }, - }); - - return { - getElement: function() { - return html; - }, - }; -}; diff --git a/src/mami.js/ui/chat-input.js b/src/mami.js/ui/chat-input.js deleted file mode 100644 index 60b244a..0000000 --- a/src/mami.js/ui/chat-input.js +++ /dev/null @@ -1,32 +0,0 @@ -#include utility.js -#include ui/chat-input-main.js -#include ui/chat-input-menus.js - -Umi.UI.ChatInput = function() { - const menus = new Umi.UI.ChatInputMenus; - const main = new Umi.UI.ChatInputMain; - - const html = $e({ - tag: 'form', - attrs: { - id: 'umi-msg-form', - className: 'input', - }, - child: [ - menus, - main, - ], - }); - - return { - getMenus: function() { - return menus; - }, - getMain: function() { - return main; - }, - getElement: function() { - return html; - }, - }; -}; diff --git a/src/mami.js/ui/chat-interface.js b/src/mami.js/ui/chat-interface.js index a530938..a4606be 100644 --- a/src/mami.js/ui/chat-interface.js +++ b/src/mami.js/ui/chat-interface.js @@ -1,10 +1,8 @@ #include utility.js #include ui/chat-message-list.js -#include ui/chat-input.js -Umi.UI.ChatInterface = function() { +Umi.UI.ChatInterface = function(chatForm) { const messages = new Umi.UI.ChatMessageList; - const input = new Umi.UI.ChatInput; const html = $e({ attrs: { @@ -12,7 +10,7 @@ Umi.UI.ChatInterface = function() { }, child: [ messages, - input, + chatForm, ], }); @@ -20,9 +18,6 @@ Umi.UI.ChatInterface = function() { getMessageList: function() { return messages; }, - getInput: function() { - return input; - }, getElement: function() { return html; }, diff --git a/src/mami.js/ui/chat-layout.js b/src/mami.js/ui/chat-layout.js index 04ef9b6..c4dc51c 100644 --- a/src/mami.js/ui/chat-layout.js +++ b/src/mami.js/ui/chat-layout.js @@ -1,10 +1,9 @@ #include utility.js #include ui/chat-interface.js -#include sidebar/sidebar.jsx // this needs revising at some point but will suffice for now -Umi.UI.ChatLayout = function(sideBar) { - const main = new Umi.UI.ChatInterface; +Umi.UI.ChatLayout = function(chatForm, sideBar) { + const main = new Umi.UI.ChatInterface(chatForm); const html = $e({ attrs: { @@ -18,9 +17,6 @@ Umi.UI.ChatLayout = function(sideBar) { }); return { - getSideBar: function() { - return sideBar; - }, getInterface: function() { return main; }, diff --git a/src/mami.js/ui/hooks.js b/src/mami.js/ui/hooks.js deleted file mode 100644 index 7d9b510..0000000 --- a/src/mami.js/ui/hooks.js +++ /dev/null @@ -1,110 +0,0 @@ -#include users.js -#include utility.js -#include ui/messages.jsx -#include ui/view.js - -Umi.UI.Hooks = (function() { - let sendMessage; - - return { - SetCallbacks: (sendMessageFunc) => { - sendMessage = sendMessageFunc; - }, - AddHooks: function() { - const msgForm = $i('umi-msg-form'); - const msgText = $i('umi-msg-text'); - - window.addEventListener('keydown', function(ev) { - if((ev.ctrlKey && ev.key !== 'v') || ev.altKey) - return; - - if(!ev.target.matches('input, textarea, select, button')) - msgText.focus(); - }); - - msgForm.addEventListener('submit', ev => { - ev.preventDefault(); - - if(typeof sendMessage !== 'function') - return; - - const textField = ev.target.elements.namedItem('text'); - if(textField instanceof HTMLTextAreaElement) { - let text = textField.value; - textField.value = ''; - - text = text.replace(/\t/g, ' '); - if(text.length > 0) - sendMessage(text); - } - }); - - msgText.addEventListener('keyup', function(ev) { - const isScrolledToBottom = Umi.UI.Messages.IsScrolledToBottom(); - - const elemParent = msgText.parentNode; - let height = 40; - - if(mami.settings.get('expandTextBox') && msgText.scrollHeight > msgText.clientHeight) - height = msgText.scrollHeight; - - if(height > 40) - elemParent.style.height = height.toString() + 'px'; - else - elemParent.style.height = null; - - if(isScrolledToBottom) - Umi.UI.Messages.ScrollIfNeeded(); - }); - - msgText.addEventListener('keydown', function(ev) { - if(ev.key === 'Tab' && (!ev.shiftKey || !ev.ctrlKey)) { - ev.preventDefault(); - - const text = Umi.UI.View.GetText(); - if(text.length < 1) - return; - - const start = Umi.UI.View.GetPosition(); - let position = start, - snippet = ''; - while(position >= 0 && text.charAt(position - 1) !== ' ' && text.charAt(position - 1) !== "\n") { - --position; - snippet = text.charAt(position) + snippet; - } - - let insertText = undefined; - - if(snippet.indexOf(':') === 0) { - let emoteRank = 0; - if(Umi.User.hasCurrentUser()) - emoteRank = Umi.User.getCurrentUser().perms.rank; - const emotes = MamiEmotes.findByName(emoteRank, snippet.substring(1), true); - if(emotes.length > 0) - insertText = ':' + emotes[0] + ':'; - } else { - const users = Umi.Users.Find(snippet); - if(users.length === 1) - insertText = users[0].name; - } - - if(insertText !== undefined) { - Umi.UI.View.SetText(text.slice(0, start - snippet.length) + text.slice(start)); - Umi.UI.View.SetPosition(start - snippet.length); - Umi.UI.View.EnterAtCursor(insertText); - Umi.UI.View.SetPosition(Umi.UI.View.GetPosition() + insertText.length); - Umi.UI.View.SetPosition(Umi.UI.View.GetPosition(), true); - } - - return; - } - - if((ev.key === 'Enter' || ev.key === 'NumpadEnter') && ev.shiftKey === mami.settings.get('newLineOnEnter')) { - ev.preventDefault(); - msgForm.requestSubmit(); - return; - } - }); - }, - }; -})(); diff --git a/src/mami.js/ui/input-menus.js b/src/mami.js/ui/input-menus.js deleted file mode 100644 index ff4f826..0000000 --- a/src/mami.js/ui/input-menus.js +++ /dev/null @@ -1,68 +0,0 @@ -#include utility.js -#include ui/input-menus.js - -Umi.UI.InputMenus = (function() { - const ids = []; - - const createButtonId = id => `umi-msg-menu-btn-${id}`; - const createButton = function(id, title, onClick) { - return $e({ - tag: 'button', - attrs: { - type: 'button', - id: createButtonId(id), - classList: ['input__button', 'input__button--' + id], - title: title, - onclick: onClick, - }, - }); - }; - - return { - Add: function(baseId, title, beforeButtonId) { - if(baseId !== 'markup') - throw 'only baseId "markup" may be added'; - - if(ids.includes(baseId)) - return; - ids.push(baseId); - - let beforeButton; - if(typeof beforeButtonId === 'string') - beforeButton = $i(createButtonId(beforeButtonId)) - if(!(beforeButton instanceof Element)) - beforeButton = $i('umi-msg-send'); - - if(typeof title === 'string') - $i('umi-msg-container').insertBefore(createButton(baseId, title), beforeButton); - $i('umi-msg-menu').appendChild( - $e({ - attrs: { - 'class': ['input__menu', 'input__menu--' + baseId, 'input__menu--active'], - id: 'umi-msg-menu-sub-' + baseId, - tabindex: '0', - } - }) - ); - }, - AddButton: function(baseId, title, onClick, beforeButtonId) { - if(ids.includes(baseId)) - return; - ids.push(baseId); - - let beforeButton; - if(typeof beforeButtonId === 'string') - beforeButton = $i(createButtonId(beforeButtonId)) - if(!(beforeButton instanceof Element)) - beforeButton = $i('umi-msg-send'); - - $i('umi-msg-container').insertBefore(createButton(baseId, title, onClick), beforeButton); - }, - Get: function(baseId, button) { - const id = 'umi-msg-menu-' + (button ? 'btn' : 'sub') + '-' + baseId; - if(ids.indexOf(baseId) >= 0) - return $i(id); - return null; - }, - }; -})(); diff --git a/src/mami.js/ui/markup.js b/src/mami.js/ui/markup.js deleted file mode 100644 index e2ec9b5..0000000 --- a/src/mami.js/ui/markup.js +++ /dev/null @@ -1,71 +0,0 @@ -#include colour.js -#include common.js -#include utility.js -#include colpick/picker.jsx -#include ui/input-menus.js -#include ui/markup.js -#include ui/view.js - -Umi.UI.Markup = (function() { - const insertRaw = function(start, end) { - const selectionLength = Umi.UI.View.GetSelectionLength(); - Umi.UI.View.EnterAtCursor(start); - Umi.UI.View.SetPosition(Umi.UI.View.GetPosition() + selectionLength + start.length); - Umi.UI.View.EnterAtCursor(end); - Umi.UI.View.SetPosition(Umi.UI.View.GetPosition() - selectionLength); - Umi.UI.View.SetPosition(Umi.UI.View.GetPosition() + selectionLength, true); - Umi.UI.View.Focus(); - }; - - let pickerTarget = document.body; - let picker, pickerVisible = false; - - const insert = function(ev) { - if(this.dataset.umiTagName === 'color') { - if(picker === undefined) { - picker = new MamiColourPicker({ presets: futami.get('colours') }); - pickerTarget.appendChild(picker.element); - } - - if(pickerVisible) { - picker.close(); - } else { - pickerVisible = true; - picker.dialog(ev) - .then(colour => insertRaw(`[color=${MamiColour.hex(colour)}]`, '[/color]')) - .catch(() => {}) // noop so the console stops screaming - .finally(() => pickerVisible = false); - } - } else - insertRaw( - this.dataset.umiBeforeCursor, - this.dataset.umiAfterCursor - ); - }; - - return { - SetPickerTarget: target => { pickerTarget = target; }, - Add: function(name, text, beforeCursor, afterCursor) { - Umi.UI.InputMenus.Get('markup').appendChild($e({ - tag: 'button', - attrs: { - type: 'button', - id: 'umi-msg-menu-markup-btn-' + name, - classList: ['markup__button', 'markup__button--' + name], - dataset: { - umiTagName: name, - umiBeforeCursor: beforeCursor, - umiAfterCursor: afterCursor, - }, - onclick: insert, - }, - child: text, - })); - }, - Reset: function() { - Umi.UI.InputMenus.Get('markup').innerHTML = ''; - }, - Insert: insert, - InsertRaw: insertRaw, - }; -})(); diff --git a/src/mami.js/ui/messages.jsx b/src/mami.js/ui/messages.jsx index dc94c80..af97f73 100644 --- a/src/mami.js/ui/messages.jsx +++ b/src/mami.js/ui/messages.jsx @@ -375,9 +375,19 @@ Umi.UI.Messages = (function() { const msgsList = $i('umi-messages'); return msgsList.scrollTop === (msgsList.scrollHeight - msgsList.offsetHeight); }, - ScrollIfNeeded: () => { + ScrollIfNeeded: (offsetOrForce = 0) => { + const msgsList = $i('umi-messages'); + if(!(msgsList instanceof Element)) + return; + + if(typeof offsetOrForce === 'boolean' && offsetOrForce !== true) + return; + + if(typeof offsetOrForce === 'number' && msgsList.scrollTop < (msgsList.scrollHeight - msgsList.offsetHeight - offsetOrForce)) + return; + if(mami.settings.get('autoScroll')) - $i('umi-messages').lastElementChild?.scrollIntoView({ inline: 'end' }); + msgsList.lastElementChild?.scrollIntoView({ inline: 'end' }); }, SwitchChannel: channel => { if(typeof channel === 'object' && channel !== null && 'name' in channel) @@ -385,15 +395,13 @@ Umi.UI.Messages = (function() { if(typeof channel !== 'string') return; - const isScrolledToBottom = Umi.UI.Messages.IsScrolledToBottom(); focusChannelName = channel; const root = $i('umi-messages'); for(const elem of root.children) elem.classList.toggle('hidden', elem.dataset.channel !== undefined && elem.dataset.channel !== focusChannelName); - if(isScrolledToBottom) - Umi.UI.Messages.ScrollIfNeeded(); + Umi.UI.Messages.ScrollIfNeeded(); }, Clear: retain => { if(typeof retain === 'string' && !isNaN(retain)) diff --git a/src/mami.js/ui/view.js b/src/mami.js/ui/view.js deleted file mode 100644 index 9dfd40b..0000000 --- a/src/mami.js/ui/view.js +++ /dev/null @@ -1,45 +0,0 @@ -#include utility.js - -Umi.UI.View = (function() { - const getPosition = function(end) { - return $i('umi-msg-text')[end ? 'selectionEnd' : 'selectionStart']; - }; - const setPosition = function(pos, end) { - $i('umi-msg-text')[end ? 'selectionEnd' : 'selectionStart'] = pos; - }; - - const getText = function() { - return $i('umi-msg-text').value; - }; - const setText = function(text) { - $i('umi-msg-text').value = text; - }; - - return { - Focus: function() { - $i('umi-msg-text').focus(); - }, - SetPosition: setPosition, - GetPosition: getPosition, - GetSelectionLength: function() { - let length = getPosition(true) - getPosition(); - if(length < 0) - length = getPosition() - getPosition(true); - return length; - }, - EnterAtCursor: function(text, overwrite) { - const value = getText(); - const current = getPosition(); - let out = ''; - - out += value.slice(0, current); - out += text; - out += value.slice(current + (overwrite ? text.length : 0)); - - setText(out); - setPosition(current); - }, - GetText: getText, - SetText: setText, - }; -})(); diff --git a/src/proto.js/sockchat/proto.js b/src/proto.js/sockchat/proto.js index f7795ee..9469733 100644 --- a/src/proto.js/sockchat/proto.js +++ b/src/proto.js/sockchat/proto.js @@ -166,6 +166,10 @@ const SockChatProtocol = function(dispatch, options) { if(!ctx.isAuthed) throw 'must be authenticated'; + text = text.replace(/\t/g, ' '); + if(text.length < 1) + return; + // there's actually a pretty big bug here lol // any unsupported command is gonna fall through to the actual channel you're in if(!text.startsWith('/') && ctx.pseudoChannelName !== undefined)