diff --git a/.eslintrc.yml b/.eslintrc.yml index 7633ddbf..2f9a28ec 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -3,7 +3,7 @@ root: true parserOptions: ecmaVersion: 2022 - parser: "babel-eslint" + parser: "@babel/eslint-parser", env: es6: true diff --git a/client/dist/components/MessageTypes/index.js b/client/dist/components/MessageTypes/index.js new file mode 100644 index 00000000..65e655e6 --- /dev/null +++ b/client/dist/components/MessageTypes/index.js @@ -0,0 +1,11 @@ +"use strict"; +// This creates a version of `require()` in the context of the current +// directory, so we iterate over its content, which is a map statically built by +// Webpack. +// Second argument says it's recursive, third makes sure we only load templates. +const requireViews = require.context(".", false, /\.vue$/); +export default requireViews.keys().reduce((acc, path) => { + acc["message-" + path.substring(2, path.length - 4)] = requireViews(path).default; + return acc; +}, {}); +//# sourceMappingURL=index.js.map diff --git a/client/dist/components/MessageTypes/index.js.map b/client/dist/components/MessageTypes/index.js.map new file mode 100644 index 00000000..68d4c677 --- /dev/null +++ b/client/dist/components/MessageTypes/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../components/MessageTypes/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,sEAAsE;AACtE,gFAAgF;AAChF,WAAW;AACX,gFAAgF;AAChF,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AAE3D,eAAe,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;IACvD,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;IAElF,OAAO,GAAG,CAAC;AACZ,CAAC,EAAE,EAAE,CAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/auth.js b/client/dist/js/auth.js new file mode 100644 index 00000000..8ff55573 --- /dev/null +++ b/client/dist/js/auth.js @@ -0,0 +1,10 @@ +"use strict"; +import storage from "./localStorage"; +import location from "./location"; +export default class Auth { + static signout() { + storage.clear(); + location.reload(); + } +} +//# sourceMappingURL=auth.js.map diff --git a/client/dist/js/auth.js.map b/client/dist/js/auth.js.map new file mode 100644 index 00000000..e1ce5853 --- /dev/null +++ b/client/dist/js/auth.js.map @@ -0,0 +1 @@ +{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../js/auth.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,OAAO,MAAM,gBAAgB,CAAC;AACrC,OAAO,QAAQ,MAAM,YAAY,CAAC;AAElC,MAAM,CAAC,OAAO,OAAO,IAAI;IACxB,MAAM,CAAC,OAAO;QACb,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,QAAQ,CAAC,MAAM,EAAE,CAAC;IACnB,CAAC;CACD"} \ No newline at end of file diff --git a/client/dist/js/autocompletion.js b/client/dist/js/autocompletion.js new file mode 100644 index 00000000..9d12a7ab --- /dev/null +++ b/client/dist/js/autocompletion.js @@ -0,0 +1,280 @@ +"use strict"; +const constants = require("./constants"); +import Mousetrap from "mousetrap"; +import {Textcomplete} from "@textcomplete/core/dist/Textcomplete"; +import {TextareaEditor} from "@textcomplete/textarea/dist/TextareaEditor"; +import fuzzy from "fuzzy"; +import emojiMap from "./helpers/simplemap.json"; +import store from "./store"; +export default enableAutocomplete; +const emojiSearchTerms = Object.keys(emojiMap); +const emojiStrategy = { + id: "emoji", + match: /(^|\s):([-+\w:?]{2,}):?$/, + search(term, callback) { + // Trim colon from the matched term, + // as we are unable to get a clean string from match regex + term = term.replace(/:$/, ""); + callback(fuzzyGrep(term, emojiSearchTerms)); + }, + template([string, original]) { + return `${emojiMap[original]} ${string}`; + }, + replace([, original]) { + return "$1" + emojiMap[original]; + }, + index: 2, +}; +const nicksStrategy = { + id: "nicks", + match: /(^|\s)(@([a-zA-Z_[\]\\^{}|`@][a-zA-Z0-9_[\]\\^{}|`-]*)?)$/, + search(term, callback) { + term = term.slice(1); + if (term[0] === "@") { + callback(completeNicks(term.slice(1), true).map((val) => ["@" + val[0], "@" + val[1]])); + } else { + callback(completeNicks(term, true)); + } + }, + template([string]) { + return string; + }, + replace([, original]) { + return "$1" + replaceNick(original); + }, + index: 2, +}; +const chanStrategy = { + id: "chans", + match: /(^|\s)((?:#|\+|&|![A-Z0-9]{5})(?:[^\s]+)?)$/, + search(term, callback) { + callback(completeChans(term)); + }, + template([string]) { + return string; + }, + replace([, original]) { + return "$1" + original; + }, + index: 2, +}; +const commandStrategy = { + id: "commands", + match: /^\/(\w*)$/, + search(term, callback) { + callback(completeCommands("/" + term)); + }, + template([string]) { + return string; + }, + replace([, original]) { + return original; + }, + index: 1, +}; +const foregroundColorStrategy = { + id: "foreground-colors", + match: /\x03(\d{0,2}|[A-Za-z ]{0,10})$/, + search(term, callback) { + term = term.toLowerCase(); + const matchingColorCodes = constants.colorCodeMap + .filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1])) + .map((i) => { + if (fuzzy.test(term, i[1])) { + return [ + i[0], + fuzzy.match(term, i[1], { + pre: "", + post: "", + }).rendered, + ]; + } + return i; + }); + callback(matchingColorCodes); + }, + template(value) { + return `${value[1]}`; + }, + replace(value) { + return "\x03" + value[0]; + }, + index: 1, +}; +const backgroundColorStrategy = { + id: "background-colors", + match: /\x03(\d{2}),(\d{0,2}|[A-Za-z ]{0,10})$/, + search(term, callback, match) { + term = term.toLowerCase(); + const matchingColorCodes = constants.colorCodeMap + .filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1])) + .map((pair) => { + if (fuzzy.test(term, pair[1])) { + return [ + pair[0], + fuzzy.match(term, pair[1], { + pre: "", + post: "", + }).rendered, + ]; + } + return pair; + }) + .map((pair) => pair.concat(match[1])); // Needed to pass fg color to `template`... + callback(matchingColorCodes); + }, + template(value) { + return `${value[1]}`; + }, + replace(value) { + return "\x03$1," + value[0]; + }, + index: 2, +}; +function enableAutocomplete(input) { + let tabCount = 0; + let lastMatch = ""; + let currentMatches = []; + input.addEventListener("input", (e) => { + if (e.detail === "autocomplete") { + return; + } + tabCount = 0; + currentMatches = []; + lastMatch = ""; + }); + Mousetrap(input).bind( + "tab", + (e) => { + if (store.state.isAutoCompleting) { + return; + } + e.preventDefault(); + const text = input.value; + if (tabCount === 0) { + lastMatch = text.substring(0, input.selectionStart).split(/\s/).pop(); + if (lastMatch.length === 0) { + return; + } + currentMatches = completeNicks(lastMatch, false); + if (currentMatches.length === 0) { + return; + } + } + const position = input.selectionStart - lastMatch.length; + const newMatch = replaceNick( + currentMatches[tabCount % currentMatches.length], + position + ); + const remainder = text.substr(input.selectionStart); + input.value = text.substr(0, position) + newMatch + remainder; + input.selectionStart -= remainder.length; + input.selectionEnd = input.selectionStart; + // Propagate change to Vue model + input.dispatchEvent( + new CustomEvent("input", { + detail: "autocomplete", + }) + ); + lastMatch = newMatch; + tabCount++; + }, + "keydown" + ); + const strategies = [ + emojiStrategy, + nicksStrategy, + chanStrategy, + commandStrategy, + foregroundColorStrategy, + backgroundColorStrategy, + ]; + const editor = new TextareaEditor(input); + const textcomplete = new Textcomplete(editor, strategies, { + dropdown: { + className: "textcomplete-menu", + placement: "top", + }, + }); + textcomplete.on("show", () => { + store.commit("isAutoCompleting", true); + }); + textcomplete.on("hidden", () => { + store.commit("isAutoCompleting", false); + }); + return { + hide() { + textcomplete.hide(); + }, + destroy() { + textcomplete.destroy(); + store.commit("isAutoCompleting", false); + }, + }; +} +function replaceNick(original, position = 1) { + // If no postfix specified, return autocompleted nick as-is + if (!store.state.settings.nickPostfix) { + return original; + } + // If there is whitespace in the input already, append space to nick + if (position > 0 && /\s/.test(store.state.activeChannel.channel.pendingMessage)) { + return original + " "; + } + // If nick is first in the input, append specified postfix + return original + store.state.settings.nickPostfix; +} +function fuzzyGrep(term, array) { + const results = fuzzy.filter(term, array, { + pre: "", + post: "", + }); + return results.map((el) => [el.string, el.original]); +} +function rawNicks() { + if (store.state.activeChannel.channel.users.length > 0) { + const users = store.state.activeChannel.channel.users.slice(); + return users.sort((a, b) => b.lastMessage - a.lastMessage).map((u) => u.nick); + } + const me = store.state.activeChannel.network.nick; + const otherUser = store.state.activeChannel.channel.name; + // If this is a query, add their name to autocomplete + if (me !== otherUser && store.state.activeChannel.channel.type === "query") { + return [otherUser, me]; + } + // Return our own name by default for anything that isn't a channel or query + return [me]; +} +function completeNicks(word, isFuzzy) { + const users = rawNicks(); + word = word.toLowerCase(); + if (isFuzzy) { + return fuzzyGrep(word, users); + } + return users.filter((w) => !w.toLowerCase().indexOf(word)); +} +function getCommands() { + let cmds = constants.commands.slice(); + if (!store.state.settings.searchEnabled) { + cmds = cmds.filter((c) => c !== "/search"); + } + return cmds; +} +function completeCommands(word) { + const commands = getCommands(); + return fuzzyGrep(word, commands); +} +function completeChans(word) { + const words = []; + for (const channel of store.state.activeChannel.network.channels) { + // Push all channels that start with the same CHANTYPE + if (channel.type === "channel" && channel.name[0] === word[0]) { + words.push(channel.name); + } + } + return fuzzyGrep(word, words); +} +//# sourceMappingURL=autocompletion.js.map diff --git a/client/dist/js/autocompletion.js.map b/client/dist/js/autocompletion.js.map new file mode 100644 index 00000000..d90df641 --- /dev/null +++ b/client/dist/js/autocompletion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"autocompletion.js","sourceRoot":"","sources":["../../js/autocompletion.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/client/dist/js/clipboard.js b/client/dist/js/clipboard.js new file mode 100644 index 00000000..6a6a6bb8 --- /dev/null +++ b/client/dist/js/clipboard.js @@ -0,0 +1,25 @@ +"use strict"; +export default function (chat) { + // Disable in Firefox as it already copies flex text correctly + if (typeof window.InstallTrigger !== "undefined") { + return; + } + const selection = window.getSelection(); + // If selection does not span multiple elements, do nothing + if (selection.anchorNode === selection.focusNode) { + return; + } + const range = selection.getRangeAt(0); + const documentFragment = range.cloneContents(); + const div = document.createElement("div"); + div.id = "js-copy-hack"; + div.appendChild(documentFragment); + chat.appendChild(div); + selection.selectAllChildren(div); + window.setTimeout(() => { + chat.removeChild(div); + selection.removeAllRanges(); + selection.addRange(range); + }, 0); +} +//# sourceMappingURL=clipboard.js.map diff --git a/client/dist/js/clipboard.js.map b/client/dist/js/clipboard.js.map new file mode 100644 index 00000000..d23987cb --- /dev/null +++ b/client/dist/js/clipboard.js.map @@ -0,0 +1 @@ +{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../js/clipboard.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,WAAW,IAAI;IAC5B,8DAA8D;IAC9D,IAAI,OAAO,MAAM,CAAC,cAAc,KAAK,WAAW,EAAE;QACjD,OAAO;KACP;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;IAExC,2DAA2D;IAC3D,IAAI,SAAS,CAAC,UAAU,KAAK,SAAS,CAAC,SAAS,EAAE;QACjD,OAAO;KACP;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,gBAAgB,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;IAC/C,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAE1C,GAAG,CAAC,EAAE,GAAG,cAAc,CAAC;IACxB,GAAG,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;IAClC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAEtB,SAAS,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAEjC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE;QACtB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACtB,SAAS,CAAC,eAAe,EAAE,CAAC;QAC5B,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,EAAE,CAAC,CAAC,CAAC;AACP,CAAC"} \ No newline at end of file diff --git a/client/dist/js/commands/collapse.js b/client/dist/js/commands/collapse.js new file mode 100644 index 00000000..910fc242 --- /dev/null +++ b/client/dist/js/commands/collapse.js @@ -0,0 +1,29 @@ +"use strict"; +import socket from "../socket"; +import store from "../store"; +function input() { + const messageIds = []; + for (const message of store.state.activeChannel.channel.messages) { + let toggled = false; + for (const preview of message.previews) { + if (preview.shown) { + preview.shown = false; + toggled = true; + } + } + if (toggled) { + messageIds.push(message.id); + } + } + // Tell the server we're toggling so it remembers at page reload + if (!document.body.classList.contains("public") && messageIds.length > 0) { + socket.emit("msg:preview:toggle", { + target: store.state.activeChannel.channel.id, + messageIds: messageIds, + shown: false, + }); + } + return true; +} +export default {input}; +//# sourceMappingURL=collapse.js.map diff --git a/client/dist/js/commands/collapse.js.map b/client/dist/js/commands/collapse.js.map new file mode 100644 index 00000000..2781257a --- /dev/null +++ b/client/dist/js/commands/collapse.js.map @@ -0,0 +1 @@ +{"version":3,"file":"collapse.js","sourceRoot":"","sources":["../../../js/commands/collapse.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,OAAO,KAAK,MAAM,UAAU,CAAC;AAE7B,SAAS,KAAK;IACb,MAAM,UAAU,GAAG,EAAE,CAAC;IAEtB,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE;QACjE,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE;YACvC,IAAI,OAAO,CAAC,KAAK,EAAE;gBAClB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;gBACtB,OAAO,GAAG,IAAI,CAAC;aACf;SACD;QAED,IAAI,OAAO,EAAE;YACZ,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;SAC5B;KACD;IAED,gEAAgE;IAChE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;QACzE,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE;YACjC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE;YAC5C,UAAU,EAAE,UAAU;YACtB,KAAK,EAAE,KAAK;SACZ,CAAC,CAAC;KACH;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED,eAAe,EAAC,KAAK,EAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/commands/expand.js b/client/dist/js/commands/expand.js new file mode 100644 index 00000000..c1f8a1e9 --- /dev/null +++ b/client/dist/js/commands/expand.js @@ -0,0 +1,29 @@ +"use strict"; +import socket from "../socket"; +import store from "../store"; +function input() { + const messageIds = []; + for (const message of store.state.activeChannel.channel.messages) { + let toggled = false; + for (const preview of message.previews) { + if (!preview.shown) { + preview.shown = true; + toggled = true; + } + } + if (toggled) { + messageIds.push(message.id); + } + } + // Tell the server we're toggling so it remembers at page reload + if (!document.body.classList.contains("public") && messageIds.length > 0) { + socket.emit("msg:preview:toggle", { + target: store.state.activeChannel.channel.id, + messageIds: messageIds, + shown: true, + }); + } + return true; +} +export default {input}; +//# sourceMappingURL=expand.js.map diff --git a/client/dist/js/commands/expand.js.map b/client/dist/js/commands/expand.js.map new file mode 100644 index 00000000..bba13c85 --- /dev/null +++ b/client/dist/js/commands/expand.js.map @@ -0,0 +1 @@ +{"version":3,"file":"expand.js","sourceRoot":"","sources":["../../../js/commands/expand.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,OAAO,KAAK,MAAM,UAAU,CAAC;AAE7B,SAAS,KAAK;IACb,MAAM,UAAU,GAAG,EAAE,CAAC;IAEtB,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE;QACjE,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE;YACvC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBACnB,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;gBACrB,OAAO,GAAG,IAAI,CAAC;aACf;SACD;QAED,IAAI,OAAO,EAAE;YACZ,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;SAC5B;KACD;IAED,gEAAgE;IAChE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;QACzE,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE;YACjC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE;YAC5C,UAAU,EAAE,UAAU;YACtB,KAAK,EAAE,IAAI;SACX,CAAC,CAAC;KACH;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED,eAAe,EAAC,KAAK,EAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/commands/index.js b/client/dist/js/commands/index.js new file mode 100644 index 00000000..f3265350 --- /dev/null +++ b/client/dist/js/commands/index.js @@ -0,0 +1,16 @@ +"use strict"; +// Taken from views/index.js +// This creates a version of `require()` in the context of the current +// directory, so we iterate over its content, which is a map statically built by +// Webpack. +// Second argument says it's recursive, third makes sure we only load javascript. +const commands = require.context("./", true, /\.js$/); +export default commands.keys().reduce((acc, path) => { + const command = path.substring(2, path.length - 3); + if (command === "index") { + return acc; + } + acc[command] = commands(path).default; + return acc; +}, {}); +//# sourceMappingURL=index.js.map diff --git a/client/dist/js/commands/index.js.map b/client/dist/js/commands/index.js.map new file mode 100644 index 00000000..53dace1b --- /dev/null +++ b/client/dist/js/commands/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../js/commands/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,4BAA4B;AAE5B,sEAAsE;AACtE,gFAAgF;AAChF,WAAW;AACX,iFAAiF;AACjF,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAEtD,eAAe,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEnD,IAAI,OAAO,KAAK,OAAO,EAAE;QACxB,OAAO,GAAG,CAAC;KACX;IAED,GAAG,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;IAEtC,OAAO,GAAG,CAAC;AACZ,CAAC,EAAE,EAAE,CAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/commands/join.js b/client/dist/js/commands/join.js new file mode 100644 index 00000000..59dfb281 --- /dev/null +++ b/client/dist/js/commands/join.js @@ -0,0 +1,40 @@ +"use strict"; +import socket from "../socket"; +import store from "../store"; +import {switchToChannel} from "../router"; +function input(args) { + if (args.length > 0) { + let channels = args[0]; + if (channels.length > 0) { + const chanTypes = store.state.activeChannel.network.serverOptions.CHANTYPES; + const channelList = args[0].split(","); + if (chanTypes && chanTypes.length > 0) { + for (let c = 0; c < channelList.length; c++) { + if (!chanTypes.includes(channelList[c][0])) { + channelList[c] = chanTypes[0] + channelList[c]; + } + } + } + channels = channelList.join(","); + const chan = store.getters.findChannelOnCurrentNetwork(channels); + if (chan) { + switchToChannel(chan); + } else { + socket.emit("input", { + text: `/join ${channels} ${args.length > 1 ? args[1] : ""}`, + target: store.state.activeChannel.channel.id, + }); + return true; + } + } + } else if (store.state.activeChannel.channel.type === "channel") { + // If `/join` command is used without any arguments, re-join current channel + socket.emit("input", { + target: store.state.activeChannel.channel.id, + text: `/join ${store.state.activeChannel.channel.name}`, + }); + return true; + } +} +export default {input}; +//# sourceMappingURL=join.js.map diff --git a/client/dist/js/commands/join.js.map b/client/dist/js/commands/join.js.map new file mode 100644 index 00000000..8e105ed9 --- /dev/null +++ b/client/dist/js/commands/join.js.map @@ -0,0 +1 @@ +{"version":3,"file":"join.js","sourceRoot":"","sources":["../../../js/commands/join.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,OAAO,KAAK,MAAM,UAAU,CAAC;AAC7B,OAAO,EAAC,eAAe,EAAC,MAAM,WAAW,CAAC;AAE1C,SAAS,KAAK,CAAC,IAAI;IAClB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;QACpB,IAAI,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEvB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;YACxB,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC;YAC5E,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAEvC,IAAI,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;gBACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBAC5C,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;wBAC3C,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;qBAC/C;iBACD;aACD;YAED,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAEjC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,2BAA2B,CAAC,QAAQ,CAAC,CAAC;YAEjE,IAAI,IAAI,EAAE;gBACT,eAAe,CAAC,IAAI,CAAC,CAAC;aACtB;iBAAM;gBACN,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;oBACpB,IAAI,EAAE,SAAS,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE;oBAC3D,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE;iBAC5C,CAAC,CAAC;gBAEH,OAAO,IAAI,CAAC;aACZ;SACD;KACD;SAAM,IAAI,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE;QAChE,4EAA4E;QAC5E,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;YACpB,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE;YAC5C,IAAI,EAAE,SAAS,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE;SACvD,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;KACZ;AACF,CAAC;AAED,eAAe,EAAC,KAAK,EAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/commands/search.js b/client/dist/js/commands/search.js new file mode 100644 index 00000000..8e2e7247 --- /dev/null +++ b/client/dist/js/commands/search.js @@ -0,0 +1,20 @@ +"use strict"; +import store from "../store"; +import {router} from "../router"; +function input(args) { + if (!store.state.settings.searchEnabled) { + return false; + } + router.push({ + name: "SearchResults", + params: { + id: store.state.activeChannel.channel.id, + }, + query: { + q: args.join(" "), + }, + }); + return true; +} +export default {input}; +//# sourceMappingURL=search.js.map diff --git a/client/dist/js/commands/search.js.map b/client/dist/js/commands/search.js.map new file mode 100644 index 00000000..bad67269 --- /dev/null +++ b/client/dist/js/commands/search.js.map @@ -0,0 +1 @@ +{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../js/commands/search.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,KAAK,MAAM,UAAU,CAAC;AAC7B,OAAO,EAAC,MAAM,EAAC,MAAM,WAAW,CAAC;AAEjC,SAAS,KAAK,CAAC,IAAI;IAClB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,EAAE;QACxC,OAAO,KAAK,CAAC;KACb;IAED,MAAM,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE;YACP,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE;SACxC;QACD,KAAK,EAAE;YACN,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;SACjB;KACD,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACb,CAAC;AAED,eAAe,EAAC,KAAK,EAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/constants.js b/client/dist/js/constants.js new file mode 100644 index 00000000..6dbfcf41 --- /dev/null +++ b/client/dist/js/constants.js @@ -0,0 +1,35 @@ +"use strict"; +const colorCodeMap = [ + ["00", "White"], + ["01", "Black"], + ["02", "Blue"], + ["03", "Green"], + ["04", "Red"], + ["05", "Brown"], + ["06", "Magenta"], + ["07", "Orange"], + ["08", "Yellow"], + ["09", "Light Green"], + ["10", "Cyan"], + ["11", "Light Cyan"], + ["12", "Light Blue"], + ["13", "Pink"], + ["14", "Grey"], + ["15", "Light Grey"], +]; +const condensedTypes = new Set(["chghost", "join", "part", "quit", "nick", "kick", "mode"]); +const timeFormats = { + msgDefault: "HH:mm", + msgWithSeconds: "HH:mm:ss", + msg12h: "hh:mm A", + msg12hWithSeconds: "hh:mm:ss A", +}; +export default { + colorCodeMap, + commands: [], + condensedTypes, + timeFormats, + // Same value as media query in CSS that forces sidebars to become overlays + mobileViewportPixels: 768, +}; +//# sourceMappingURL=constants.js.map diff --git a/client/dist/js/constants.js.map b/client/dist/js/constants.js.map new file mode 100644 index 00000000..6b2257fe --- /dev/null +++ b/client/dist/js/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../js/constants.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,YAAY,GAAG;IACpB,CAAC,IAAI,EAAE,OAAO,CAAC;IACf,CAAC,IAAI,EAAE,OAAO,CAAC;IACf,CAAC,IAAI,EAAE,MAAM,CAAC;IACd,CAAC,IAAI,EAAE,OAAO,CAAC;IACf,CAAC,IAAI,EAAE,KAAK,CAAC;IACb,CAAC,IAAI,EAAE,OAAO,CAAC;IACf,CAAC,IAAI,EAAE,SAAS,CAAC;IACjB,CAAC,IAAI,EAAE,QAAQ,CAAC;IAChB,CAAC,IAAI,EAAE,QAAQ,CAAC;IAChB,CAAC,IAAI,EAAE,aAAa,CAAC;IACrB,CAAC,IAAI,EAAE,MAAM,CAAC;IACd,CAAC,IAAI,EAAE,YAAY,CAAC;IACpB,CAAC,IAAI,EAAE,YAAY,CAAC;IACpB,CAAC,IAAI,EAAE,MAAM,CAAC;IACd,CAAC,IAAI,EAAE,MAAM,CAAC;IACd,CAAC,IAAI,EAAE,YAAY,CAAC;CACpB,CAAC;AAEF,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5F,MAAM,WAAW,GAAG;IACnB,UAAU,EAAE,OAAO;IACnB,cAAc,EAAE,UAAU;IAC1B,MAAM,EAAE,SAAS;IACjB,iBAAiB,EAAE,YAAY;CAC/B,CAAC;AAEF,eAAe;IACd,YAAY;IACZ,QAAQ,EAAE,EAAE;IACZ,cAAc;IACd,WAAW;IACX,2EAA2E;IAC3E,oBAAoB,EAAE,GAAG;CACzB,CAAC"} \ No newline at end of file diff --git a/client/dist/js/eventbus.js b/client/dist/js/eventbus.js new file mode 100644 index 00000000..a898b692 --- /dev/null +++ b/client/dist/js/eventbus.js @@ -0,0 +1,48 @@ +const events = new Map(); +class EventBus { + /** + * Register an event handler for the given type. + * + * @param {String} type Type of event to listen for. + * @param {Function} handler Function to call in response to given event. + */ + on(type, handler) { + if (events.has(type)) { + events.get(type).push(handler); + } else { + events.set(type, [handler]); + } + } + /** + * Remove an event handler for the given type. + * + * @param {String} type Type of event to unregister `handler` from. + * @param {Function} handler Handler function to remove. + */ + off(type, handler) { + if (events.has(type)) { + events.set( + type, + events.get(type).filter((item) => item !== handler) + ); + } + } + /** + * Invoke all handlers for the given type. + * + * @param {String} type The event type to invoke. + * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler. + */ + emit(type, ...evt) { + if (events.has(type)) { + events + .get(type) + .slice() + .map((handler) => { + handler(...evt); + }); + } + } +} +export default new EventBus(); +//# sourceMappingURL=eventbus.js.map diff --git a/client/dist/js/eventbus.js.map b/client/dist/js/eventbus.js.map new file mode 100644 index 00000000..d66d7711 --- /dev/null +++ b/client/dist/js/eventbus.js.map @@ -0,0 +1 @@ +{"version":3,"file":"eventbus.js","sourceRoot":"","sources":["../../js/eventbus.js"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;AAEzB,MAAM,QAAQ;IACb;;;;;OAKG;IACH,EAAE,CAAC,IAAI,EAAE,OAAO;QACf,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACrB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;SAC/B;aAAM;YACN,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;SAC5B;IACF,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,OAAO;QAChB,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACrB,MAAM,CAAC,GAAG,CACT,IAAI,EACJ,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC,CACnD,CAAC;SACF;IACF,CAAC;IAED;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG;QAChB,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACrB,MAAM;iBACJ,GAAG,CAAC,IAAI,CAAC;iBACT,KAAK,EAAE;iBACP,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;gBAChB,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;YACjB,CAAC,CAAC,CAAC;SACJ;IACF,CAAC;CACD;AAED,eAAe,IAAI,QAAQ,EAAE,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/collapseNetwork.js b/client/dist/js/helpers/collapseNetwork.js new file mode 100644 index 00000000..1dbf507e --- /dev/null +++ b/client/dist/js/helpers/collapseNetwork.js @@ -0,0 +1,13 @@ +"use strict"; +import storage from "../localStorage"; +export default (network, isCollapsed) => { + const networks = new Set(JSON.parse(storage.get("thelounge.networks.collapsed"))); + network.isCollapsed = isCollapsed; + if (isCollapsed) { + networks.add(network.uuid); + } else { + networks.delete(network.uuid); + } + storage.set("thelounge.networks.collapsed", JSON.stringify([...networks])); +}; +//# sourceMappingURL=collapseNetwork.js.map diff --git a/client/dist/js/helpers/collapseNetwork.js.map b/client/dist/js/helpers/collapseNetwork.js.map new file mode 100644 index 00000000..08dd97fa --- /dev/null +++ b/client/dist/js/helpers/collapseNetwork.js.map @@ -0,0 +1 @@ +{"version":3,"file":"collapseNetwork.js","sourceRoot":"","sources":["../../../js/helpers/collapseNetwork.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,OAAO,MAAM,iBAAiB,CAAC;AAEtC,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE;IACvC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC,CAAC;IAClF,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC;IAElC,IAAI,WAAW,EAAE;QAChB,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;KAC3B;SAAM;QACN,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;KAC9B;IAED,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/colorClass.js b/client/dist/js/helpers/colorClass.js new file mode 100644 index 00000000..2e62badb --- /dev/null +++ b/client/dist/js/helpers/colorClass.js @@ -0,0 +1,15 @@ +"use strict"; +// Generates a string from "color-1" to "color-32" based on an input string +export default (str) => { + let hash = 0; + for (let i = 0; i < str.length; i++) { + hash += str.charCodeAt(i); + } + /* + Modulo 32 lets us be case insensitive for ascii + due to A being ascii 65 (100 0001) + while a being ascii 97 (110 0001) + */ + return "color-" + (1 + (hash % 32)); +}; +//# sourceMappingURL=colorClass.js.map diff --git a/client/dist/js/helpers/colorClass.js.map b/client/dist/js/helpers/colorClass.js.map new file mode 100644 index 00000000..0d382d86 --- /dev/null +++ b/client/dist/js/helpers/colorClass.js.map @@ -0,0 +1 @@ +{"version":3,"file":"colorClass.js","sourceRoot":"","sources":["../../../js/helpers/colorClass.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,2EAA2E;AAC3E,eAAe,CAAC,GAAG,EAAE,EAAE;IACtB,IAAI,IAAI,GAAG,CAAC,CAAC;IAEb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACpC,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;KAC1B;IAED;;;;MAIE;IACF,OAAO,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;AACrC,CAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/contextMenu.js b/client/dist/js/helpers/contextMenu.js new file mode 100644 index 00000000..ec184686 --- /dev/null +++ b/client/dist/js/helpers/contextMenu.js @@ -0,0 +1,378 @@ +"use strict"; +import socket from "../socket"; +import eventbus from "../eventbus"; +export function generateChannelContextMenu($root, channel, network) { + const typeMap = { + lobby: "network", + channel: "chan", + query: "query", + special: "chan", + }; + const closeMap = { + lobby: "Remove", + channel: "Leave", + query: "Close", + special: "Close", + }; + let items = [ + { + label: channel.name, + type: "item", + class: typeMap[channel.type], + link: `/chan-${channel.id}`, + }, + { + type: "divider", + }, + ]; + // Add menu items for lobbies + if (channel.type === "lobby") { + items = [ + ...items, + { + label: "Edit this network…", + type: "item", + class: "edit", + link: `/edit-network/${network.uuid}`, + }, + { + label: "Join a channel…", + type: "item", + class: "join", + action: () => (network.isJoinChannelShown = true), + }, + { + label: "List all channels", + type: "item", + class: "list", + action: () => + socket.emit("input", { + target: channel.id, + text: "/list", + }), + }, + { + label: "List ignored users", + type: "item", + class: "list", + action: () => + socket.emit("input", { + target: channel.id, + text: "/ignorelist", + }), + }, + network.status.connected + ? { + label: "Disconnect", + type: "item", + class: "disconnect", + action: () => + socket.emit("input", { + target: channel.id, + text: "/disconnect", + }), + } + : { + label: "Connect", + type: "item", + class: "connect", + action: () => + socket.emit("input", { + target: channel.id, + text: "/connect", + }), + }, + ]; + } + // Add menu items for channels + if (channel.type === "channel") { + items.push({ + label: "Edit topic", + type: "item", + class: "edit", + action() { + channel.editTopic = true; + $root.switchToChannel(channel); + }, + }); + items.push({ + label: "List banned users", + type: "item", + class: "list", + action() { + socket.emit("input", { + target: channel.id, + text: "/banlist", + }); + }, + }); + } + // Add menu items for queries + if (channel.type === "query") { + items.push( + { + label: "User information", + type: "item", + class: "action-whois", + action() { + $root.switchToChannel(channel); + socket.emit("input", { + target: channel.id, + text: "/whois " + channel.name, + }); + }, + }, + { + label: "Ignore user", + type: "item", + class: "action-ignore", + action() { + socket.emit("input", { + target: channel.id, + text: "/ignore " + channel.name, + }); + }, + } + ); + } + if (channel.type === "channel" || channel.type === "query") { + items.push({ + label: "Clear history", + type: "item", + class: "clear-history", + action() { + eventbus.emit( + "confirm-dialog", + { + title: "Clear history", + text: `Are you sure you want to clear history for ${channel.name}? This cannot be undone.`, + button: "Clear history", + }, + (result) => { + if (!result) { + return; + } + socket.emit("history:clear", { + target: channel.id, + }); + } + ); + }, + }); + } + const humanFriendlyChanTypeMap = { + lobby: "network", + channel: "channel", + query: "conversation", + }; + // We don't allow the muting of ChanType.SPECIAL channels + const mutableChanTypes = Object.keys(humanFriendlyChanTypeMap); + if (mutableChanTypes.includes(channel.type)) { + const chanType = humanFriendlyChanTypeMap[channel.type]; + items.push({ + label: channel.muted ? `Unmute ${chanType}` : `Mute ${chanType}`, + type: "item", + class: "mute", + action() { + socket.emit("mute:change", { + target: channel.id, + setMutedTo: !channel.muted, + }); + }, + }); + } + // Add close menu item + items.push({ + label: closeMap[channel.type], + type: "item", + class: "close", + action() { + $root.closeChannel(channel); + }, + }); + return items; +} +export function generateInlineChannelContextMenu($root, chan, network) { + const join = () => { + const channel = network.channels.find((c) => c.name === chan); + if (channel) { + $root.switchToChannel(channel); + } + socket.emit("input", { + target: $root.$store.state.activeChannel.channel.id, + text: "/join " + chan, + }); + }; + const channel = network.channels.find((c) => c.name === chan); + if (channel) { + return [ + { + label: "Go to channel", + type: "item", + class: "chan", + link: `/chan-${channel.id}`, + }, + ]; + } + return [ + { + label: "Join channel", + type: "item", + class: "join", + action: join, + }, + ]; +} +export function generateUserContextMenu($root, channel, network, user) { + const currentChannelUser = channel + ? channel.users.find((u) => u.nick === network.nick) || {} + : {}; + const whois = () => { + const chan = network.channels.find((c) => c.name === user.nick); + if (chan) { + $root.switchToChannel(chan); + } + socket.emit("input", { + target: channel.id, + text: "/whois " + user.nick, + }); + }; + const items = [ + { + label: user.nick, + type: "item", + class: "user", + action: whois, + }, + { + type: "divider", + }, + { + label: "User information", + type: "item", + class: "action-whois", + action: whois, + }, + { + label: "Ignore user", + type: "item", + class: "action-ignore", + action() { + socket.emit("input", { + target: channel.id, + text: "/ignore " + user.nick, + }); + }, + }, + { + label: "Direct messages", + type: "item", + class: "action-query", + action() { + const chan = $root.$store.getters.findChannelOnCurrentNetwork(user.nick); + if (chan) { + $root.switchToChannel(chan); + } + socket.emit("input", { + target: channel.id, + text: "/query " + user.nick, + }); + }, + }, + ]; + // Bail because we're in a query or we don't have a special mode. + if (!currentChannelUser.modes || currentChannelUser.modes.length < 1) { + return items; + } + // Names of the standard modes we are able to change + const modeCharToName = { + "~": "owner", + "&": "admin", + "@": "operator", + "%": "half-op", + "+": "voice", + }; + // Labels for the mode changes. For example .rev({mode: "a", symbol: "&"}) => 'Revoke admin (-a)' + const modeTextTemplate = { + revoke(m) { + const name = modeCharToName[m.symbol]; + const res = name ? `Revoke ${name} (-${m.mode})` : `Mode -${m.mode}`; + return res; + }, + give(m) { + const name = modeCharToName[m.symbol]; + const res = name ? `Give ${name} (+${m.mode})` : `Mode +${m.mode}`; + return res; + }, + }; + const networkModeSymbols = network.serverOptions.PREFIX.symbols; + /** + * Determine whether the prefix of mode p1 has access to perform actions on p2. + * + * EXAMPLE: + * compare('@', '@') => true + * compare('&', '@') => true + * compare('+', '~') => false + * @param {string} p1 The mode performing an action + * @param {string} p2 The target mode + * + * @return {boolean} whether p1 can perform an action on p2 + */ + function compare(p1, p2) { + // The modes ~ and @ can perform actions on their own mode. The others on modes below. + return "~@".indexOf(p1) > -1 + ? networkModeSymbols.indexOf(p1) <= networkModeSymbols.indexOf(p2) + : networkModeSymbols.indexOf(p1) < networkModeSymbols.indexOf(p2); + } + network.serverOptions.PREFIX.prefix.forEach((mode) => { + if (!compare(currentChannelUser.modes[0], mode.symbol)) { + // Our highest mode is below the current mode. Bail. + return; + } + if (!user.modes.includes(mode.symbol)) { + // The target doesn't already have this mode, therefore we can set it. + items.push({ + label: modeTextTemplate.give(mode), + type: "item", + class: "action-set-mode", + action() { + socket.emit("input", { + target: channel.id, + text: "/mode +" + mode.mode + " " + user.nick, + }); + }, + }); + } else { + items.push({ + label: modeTextTemplate.revoke(mode), + type: "item", + class: "action-revoke-mode", + action() { + socket.emit("input", { + target: channel.id, + text: "/mode -" + mode.mode + " " + user.nick, + }); + }, + }); + } + }); + // Determine if we are half-op or op depending on the network modes so we can kick. + if (!compare(networkModeSymbols.indexOf("%") > -1 ? "%" : "@", currentChannelUser.modes[0])) { + // Check if the target user has no mode or a mode lower than ours. + if (user.modes.length === 0 || compare(currentChannelUser.modes[0], user.modes[0])) { + items.push({ + label: "Kick", + type: "item", + class: "action-kick", + action() { + socket.emit("input", { + target: channel.id, + text: "/kick " + user.nick, + }); + }, + }); + } + } + return items; +} +//# sourceMappingURL=contextMenu.js.map diff --git a/client/dist/js/helpers/contextMenu.js.map b/client/dist/js/helpers/contextMenu.js.map new file mode 100644 index 00000000..72783177 --- /dev/null +++ b/client/dist/js/helpers/contextMenu.js.map @@ -0,0 +1 @@ +{"version":3,"file":"contextMenu.js","sourceRoot":"","sources":["../../../js/helpers/contextMenu.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/client/dist/js/helpers/distance.js b/client/dist/js/helpers/distance.js new file mode 100644 index 00000000..670693ca --- /dev/null +++ b/client/dist/js/helpers/distance.js @@ -0,0 +1,5 @@ +function distance([x1, y1], [x2, y2]) { + return Math.hypot(x1 - x2, y1 - y2); +} +export default distance; +//# sourceMappingURL=distance.js.map diff --git a/client/dist/js/helpers/distance.js.map b/client/dist/js/helpers/distance.js.map new file mode 100644 index 00000000..02f5b8d9 --- /dev/null +++ b/client/dist/js/helpers/distance.js.map @@ -0,0 +1 @@ +{"version":3,"file":"distance.js","sourceRoot":"","sources":["../../../js/helpers/distance.js"],"names":[],"mappings":"AAAA,SAAS,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,eAAe,QAAQ,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/friendlysize.js b/client/dist/js/helpers/friendlysize.js new file mode 100644 index 00000000..db1a4686 --- /dev/null +++ b/client/dist/js/helpers/friendlysize.js @@ -0,0 +1,9 @@ +"use strict"; +const sizes = ["Bytes", "KiB", "MiB", "GiB", "TiB", "PiB"]; +export default (size) => { + // Loosely inspired from https://stackoverflow.com/a/18650828/1935861 + const i = size > 0 ? Math.floor(Math.log(size) / Math.log(1024)) : 0; + const fixedSize = parseFloat((size / Math.pow(1024, i)).toFixed(1)); + return `${fixedSize} ${sizes[i]}`; +}; +//# sourceMappingURL=friendlysize.js.map diff --git a/client/dist/js/helpers/friendlysize.js.map b/client/dist/js/helpers/friendlysize.js.map new file mode 100644 index 00000000..f7255291 --- /dev/null +++ b/client/dist/js/helpers/friendlysize.js.map @@ -0,0 +1 @@ +{"version":3,"file":"friendlysize.js","sourceRoot":"","sources":["../../../js/helpers/friendlysize.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAE3D,eAAe,CAAC,IAAI,EAAE,EAAE;IACvB,qEAAqE;IACrE,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,OAAO,GAAG,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACnC,CAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/ircmessageparser/anyIntersection.js b/client/dist/js/helpers/ircmessageparser/anyIntersection.js new file mode 100644 index 00000000..9c041e6a --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/anyIntersection.js @@ -0,0 +1,13 @@ +"use strict"; +// Return true if any section of "a" or "b" parts (defined by their start/end +// markers) intersect each other, false otherwise. +function anyIntersection(a, b) { + return ( + (a.start <= b.start && b.start < a.end) || + (a.start < b.end && b.end <= a.end) || + (b.start <= a.start && a.start < b.end) || + (b.start < a.end && a.end <= b.end) + ); +} +export default anyIntersection; +//# sourceMappingURL=anyIntersection.js.map diff --git a/client/dist/js/helpers/ircmessageparser/anyIntersection.js.map b/client/dist/js/helpers/ircmessageparser/anyIntersection.js.map new file mode 100644 index 00000000..97b2bb3c --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/anyIntersection.js.map @@ -0,0 +1 @@ +{"version":3,"file":"anyIntersection.js","sourceRoot":"","sources":["../../../../js/helpers/ircmessageparser/anyIntersection.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,6EAA6E;AAC7E,kDAAkD;AAClD,SAAS,eAAe,CAAC,CAAC,EAAE,CAAC;IAC5B,OAAO,CACN,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC;QACvC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC;QACnC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC;QACvC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CACnC,CAAC;AACH,CAAC;AAED,eAAe,eAAe,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/ircmessageparser/cleanIrcMessage.js b/client/dist/js/helpers/ircmessageparser/cleanIrcMessage.js new file mode 100644 index 00000000..c612fef6 --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/cleanIrcMessage.js @@ -0,0 +1,5 @@ +"use strict"; +const matchFormatting = + /\x02|\x1D|\x1F|\x16|\x0F|\x11|\x1E|\x03(?:[0-9]{1,2}(?:,[0-9]{1,2})?)?|\x04(?:[0-9a-f]{6}(?:,[0-9a-f]{6})?)?/gi; +module.exports = (message) => message.replace(matchFormatting, "").trim(); +//# sourceMappingURL=cleanIrcMessage.js.map diff --git a/client/dist/js/helpers/ircmessageparser/cleanIrcMessage.js.map b/client/dist/js/helpers/ircmessageparser/cleanIrcMessage.js.map new file mode 100644 index 00000000..5bc423d4 --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/cleanIrcMessage.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cleanIrcMessage.js","sourceRoot":"","sources":["../../../../js/helpers/ircmessageparser/cleanIrcMessage.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,eAAe,GACpB,gHAAgH,CAAC;AAElH,MAAM,CAAC,OAAO,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/ircmessageparser/fill.js b/client/dist/js/helpers/ircmessageparser/fill.js new file mode 100644 index 00000000..0c82cb26 --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/fill.js @@ -0,0 +1,30 @@ +"use strict"; +// Create plain text entries corresponding to areas of the text that match no +// existing entries. Returns an empty array if all parts of the text have been +// parsed into recognizable entries already. +function fill(existingEntries, text) { + let position = 0; + // Fill inner parts of the text. For example, if text is `foobarbaz` and both + // `foo` and `baz` have matched into an entry, this will return a dummy entry + // corresponding to `bar`. + const result = existingEntries.reduce((acc, textSegment) => { + if (textSegment.start > position) { + acc.push({ + start: position, + end: textSegment.start, + }); + } + position = textSegment.end; + return acc; + }, []); + // Complete the unmatched end of the text with a dummy entry + if (position < text.length) { + result.push({ + start: position, + end: text.length, + }); + } + return result; +} +export default fill; +//# sourceMappingURL=fill.js.map diff --git a/client/dist/js/helpers/ircmessageparser/fill.js.map b/client/dist/js/helpers/ircmessageparser/fill.js.map new file mode 100644 index 00000000..c85edec6 --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/fill.js.map @@ -0,0 +1 @@ +{"version":3,"file":"fill.js","sourceRoot":"","sources":["../../../../js/helpers/ircmessageparser/fill.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,6EAA6E;AAC7E,8EAA8E;AAC9E,4CAA4C;AAC5C,SAAS,IAAI,CAAC,eAAe,EAAE,IAAI;IAClC,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,6EAA6E;IAC7E,6EAA6E;IAC7E,0BAA0B;IAC1B,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE;QAC1D,IAAI,WAAW,CAAC,KAAK,GAAG,QAAQ,EAAE;YACjC,GAAG,CAAC,IAAI,CAAC;gBACR,KAAK,EAAE,QAAQ;gBACf,GAAG,EAAE,WAAW,CAAC,KAAK;aACtB,CAAC,CAAC;SACH;QAED,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC;QAC3B,OAAO,GAAG,CAAC;IACZ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,4DAA4D;IAC5D,IAAI,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE;QAC3B,MAAM,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,QAAQ;YACf,GAAG,EAAE,IAAI,CAAC,MAAM;SAChB,CAAC,CAAC;KACH;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAED,eAAe,IAAI,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/ircmessageparser/findChannels.js b/client/dist/js/helpers/ircmessageparser/findChannels.js new file mode 100644 index 00000000..694e187f --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/findChannels.js @@ -0,0 +1,37 @@ +"use strict"; +// Escapes the RegExp special characters "^", "$", "", ".", "*", "+", "?", "(", +// ")", "[", "]", "{", "}", and "|" in string. +// See https://lodash.com/docs/#escapeRegExp +import escapeRegExp from "lodash/escapeRegExp"; +// Given an array of channel prefixes (such as "#" and "&") and an array of user +// modes (such as "@" and "+"), this function extracts channels and nicks from a +// text. +// It returns an array of objects for each channel found with their start index, +// end index and channel name. +function findChannels(text, channelPrefixes, userModes) { + // `userModePattern` is necessary to ignore user modes in /whois responses. + // For example, a voiced user in #thelounge will have a /whois response of: + // > foo is on the following channels: +#thelounge + // We need to explicitly ignore user modes to parse such channels correctly. + const userModePattern = userModes.map(escapeRegExp).join(""); + const channelPrefixPattern = channelPrefixes.map(escapeRegExp).join(""); + const channelPattern = `(?:^|\\s)[${userModePattern}]*([${channelPrefixPattern}][^ \u0007]+)`; + const channelRegExp = new RegExp(channelPattern, "g"); + const result = []; + let match; + do { + // With global ("g") regexes, calling `exec` multiple times will find + // successive matches in the same string. + match = channelRegExp.exec(text); + if (match) { + result.push({ + start: match.index + match[0].length - match[1].length, + end: match.index + match[0].length, + channel: match[1], + }); + } + } while (match); + return result; +} +export default findChannels; +//# sourceMappingURL=findChannels.js.map diff --git a/client/dist/js/helpers/ircmessageparser/findChannels.js.map b/client/dist/js/helpers/ircmessageparser/findChannels.js.map new file mode 100644 index 00000000..c26c9407 --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/findChannels.js.map @@ -0,0 +1 @@ +{"version":3,"file":"findChannels.js","sourceRoot":"","sources":["../../../../js/helpers/ircmessageparser/findChannels.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,+EAA+E;AAC/E,8CAA8C;AAC9C,4CAA4C;AAC5C,OAAO,YAAY,MAAM,qBAAqB,CAAC;AAE/C,gFAAgF;AAChF,gFAAgF;AAChF,QAAQ;AACR,gFAAgF;AAChF,8BAA8B;AAC9B,SAAS,YAAY,CAAC,IAAI,EAAE,eAAe,EAAE,SAAS;IACrD,2EAA2E;IAC3E,2EAA2E;IAC3E,kDAAkD;IAClD,4EAA4E;IAC5E,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7D,MAAM,oBAAoB,GAAG,eAAe,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxE,MAAM,cAAc,GAAG,aAAa,eAAe,OAAO,oBAAoB,eAAe,CAAC;IAC9F,MAAM,aAAa,GAAG,IAAI,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IAEtD,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,IAAI,KAAK,CAAC;IAEV,GAAG;QACF,qEAAqE;QACrE,yCAAyC;QACzC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEjC,IAAI,KAAK,EAAE;YACV,MAAM,CAAC,IAAI,CAAC;gBACX,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM;gBACtD,GAAG,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM;gBAClC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;aACjB,CAAC,CAAC;SACH;KACD,QAAQ,KAAK,EAAE;IAEhB,OAAO,MAAM,CAAC;AACf,CAAC;AAED,eAAe,YAAY,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/ircmessageparser/findEmoji.js b/client/dist/js/helpers/ircmessageparser/findEmoji.js new file mode 100644 index 00000000..08bd843d --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/findEmoji.js @@ -0,0 +1,16 @@ +"use strict"; +const emojiRegExp = require("emoji-regex")(); +function findEmoji(text) { + const result = []; + let match; + while ((match = emojiRegExp.exec(text))) { + result.push({ + start: match.index, + end: match.index + match[0].length, + emoji: match[0], + }); + } + return result; +} +export default findEmoji; +//# sourceMappingURL=findEmoji.js.map diff --git a/client/dist/js/helpers/ircmessageparser/findEmoji.js.map b/client/dist/js/helpers/ircmessageparser/findEmoji.js.map new file mode 100644 index 00000000..cbfb0c73 --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/findEmoji.js.map @@ -0,0 +1 @@ +{"version":3,"file":"findEmoji.js","sourceRoot":"","sources":["../../../../js/helpers/ircmessageparser/findEmoji.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;AAE7C,SAAS,SAAS,CAAC,IAAI;IACtB,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,IAAI,KAAK,CAAC;IAEV,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE;QACxC,MAAM,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,GAAG,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM;YAClC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;SACf,CAAC,CAAC;KACH;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAED,eAAe,SAAS,CAAC"} \ No newline at end of file diff --git a/client/js/helpers/ircmessageparser/findLinks.js b/client/dist/js/helpers/ircmessageparser/findLinks.js similarity index 88% rename from client/js/helpers/ircmessageparser/findLinks.js rename to client/dist/js/helpers/ircmessageparser/findLinks.js index b35a3efe..00c3bc37 100644 --- a/client/js/helpers/ircmessageparser/findLinks.js +++ b/client/dist/js/helpers/ircmessageparser/findLinks.js @@ -1,27 +1,23 @@ "use strict"; - -const LinkifyIt = require("linkify-it"); - +import LinkifyIt from "linkify-it"; LinkifyIt.prototype.normalize = function normalize(match) { if (!match.schema) { match.schema = "http:"; match.url = "http://" + match.url; + //@ts-ignore match.noschema = true; } - if (match.schema === "//") { match.schema = "http:"; match.url = "http:" + match.url; + //@ts-ignore match.noschema = true; } - if (match.schema === "mailto:" && !/^mailto:/i.test(match.url)) { match.url = "mailto:" + match.url; } }; - const linkify = LinkifyIt().tlds(require("tlds")).tlds("onion", true); - // Known schemes to detect in text const commonSchemes = [ "sftp", @@ -39,31 +35,23 @@ const commonSchemes = [ "gopher", "gemini", ]; - for (const schema of commonSchemes) { linkify.add(schema + ":", "http:"); } - function findLinks(text) { const matches = linkify.match(text); - if (!matches) { return []; } - return matches.map(returnUrl); } - function findLinksWithSchema(text) { const matches = linkify.match(text); - if (!matches) { return []; } - return matches.filter((url) => !url.noschema).map(returnUrl); } - function returnUrl(url) { return { start: url.index, @@ -71,8 +59,5 @@ function returnUrl(url) { link: url.url, }; } - -module.exports = { - findLinks, - findLinksWithSchema, -}; +export {findLinks, findLinksWithSchema}; +//# sourceMappingURL=findLinks.js.map diff --git a/client/dist/js/helpers/ircmessageparser/findLinks.js.map b/client/dist/js/helpers/ircmessageparser/findLinks.js.map new file mode 100644 index 00000000..e939235e --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/findLinks.js.map @@ -0,0 +1 @@ +{"version":3,"file":"findLinks.js","sourceRoot":"","sources":["../../../../js/helpers/ircmessageparser/findLinks.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,SAAoB,MAAM,YAAY,CAAA;AAM7C,SAAS,CAAC,SAAS,CAAC,SAAS,GAAG,SAAS,SAAS,CAAC,KAAe;IACjE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QAClB,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;QACvB,KAAK,CAAC,GAAG,GAAG,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC;QAClC,YAAY;QACZ,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;KACtB;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE;QAC1B,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;QACvB,KAAK,CAAC,GAAG,GAAG,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC;QAChC,YAAY;QACZ,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;KACtB;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;QAC/D,KAAK,CAAC,GAAG,GAAG,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC;KAClC;AACF,CAAC,CAAC;AAEF,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAEtE,kCAAkC;AAClC,MAAM,aAAa,GAAG;IACrB,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,OAAO;IACP,QAAQ;IACR,WAAW;IACX,SAAS;IACT,KAAK;IACL,QAAQ;IACR,QAAQ;CACR,CAAC;AAEF,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE;IACnC,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,SAAS,SAAS,CAAC,IAAY;IAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;IAElD,IAAI,CAAC,OAAO,EAAE;QACb,OAAO,EAAE,CAAC;KACV;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACxC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;IAElD,IAAI,CAAC,OAAO,EAAE;QACb,OAAO,EAAE,CAAC;KACV;IAED,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,SAAS,CAAC,GAAa;IAC/B,OAAO;QACN,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,GAAG,EAAE,GAAG,CAAC,SAAS;QAClB,IAAI,EAAE,GAAG,CAAC,GAAG;KACb,CAAC;AACH,CAAC;AAED,OAAO,EACN,SAAS,EACT,mBAAmB,GACnB,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/ircmessageparser/findNames.js b/client/dist/js/helpers/ircmessageparser/findNames.js new file mode 100644 index 00000000..89688e2b --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/findNames.js @@ -0,0 +1,22 @@ +"use strict"; +const nickRegExp = /([\w[\]\\`^{|}-]+)/g; +function findNames(text, users) { + const result = []; + // Return early if we don't have any nicknames to find + if (users.length === 0) { + return result; + } + let match; + while ((match = nickRegExp.exec(text))) { + if (users.indexOf(match[1]) > -1) { + result.push({ + start: match.index, + end: match.index + match[1].length, + nick: match[1], + }); + } + } + return result; +} +export default findNames; +//# sourceMappingURL=findNames.js.map diff --git a/client/dist/js/helpers/ircmessageparser/findNames.js.map b/client/dist/js/helpers/ircmessageparser/findNames.js.map new file mode 100644 index 00000000..bdddf9dc --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/findNames.js.map @@ -0,0 +1 @@ +{"version":3,"file":"findNames.js","sourceRoot":"","sources":["../../../../js/helpers/ircmessageparser/findNames.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,UAAU,GAAG,qBAAqB,CAAC;AAEzC,SAAS,SAAS,CAAC,IAAI,EAAE,KAAK;IAC7B,MAAM,MAAM,GAAG,EAAE,CAAC;IAElB,sDAAsD;IACtD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;QACvB,OAAO,MAAM,CAAC;KACd;IAED,IAAI,KAAK,CAAC;IAEV,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE;QACvC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;YACjC,MAAM,CAAC,IAAI,CAAC;gBACX,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,GAAG,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM;gBAClC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;aACd,CAAC,CAAC;SACH;KACD;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAED,eAAe,SAAS,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/ircmessageparser/merge.js b/client/dist/js/helpers/ircmessageparser/merge.js new file mode 100644 index 00000000..8d0a6faa --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/merge.js @@ -0,0 +1,44 @@ +"use strict"; +import anyIntersection from "./anyIntersection"; +import fill from "./fill"; +// Merge text part information within a styling fragment +function assign(textPart, fragment) { + const fragStart = fragment.start; + const start = Math.max(fragment.start, textPart.start); + const end = Math.min(fragment.end, textPart.end); + const text = fragment.text.slice(start - fragStart, end - fragStart); + return Object.assign({}, fragment, {start, end, text}); +} +function sortParts(a, b) { + return a.start - b.start || b.end - a.end; +} +// Merge the style fragments within the text parts, taking into account +// boundaries and text sections that have not matched to links or channels. +// For example, given a string "foobar" where "foo" and "bar" have been +// identified as parts (channels, links, etc.) and "fo", "ob" and "ar" have 3 +// different styles, the first resulting part will contain fragments "fo" and +// "o", and the second resulting part will contain "b" and "ar". "o" and "b" +// fragments will contain duplicate styling attributes. +function merge(textParts, styleFragments, cleanText) { + // Remove overlapping parts + textParts = textParts.sort(sortParts).reduce((prev, curr) => { + const intersection = prev.some((p) => anyIntersection(p, curr)); + if (intersection) { + return prev; + } + return prev.concat([curr]); + }, []); + // Every section of the original text that has not been captured in a "part" + // is filled with "text" parts, dummy objects with start/end but no extra + // metadata. + const allParts = textParts.concat(fill(textParts, cleanText)).sort(sortParts); // Sort all parts identified based on their position in the original text + // Distribute the style fragments within the text parts + return allParts.map((textPart) => { + textPart.fragments = styleFragments + .filter((fragment) => anyIntersection(textPart, fragment)) + .map((fragment) => assign(textPart, fragment)); + return textPart; + }); +} +export default merge; +//# sourceMappingURL=merge.js.map diff --git a/client/dist/js/helpers/ircmessageparser/merge.js.map b/client/dist/js/helpers/ircmessageparser/merge.js.map new file mode 100644 index 00000000..50e81779 --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/merge.js.map @@ -0,0 +1 @@ +{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../../../js/helpers/ircmessageparser/merge.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAChD,OAAO,IAAI,MAAM,QAAQ,CAAC;AAE1B,wDAAwD;AACxD,SAAS,MAAM,CAAC,QAAQ,EAAE,QAAQ;IACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,SAAS,EAAE,GAAG,GAAG,SAAS,CAAC,CAAC;IAErE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAC,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,SAAS,CAAC,CAAC,EAAE,CAAC;IACtB,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;AAC3C,CAAC;AAED,uEAAuE;AACvE,2EAA2E;AAC3E,uEAAuE;AACvE,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,uDAAuD;AACvD,SAAS,KAAK,CAAC,SAAS,EAAE,cAAc,EAAE,SAAS;IAClD,2BAA2B;IAC3B,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;QAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QAEhE,IAAI,YAAY,EAAE;YACjB,OAAO,IAAI,CAAC;SACZ;QAED,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5B,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,4EAA4E;IAC5E,yEAAyE;IACzE,YAAY;IACZ,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,yEAAyE;IAExJ,uDAAuD;IACvD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChC,QAAQ,CAAC,SAAS,GAAG,cAAc;aACjC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;aACzD,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;QAEhD,OAAO,QAAQ,CAAC;IACjB,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,eAAe,KAAK,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/ircmessageparser/parseStyle.js b/client/dist/js/helpers/ircmessageparser/parseStyle.js new file mode 100644 index 00000000..0b2faf54 --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/parseStyle.js @@ -0,0 +1,198 @@ +"use strict"; +// Styling control codes +const BOLD = "\x02"; +const COLOR = "\x03"; +const HEX_COLOR = "\x04"; +const RESET = "\x0f"; +const REVERSE = "\x16"; +const ITALIC = "\x1d"; +const UNDERLINE = "\x1f"; +const STRIKETHROUGH = "\x1e"; +const MONOSPACE = "\x11"; +// Color code matcher, with format `XX,YY` where both `XX` and `YY` are +// integers, `XX` is the text color and `YY` is an optional background color. +const colorRx = /^(\d{1,2})(?:,(\d{1,2}))?/; +// 6-char Hex color code matcher +const hexColorRx = /^([0-9a-f]{6})(?:,([0-9a-f]{6}))?/i; +// Represents all other control codes that to be ignored/filtered from the text +// This regex allows line feed character +const controlCodesRx = /[\u0000-\u0009\u000B-\u001F]/g; +// Converts a given text into an array of objects, each of them representing a +// similarly styled section of the text. Each object carries the `text`, style +// information (`bold`, `textColor`, `bgcolor`, `italic`, +// `underline`, `strikethrough`, `monospace`), and `start`/`end` cursors. +function parseStyle(text) { + const result = []; + let start = 0; + let position = 0; + // At any given time, these carry style information since last time a styling + // control code was met. + let colorCodes, + bold, + textColor, + bgColor, + hexColor, + hexBgColor, + italic, + underline, + strikethrough, + monospace; + const resetStyle = () => { + bold = false; + textColor = undefined; + bgColor = undefined; + hexColor = undefined; + hexBgColor = undefined; + italic = false; + underline = false; + strikethrough = false; + monospace = false; + }; + resetStyle(); + // When called, this "closes" the current fragment by adding an entry to the + // `result` array using the styling information set last time a control code + // was met. + const emitFragment = () => { + // Uses the text fragment starting from the last control code position up to + // the current position + const textPart = text.slice(start, position); + // Filters out all non-style related control codes present in this text + const processedText = textPart.replace(controlCodesRx, " "); + if (processedText.length) { + // Current fragment starts where the previous one ends, or at 0 if none + const fragmentStart = result.length ? result[result.length - 1].end : 0; + result.push({ + bold, + textColor, + bgColor, + hexColor, + hexBgColor, + italic, + underline, + strikethrough, + monospace, + text: processedText, + start: fragmentStart, + end: fragmentStart + processedText.length, + }); + } + // Now that a fragment has been "closed", the next one will start after that + start = position + 1; + }; + // This loop goes through each character of the given text one by one by + // bumping the `position` cursor. Every time a new special "styling" character + // is met, an object gets created (with `emitFragment()`)information on text + // encountered since the previous styling character. + while (position < text.length) { + switch (text[position]) { + case RESET: + emitFragment(); + resetStyle(); + break; + // Meeting a BOLD character means that the ongoing text is either going to + // be in bold or that the previous one was in bold and the following one + // must be reset. + // This same behavior applies to COLOR, REVERSE, ITALIC, and UNDERLINE. + case BOLD: + emitFragment(); + bold = !bold; + break; + case COLOR: + emitFragment(); + // Go one step further to find the corresponding color + colorCodes = text.slice(position + 1).match(colorRx); + if (colorCodes) { + textColor = Number(colorCodes[1]); + if (colorCodes[2]) { + bgColor = Number(colorCodes[2]); + } + // Color code length is > 1, so bump the current position cursor by as + // much (and reset the start cursor for the current text block as well) + position += colorCodes[0].length; + start = position + 1; + } else { + // If no color codes were found, toggles back to no colors (like BOLD). + textColor = undefined; + bgColor = undefined; + } + break; + case HEX_COLOR: + emitFragment(); + colorCodes = text.slice(position + 1).match(hexColorRx); + if (colorCodes) { + hexColor = colorCodes[1].toUpperCase(); + if (colorCodes[2]) { + hexBgColor = colorCodes[2].toUpperCase(); + } + // Color code length is > 1, so bump the current position cursor by as + // much (and reset the start cursor for the current text block as well) + position += colorCodes[0].length; + start = position + 1; + } else { + // If no color codes were found, toggles back to no colors (like BOLD). + hexColor = undefined; + hexBgColor = undefined; + } + break; + case REVERSE: { + emitFragment(); + const tmp = bgColor; + bgColor = textColor; + textColor = tmp; + break; + } + case ITALIC: + emitFragment(); + italic = !italic; + break; + case UNDERLINE: + emitFragment(); + underline = !underline; + break; + case STRIKETHROUGH: + emitFragment(); + strikethrough = !strikethrough; + break; + case MONOSPACE: + emitFragment(); + monospace = !monospace; + break; + } + // Evaluate the next character at the next iteration + position += 1; + } + // The entire text has been parsed, so we finalize the current text fragment. + emitFragment(); + return result; +} +const properties = [ + "bold", + "textColor", + "bgColor", + "hexColor", + "hexBgColor", + "italic", + "underline", + "strikethrough", + "monospace", +]; +function prepare(text) { + return ( + parseStyle(text) + // This optimizes fragments by combining them together when all their values + // for the properties defined above are equal. + .reduce((prev, curr) => { + if (prev.length) { + const lastEntry = prev[prev.length - 1]; + if (properties.every((key) => curr[key] === lastEntry[key])) { + lastEntry.text += curr.text; + lastEntry.end += curr.text.length; + return prev; + } + } + return prev.concat([curr]); + }, []) + ); +} +export default prepare; +//# sourceMappingURL=parseStyle.js.map diff --git a/client/dist/js/helpers/ircmessageparser/parseStyle.js.map b/client/dist/js/helpers/ircmessageparser/parseStyle.js.map new file mode 100644 index 00000000..92b24a6d --- /dev/null +++ b/client/dist/js/helpers/ircmessageparser/parseStyle.js.map @@ -0,0 +1 @@ +{"version":3,"file":"parseStyle.js","sourceRoot":"","sources":["../../../../js/helpers/ircmessageparser/parseStyle.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,wBAAwB;AACxB,MAAM,IAAI,GAAG,MAAM,CAAC;AACpB,MAAM,KAAK,GAAG,MAAM,CAAC;AACrB,MAAM,SAAS,GAAG,MAAM,CAAC;AACzB,MAAM,KAAK,GAAG,MAAM,CAAC;AACrB,MAAM,OAAO,GAAG,MAAM,CAAC;AACvB,MAAM,MAAM,GAAG,MAAM,CAAC;AACtB,MAAM,SAAS,GAAG,MAAM,CAAC;AACzB,MAAM,aAAa,GAAG,MAAM,CAAC;AAC7B,MAAM,SAAS,GAAG,MAAM,CAAC;AAEzB,uEAAuE;AACvE,6EAA6E;AAC7E,MAAM,OAAO,GAAG,2BAA2B,CAAC;AAE5C,gCAAgC;AAChC,MAAM,UAAU,GAAG,oCAAoC,CAAC;AAExD,+EAA+E;AAC/E,wCAAwC;AACxC,MAAM,cAAc,GAAG,+BAA+B,CAAC;AAEvD,8EAA8E;AAC9E,8EAA8E;AAC9E,yDAAyD;AACzD,yEAAyE;AACzE,SAAS,UAAU,CAAC,IAAI;IACvB,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,6EAA6E;IAC7E,wBAAwB;IACxB,IAAI,UAAU,EACb,IAAI,EACJ,SAAS,EACT,OAAO,EACP,QAAQ,EACR,UAAU,EACV,MAAM,EACN,SAAS,EACT,aAAa,EACb,SAAS,CAAC;IAEX,MAAM,UAAU,GAAG,GAAG,EAAE;QACvB,IAAI,GAAG,KAAK,CAAC;QACb,SAAS,GAAG,SAAS,CAAC;QACtB,OAAO,GAAG,SAAS,CAAC;QACpB,QAAQ,GAAG,SAAS,CAAC;QACrB,UAAU,GAAG,SAAS,CAAC;QACvB,MAAM,GAAG,KAAK,CAAC;QACf,SAAS,GAAG,KAAK,CAAC;QAClB,aAAa,GAAG,KAAK,CAAC;QACtB,SAAS,GAAG,KAAK,CAAC;IACnB,CAAC,CAAC;IAEF,UAAU,EAAE,CAAC;IAEb,4EAA4E;IAC5E,4EAA4E;IAC5E,WAAW;IACX,MAAM,YAAY,GAAG,GAAG,EAAE;QACzB,4EAA4E;QAC5E,uBAAuB;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAE7C,uEAAuE;QACvE,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QAE5D,IAAI,aAAa,CAAC,MAAM,EAAE;YACzB,uEAAuE;YACvE,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAExE,MAAM,CAAC,IAAI,CAAC;gBACX,IAAI;gBACJ,SAAS;gBACT,OAAO;gBACP,QAAQ;gBACR,UAAU;gBACV,MAAM;gBACN,SAAS;gBACT,aAAa;gBACb,SAAS;gBACT,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,aAAa;gBACpB,GAAG,EAAE,aAAa,GAAG,aAAa,CAAC,MAAM;aACzC,CAAC,CAAC;SACH;QAED,4EAA4E;QAC5E,KAAK,GAAG,QAAQ,GAAG,CAAC,CAAC;IACtB,CAAC,CAAC;IAEF,wEAAwE;IACxE,8EAA8E;IAC9E,4EAA4E;IAC5E,oDAAoD;IACpD,OAAO,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE;QAC9B,QAAQ,IAAI,CAAC,QAAQ,CAAC,EAAE;YACvB,KAAK,KAAK;gBACT,YAAY,EAAE,CAAC;gBACf,UAAU,EAAE,CAAC;gBACb,MAAM;YAEP,0EAA0E;YAC1E,wEAAwE;YACxE,iBAAiB;YACjB,uEAAuE;YACvE,KAAK,IAAI;gBACR,YAAY,EAAE,CAAC;gBACf,IAAI,GAAG,CAAC,IAAI,CAAC;gBACb,MAAM;YAEP,KAAK,KAAK;gBACT,YAAY,EAAE,CAAC;gBAEf,sDAAsD;gBACtD,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAErD,IAAI,UAAU,EAAE;oBACf,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;oBAElC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE;wBAClB,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;qBAChC;oBAED,sEAAsE;oBACtE,uEAAuE;oBACvE,QAAQ,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;oBACjC,KAAK,GAAG,QAAQ,GAAG,CAAC,CAAC;iBACrB;qBAAM;oBACN,uEAAuE;oBACvE,SAAS,GAAG,SAAS,CAAC;oBACtB,OAAO,GAAG,SAAS,CAAC;iBACpB;gBAED,MAAM;YAEP,KAAK,SAAS;gBACb,YAAY,EAAE,CAAC;gBAEf,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAExD,IAAI,UAAU,EAAE;oBACf,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;oBAEvC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE;wBAClB,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;qBACzC;oBAED,sEAAsE;oBACtE,uEAAuE;oBACvE,QAAQ,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;oBACjC,KAAK,GAAG,QAAQ,GAAG,CAAC,CAAC;iBACrB;qBAAM;oBACN,uEAAuE;oBACvE,QAAQ,GAAG,SAAS,CAAC;oBACrB,UAAU,GAAG,SAAS,CAAC;iBACvB;gBAED,MAAM;YAEP,KAAK,OAAO,CAAC,CAAC;gBACb,YAAY,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,OAAO,CAAC;gBACpB,OAAO,GAAG,SAAS,CAAC;gBACpB,SAAS,GAAG,GAAG,CAAC;gBAChB,MAAM;aACN;YAED,KAAK,MAAM;gBACV,YAAY,EAAE,CAAC;gBACf,MAAM,GAAG,CAAC,MAAM,CAAC;gBACjB,MAAM;YAEP,KAAK,SAAS;gBACb,YAAY,EAAE,CAAC;gBACf,SAAS,GAAG,CAAC,SAAS,CAAC;gBACvB,MAAM;YAEP,KAAK,aAAa;gBACjB,YAAY,EAAE,CAAC;gBACf,aAAa,GAAG,CAAC,aAAa,CAAC;gBAC/B,MAAM;YAEP,KAAK,SAAS;gBACb,YAAY,EAAE,CAAC;gBACf,SAAS,GAAG,CAAC,SAAS,CAAC;gBACvB,MAAM;SACP;QAED,oDAAoD;QACpD,QAAQ,IAAI,CAAC,CAAC;KACd;IAED,6EAA6E;IAC7E,YAAY,EAAE,CAAC;IAEf,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,GAAG;IAClB,MAAM;IACN,WAAW;IACX,SAAS;IACT,UAAU;IACV,YAAY;IACZ,QAAQ;IACR,WAAW;IACX,eAAe;IACf,WAAW;CACX,CAAC;AAEF,SAAS,OAAO,CAAC,IAAI;IACpB,OAAO,CACN,UAAU,CAAC,IAAI,CAAC;QACf,4EAA4E;QAC5E,8CAA8C;SAC7C,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;QACtB,IAAI,IAAI,CAAC,MAAM,EAAE;YAChB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAExC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE;gBAC5D,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC;gBAC5B,SAAS,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;gBAClC,OAAO,IAAI,CAAC;aACZ;SACD;QAED,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5B,CAAC,EAAE,EAAE,CAAC,CACP,CAAC;AACH,CAAC;AAED,eAAe,OAAO,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/isChannelCollapsed.js b/client/dist/js/helpers/isChannelCollapsed.js new file mode 100644 index 00000000..d0b6d3ff --- /dev/null +++ b/client/dist/js/helpers/isChannelCollapsed.js @@ -0,0 +1,12 @@ +"use strict"; +import store from "../store"; +export default (network, channel) => { + if (!network.isCollapsed || channel.highlight || channel.type === "lobby") { + return false; + } + if (store.state.activeChannel && channel === store.state.activeChannel.channel) { + return false; + } + return true; +}; +//# sourceMappingURL=isChannelCollapsed.js.map diff --git a/client/dist/js/helpers/isChannelCollapsed.js.map b/client/dist/js/helpers/isChannelCollapsed.js.map new file mode 100644 index 00000000..b56884ca --- /dev/null +++ b/client/dist/js/helpers/isChannelCollapsed.js.map @@ -0,0 +1 @@ +{"version":3,"file":"isChannelCollapsed.js","sourceRoot":"","sources":["../../../js/helpers/isChannelCollapsed.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,KAAK,MAAM,UAAU,CAAC;AAE7B,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE;IACnC,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE;QAC1E,OAAO,KAAK,CAAC;KACb;IAED,IAAI,KAAK,CAAC,KAAK,CAAC,aAAa,IAAI,OAAO,KAAK,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE;QAC/E,OAAO,KAAK,CAAC;KACb;IAED,OAAO,IAAI,CAAC;AACb,CAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/isIgnoredKeybind.js b/client/dist/js/helpers/isIgnoredKeybind.js new file mode 100644 index 00000000..47e710e8 --- /dev/null +++ b/client/dist/js/helpers/isIgnoredKeybind.js @@ -0,0 +1,11 @@ +"use strict"; +export default (event) => { + if (event.target.tagName !== "TEXTAREA" && event.target.tagName !== "INPUT") { + return false; + } + // If focus is in a textarea, do not handle keybinds if user has typed anything + // This is done to prevent keyboard layout binds conflicting with ours + // For example alt+shift+left on macos selects a word + return !!event.target.value; +}; +//# sourceMappingURL=isIgnoredKeybind.js.map diff --git a/client/dist/js/helpers/isIgnoredKeybind.js.map b/client/dist/js/helpers/isIgnoredKeybind.js.map new file mode 100644 index 00000000..1a66dd7d --- /dev/null +++ b/client/dist/js/helpers/isIgnoredKeybind.js.map @@ -0,0 +1 @@ +{"version":3,"file":"isIgnoredKeybind.js","sourceRoot":"","sources":["../../../js/helpers/isIgnoredKeybind.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,eAAe,CAAC,KAAK,EAAE,EAAE;IACxB,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,KAAK,OAAO,EAAE;QAC5E,OAAO,KAAK,CAAC;KACb;IAED,+EAA+E;IAC/E,sEAAsE;IACtE,qDAAqD;IACrD,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;AAC7B,CAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/listenForTwoFingerSwipes.js b/client/dist/js/helpers/listenForTwoFingerSwipes.js new file mode 100644 index 00000000..249fb96a --- /dev/null +++ b/client/dist/js/helpers/listenForTwoFingerSwipes.js @@ -0,0 +1,85 @@ +"use strict"; +import distance from "./distance"; +// onTwoFingerSwipe will be called with a cardinal direction ("n", "e", "s" or +// "w") as its only argument. +function listenForTwoFingerSwipes(onTwoFingerSwipe) { + let history = []; + document.body.addEventListener( + "touchmove", + function (event) { + if (event.touches.length !== 2) { + return; + } + const a = event.touches.item(0); + const b = event.touches.item(1); + const timestamp = window.performance.now(); + const center = [(a.screenX + b.screenX) / 2, (a.screenY + b.screenY) / 2]; + if (history.length > 0) { + const last = history[history.length - 1]; + const centersAreEqual = + last.center[0] === center[0] && last.center[1] === center[1]; + if (last.timestamp === timestamp || centersAreEqual) { + // Touches with the same timestamps or center don't help us + // see the speed of movement. Ignore them. + return; + } + } + history.push({timestamp, center}); + }, + {passive: true} + ); + document.body.addEventListener( + "touchend", + function (event) { + if (event.touches.length >= 2) { + return; + } + try { + const direction = getSwipe(history); + if (direction) { + onTwoFingerSwipe(direction); + } + } finally { + history = []; + } + }, + {passive: true} + ); + document.body.addEventListener( + "touchcancel", + function () { + history = []; + }, + {passive: true} + ); +} +// Returns the cardinal direction of the swipe or null if there is no swipe. +function getSwipe(hist) { + // Speed is in pixels/millisecond. Must be maintained throughout swipe. + const MIN_SWIPE_SPEED = 0.2; + if (hist.length < 2) { + return null; + } + for (let i = 1; i < hist.length; ++i) { + const previous = hist[i - 1]; + const current = hist[i]; + const speed = + distance(previous.center, current.center) / + Math.abs(previous.timestamp - current.timestamp); + if (speed < MIN_SWIPE_SPEED) { + return null; + } + } + return getCardinalDirection(hist[0].center, hist[hist.length - 1].center); +} +function getCardinalDirection([x1, y1], [x2, y2]) { + // If θ is the angle of the vector then this is tan(θ) + const tangent = (y2 - y1) / (x2 - x1); + // All values of |tan(-45° to 45°)| are less than 1, same for 145° to 225° + if (Math.abs(tangent) < 1) { + return x1 < x2 ? "e" : "w"; + } + return y1 < y2 ? "s" : "n"; +} +export default listenForTwoFingerSwipes; +//# sourceMappingURL=listenForTwoFingerSwipes.js.map diff --git a/client/dist/js/helpers/listenForTwoFingerSwipes.js.map b/client/dist/js/helpers/listenForTwoFingerSwipes.js.map new file mode 100644 index 00000000..44adb07b --- /dev/null +++ b/client/dist/js/helpers/listenForTwoFingerSwipes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"listenForTwoFingerSwipes.js","sourceRoot":"","sources":["../../../js/helpers/listenForTwoFingerSwipes.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/client/dist/js/helpers/localetime.js b/client/dist/js/helpers/localetime.js new file mode 100644 index 00000000..a42f3f8d --- /dev/null +++ b/client/dist/js/helpers/localetime.js @@ -0,0 +1,4 @@ +"use strict"; +import dayjs from "dayjs"; +export default (time) => dayjs(time).format("D MMMM YYYY, HH:mm:ss"); +//# sourceMappingURL=localetime.js.map diff --git a/client/dist/js/helpers/localetime.js.map b/client/dist/js/helpers/localetime.js.map new file mode 100644 index 00000000..8d3e38b1 --- /dev/null +++ b/client/dist/js/helpers/localetime.js.map @@ -0,0 +1 @@ +{"version":3,"file":"localetime.js","sourceRoot":"","sources":["../../../js/helpers/localetime.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/parse.js b/client/dist/js/helpers/parse.js new file mode 100644 index 00000000..86a7e178 --- /dev/null +++ b/client/dist/js/helpers/parse.js @@ -0,0 +1,177 @@ +"use strict"; +import parseStyle from "./ircmessageparser/parseStyle"; +import findChannels from "./ircmessageparser/findChannels"; +import {findLinks} from "./ircmessageparser/findLinks"; +import findEmoji from "./ircmessageparser/findEmoji"; +import findNames from "./ircmessageparser/findNames"; +import merge from "./ircmessageparser/merge"; +import emojiMap from "./fullnamemap.json"; +import LinkPreviewToggle from "../../components/LinkPreviewToggle.vue"; +import LinkPreviewFileSize from "../../components/LinkPreviewFileSize.vue"; +import InlineChannel from "../../components/InlineChannel.vue"; +import Username from "../../components/Username.vue"; +const emojiModifiersRegex = /[\u{1f3fb}-\u{1f3ff}]|\u{fe0f}/gu; +// Create an HTML `span` with styling information for a given fragment +function createFragment(fragment, createElement) { + const classes = []; + if (fragment.bold) { + classes.push("irc-bold"); + } + if (fragment.textColor !== undefined) { + classes.push("irc-fg" + fragment.textColor); + } + if (fragment.bgColor !== undefined) { + classes.push("irc-bg" + fragment.bgColor); + } + if (fragment.italic) { + classes.push("irc-italic"); + } + if (fragment.underline) { + classes.push("irc-underline"); + } + if (fragment.strikethrough) { + classes.push("irc-strikethrough"); + } + if (fragment.monospace) { + classes.push("irc-monospace"); + } + const data = {}; + let hasData = false; + if (classes.length > 0) { + hasData = true; + data.class = classes; + } + if (fragment.hexColor) { + hasData = true; + data.style = { + color: `#${fragment.hexColor}`, + }; + if (fragment.hexBgColor) { + data.style["background-color"] = `#${fragment.hexBgColor}`; + } + } + return hasData ? createElement("span", data, fragment.text) : fragment.text; +} +// Transform an IRC message potentially filled with styling control codes, URLs, +// nicknames, and channels into a string of HTML elements to display on the client. +function parse(createElement, text, message = undefined, network = undefined) { + // Extract the styling information and get the plain text version from it + const styleFragments = parseStyle(text); + const cleanText = styleFragments.map((fragment) => fragment.text).join(""); + // On the plain text, find channels and URLs, returned as "parts". Parts are + // arrays of objects containing start and end markers, as well as metadata + // depending on what was found (channel or link). + const channelPrefixes = network ? network.serverOptions.CHANTYPES : ["#", "&"]; + const userModes = network?.serverOptions?.PREFIX.symbols || ["!", "@", "%", "+"]; + const channelParts = findChannels(cleanText, channelPrefixes, userModes); + const linkParts = findLinks(cleanText); + const emojiParts = findEmoji(cleanText); + const nameParts = findNames(cleanText, message ? message.users || [] : []); + const parts = channelParts.concat(linkParts).concat(emojiParts).concat(nameParts); + // The channel the message belongs to might not exist if the user isn't joined to it. + const messageChannel = message ? message.channel : null; + // Merge the styling information with the channels / URLs / nicks / text objects and + // generate HTML strings with the resulting fragments + return merge(parts, styleFragments, cleanText).map((textPart) => { + const fragments = textPart.fragments.map((fragment) => + createFragment(fragment, createElement) + ); + // Wrap these potentially styled fragments with links and channel buttons + if (textPart.link) { + const preview = + message && + message.previews && + message.previews.find((p) => p.link === textPart.link); + const link = createElement( + "a", + { + attrs: { + href: textPart.link, + dir: preview ? null : "auto", + target: "_blank", + rel: "noopener", + }, + }, + fragments + ); + if (!preview) { + return link; + } + const linkEls = [link]; + if (preview.size > 0) { + linkEls.push( + createElement(LinkPreviewFileSize, { + props: { + size: preview.size, + }, + }) + ); + } + linkEls.push( + createElement(LinkPreviewToggle, { + props: { + link: preview, + }, + }) + ); + // We wrap the link, size, and the toggle button into + // to correctly keep the left-to-right order of these elements + return createElement( + "span", + { + attrs: { + dir: "auto", + }, + }, + linkEls + ); + } else if (textPart.channel) { + return createElement( + InlineChannel, + { + props: { + channel: textPart.channel, + }, + }, + fragments + ); + } else if (textPart.emoji) { + const emojiWithoutModifiers = textPart.emoji.replace(emojiModifiersRegex, ""); + const title = emojiMap[emojiWithoutModifiers] + ? `Emoji: ${emojiMap[emojiWithoutModifiers]}` + : null; + return createElement( + "span", + { + class: ["emoji"], + attrs: { + role: "img", + "aria-label": title, + title: title, + }, + }, + fragments + ); + } else if (textPart.nick) { + return createElement( + Username, + { + props: { + user: { + nick: textPart.nick, + }, + channel: messageChannel, + network, + }, + attrs: { + dir: "auto", + }, + }, + fragments + ); + } + return fragments; + }); +} +export default parse; +//# sourceMappingURL=parse.js.map diff --git a/client/dist/js/helpers/parse.js.map b/client/dist/js/helpers/parse.js.map new file mode 100644 index 00000000..66912fa8 --- /dev/null +++ b/client/dist/js/helpers/parse.js.map @@ -0,0 +1 @@ +{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../js/helpers/parse.js"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/client/dist/js/helpers/parseIrcUri.js b/client/dist/js/helpers/parseIrcUri.js new file mode 100644 index 00000000..909eacb1 --- /dev/null +++ b/client/dist/js/helpers/parseIrcUri.js @@ -0,0 +1,43 @@ +"use strict"; +export default (stringUri) => { + const data = {}; + try { + // https://tools.ietf.org/html/draft-butcher-irc-url-04 + const uri = new URL(stringUri); + // Replace protocol with a "special protocol" (that's what it's called in WHATWG spec) + // So that the uri can be properly parsed + if (uri.protocol === "irc:") { + uri.protocol = "http:"; + if (!uri.port) { + uri.port = 6667; + } + data.tls = false; + } else if (uri.protocol === "ircs:") { + uri.protocol = "https:"; + if (!uri.port) { + uri.port = 6697; + } + data.tls = true; + } else { + return; + } + if (!uri.hostname) { + return {}; + } + data.host = data.name = uri.hostname; + data.port = uri.port; + let channel = ""; + if (uri.pathname.length > 1) { + channel = uri.pathname.substr(1); // Remove slash + } + if (uri.hash.length > 1) { + channel += uri.hash; + } + // We don't split channels or append # here because the connect window takes care of that + data.join = channel; + } catch (e) { + // do nothing on invalid uri + } + return data; +}; +//# sourceMappingURL=parseIrcUri.js.map diff --git a/client/dist/js/helpers/parseIrcUri.js.map b/client/dist/js/helpers/parseIrcUri.js.map new file mode 100644 index 00000000..8735220a --- /dev/null +++ b/client/dist/js/helpers/parseIrcUri.js.map @@ -0,0 +1 @@ +{"version":3,"file":"parseIrcUri.js","sourceRoot":"","sources":["../../../js/helpers/parseIrcUri.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,eAAe,CAAC,SAAS,EAAE,EAAE;IAC5B,MAAM,IAAI,GAAG,EAAE,CAAC;IAEhB,IAAI;QACH,uDAAuD;QACvD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QAE/B,sFAAsF;QACtF,yCAAyC;QACzC,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE;YAC5B,GAAG,CAAC,QAAQ,GAAG,OAAO,CAAC;YAEvB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;gBACd,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;aAChB;YAED,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC;SACjB;aAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE;YACpC,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAExB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;gBACd,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;aAChB;YAED,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;SAChB;aAAM;YACN,OAAO;SACP;QAED,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE;YAClB,OAAO,EAAE,CAAC;SACV;QAED,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QAErB,IAAI,OAAO,GAAG,EAAE,CAAC;QAEjB,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;YAC5B,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe;SACjD;QAED,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;YACxB,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC;SACpB;QAED,yFAAyF;QACzF,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC;KACpB;IAAC,OAAO,CAAC,EAAE;QACX,4BAA4B;KAC5B;IAED,OAAO,IAAI,CAAC;AACb,CAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/helpers/roundBadgeNumber.js b/client/dist/js/helpers/roundBadgeNumber.js new file mode 100644 index 00000000..d8050c60 --- /dev/null +++ b/client/dist/js/helpers/roundBadgeNumber.js @@ -0,0 +1,8 @@ +"use strict"; +export default (count) => { + if (count < 1000) { + return count.toString(); + } + return (count / 1000).toFixed(2).slice(0, -1) + "k"; +}; +//# sourceMappingURL=roundBadgeNumber.js.map diff --git a/client/dist/js/helpers/roundBadgeNumber.js.map b/client/dist/js/helpers/roundBadgeNumber.js.map new file mode 100644 index 00000000..3c77c631 --- /dev/null +++ b/client/dist/js/helpers/roundBadgeNumber.js.map @@ -0,0 +1 @@ +{"version":3,"file":"roundBadgeNumber.js","sourceRoot":"","sources":["../../../js/helpers/roundBadgeNumber.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,eAAe,CAAC,KAAK,EAAE,EAAE;IACxB,IAAI,KAAK,GAAG,IAAI,EAAE;QACjB,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;KACxB;IAED,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACrD,CAAC,CAAC"} \ No newline at end of file diff --git a/client/dist/js/keybinds.js b/client/dist/js/keybinds.js new file mode 100644 index 00000000..7263ffd7 --- /dev/null +++ b/client/dist/js/keybinds.js @@ -0,0 +1,188 @@ +"use strict"; +import Mousetrap from "mousetrap"; +import store from "./store"; +import {switchToChannel, router, navigate} from "./router"; +import isChannelCollapsed from "./helpers/isChannelCollapsed"; +import isIgnoredKeybind from "./helpers/isIgnoredKeybind"; +import listenForTwoFingerSwipes from "./helpers/listenForTwoFingerSwipes"; +// Switch to the next/previous window in the channel list. +Mousetrap.bind(["alt+up", "alt+down"], function (e, keys) { + if (isIgnoredKeybind(e)) { + return true; + } + navigateWindow(keys.split("+").pop() === "up" ? -1 : 1); + return false; +}); +listenForTwoFingerSwipes(function (cardinalDirection) { + if (cardinalDirection === "e" || cardinalDirection === "w") { + navigateWindow(cardinalDirection === "e" ? -1 : 1); + } +}); +function navigateWindow(direction) { + if (store.state.networks.length === 0) { + return; + } + const flatChannels = []; + let index = -1; + for (const network of store.state.networks) { + for (const channel of network.channels) { + if (isChannelCollapsed(network, channel)) { + continue; + } + if ( + index === -1 && + store.state.activeChannel && + store.state.activeChannel.channel === channel + ) { + index = flatChannels.length; + } + flatChannels.push(channel); + } + } + // Circular array, and a modulo bug workaround because in JS it stays negative + const length = flatChannels.length; + index = (((index + direction) % length) + length) % length; + jumpToChannel(flatChannels[index]); +} +// Switch to the next/previous lobby in the channel list +Mousetrap.bind(["alt+shift+up", "alt+shift+down"], function (e, keys) { + if (isIgnoredKeybind(e)) { + return true; + } + const length = store.state.networks.length; + if (length === 0) { + return false; + } + const direction = keys.split("+").pop() === "up" ? -1 : 1; + let index = 0; + // If we're in another window, jump to first lobby + if (store.state.activeChannel) { + index = store.state.networks.findIndex((n) => n === store.state.activeChannel.network); + // If we're in a channel, and it's not the lobby, jump to lobby of this network when going up + if (direction !== -1 || store.state.activeChannel.channel.type === "lobby") { + index = (((index + direction) % length) + length) % length; + } + } + jumpToChannel(store.state.networks[index].channels[0]); + return false; +}); +// Jump to the first window with a highlight in it, or the first with unread +// activity if there are none with highlights. +Mousetrap.bind(["alt+a"], function (e) { + if (isIgnoredKeybind(e)) { + return true; + } + let targetChannel; + outer_loop: for (const network of store.state.networks) { + for (const chan of network.channels) { + if (chan.highlight) { + targetChannel = chan; + break outer_loop; + } + if (chan.unread && !targetChannel) { + targetChannel = chan; + } + } + } + if (targetChannel) { + jumpToChannel(targetChannel); + } + return false; +}); +// Show the help menu. +Mousetrap.bind(["alt+/"], function (e) { + if (isIgnoredKeybind(e)) { + return true; + } + navigate("Help"); + return false; +}); +function jumpToChannel(targetChannel) { + switchToChannel(targetChannel); + const element = document.querySelector( + `#sidebar .channel-list-item[aria-controls="#chan-${targetChannel.id}"]` + ); + if (element) { + scrollIntoViewNicely(element); + } +} +// Ignored keys which should not automatically focus the input bar +const ignoredKeys = { + 8: true, + 9: true, + 12: true, + 16: true, + 17: true, + 18: true, + 19: true, + 20: true, + 27: true, + 35: true, + 36: true, + 37: true, + 38: true, + 39: true, + 40: true, + 45: true, + 46: true, + 112: true, + 113: true, + 114: true, + 115: true, + 116: true, + 117: true, + 118: true, + 119: true, + 120: true, + 121: true, + 122: true, + 123: true, + 144: true, + 145: true, + 224: true, // Meta +}; +document.addEventListener("keydown", (e) => { + // Allow navigating back to the previous page when on the help screen. + if (e.key === "Escape" && router.currentRoute.name === "Help") { + router.go(-1); + return; + } + // Ignore any key that uses alt modifier + // Ignore keys defined above + if (e.altKey || ignoredKeys[e.which]) { + return; + } + // Ignore all ctrl keys except for ctrl+v to allow pasting + if ((e.ctrlKey || e.metaKey) && e.which !== 86) { + return; + } + // Redirect pagedown/pageup keys to messages container so it scrolls + if (e.which === 33 || e.which === 34) { + const chat = document.querySelector(".window .chat-content .chat"); + if (chat) { + chat.focus(); + } + return; + } + const tagName = e.target.tagName; + // Ignore if we're already typing into or