mirror of
https://github.com/thelounge/thelounge.git
synced 2024-05-19 14:46:36 +02:00
ts progress
This commit is contained in:
parent
291ac3e903
commit
5bb94d6428
|
@ -3,7 +3,7 @@ root: true
|
|||
|
||||
parserOptions:
|
||||
ecmaVersion: 2022
|
||||
parser: "babel-eslint"
|
||||
parser: "@babel/eslint-parser",
|
||||
|
||||
env:
|
||||
es6: true
|
||||
|
|
11
client/dist/components/MessageTypes/index.js
vendored
Normal file
11
client/dist/components/MessageTypes/index.js
vendored
Normal file
|
@ -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
|
1
client/dist/components/MessageTypes/index.js.map
vendored
Normal file
1
client/dist/components/MessageTypes/index.js.map
vendored
Normal file
|
@ -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"}
|
10
client/dist/js/auth.js
vendored
Normal file
10
client/dist/js/auth.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/auth.js.map
vendored
Normal file
1
client/dist/js/auth.js.map
vendored
Normal file
|
@ -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"}
|
280
client/dist/js/autocompletion.js
vendored
Normal file
280
client/dist/js/autocompletion.js
vendored
Normal file
|
@ -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 `<span class="emoji">${emojiMap[original]}</span> ${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: "<b>",
|
||||
post: "</b>",
|
||||
}).rendered,
|
||||
];
|
||||
}
|
||||
return i;
|
||||
});
|
||||
callback(matchingColorCodes);
|
||||
},
|
||||
template(value) {
|
||||
return `<span class="irc-fg${parseInt(value[0], 10)}">${value[1]}</span>`;
|
||||
},
|
||||
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: "<b>",
|
||||
post: "</b>",
|
||||
}).rendered,
|
||||
];
|
||||
}
|
||||
return pair;
|
||||
})
|
||||
.map((pair) => pair.concat(match[1])); // Needed to pass fg color to `template`...
|
||||
callback(matchingColorCodes);
|
||||
},
|
||||
template(value) {
|
||||
return `<span class="irc-fg${parseInt(value[2], 10)} irc-bg irc-bg${parseInt(
|
||||
value[0],
|
||||
10
|
||||
)}">${value[1]}</span>`;
|
||||
},
|
||||
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: "<b>",
|
||||
post: "</b>",
|
||||
});
|
||||
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
|
1
client/dist/js/autocompletion.js.map
vendored
Normal file
1
client/dist/js/autocompletion.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
25
client/dist/js/clipboard.js
vendored
Normal file
25
client/dist/js/clipboard.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/clipboard.js.map
vendored
Normal file
1
client/dist/js/clipboard.js.map
vendored
Normal file
|
@ -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"}
|
29
client/dist/js/commands/collapse.js
vendored
Normal file
29
client/dist/js/commands/collapse.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/commands/collapse.js.map
vendored
Normal file
1
client/dist/js/commands/collapse.js.map
vendored
Normal file
|
@ -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"}
|
29
client/dist/js/commands/expand.js
vendored
Normal file
29
client/dist/js/commands/expand.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/commands/expand.js.map
vendored
Normal file
1
client/dist/js/commands/expand.js.map
vendored
Normal file
|
@ -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"}
|
16
client/dist/js/commands/index.js
vendored
Normal file
16
client/dist/js/commands/index.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/commands/index.js.map
vendored
Normal file
1
client/dist/js/commands/index.js.map
vendored
Normal file
|
@ -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"}
|
40
client/dist/js/commands/join.js
vendored
Normal file
40
client/dist/js/commands/join.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/commands/join.js.map
vendored
Normal file
1
client/dist/js/commands/join.js.map
vendored
Normal file
|
@ -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"}
|
20
client/dist/js/commands/search.js
vendored
Normal file
20
client/dist/js/commands/search.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/commands/search.js.map
vendored
Normal file
1
client/dist/js/commands/search.js.map
vendored
Normal file
|
@ -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"}
|
35
client/dist/js/constants.js
vendored
Normal file
35
client/dist/js/constants.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/constants.js.map
vendored
Normal file
1
client/dist/js/constants.js.map
vendored
Normal file
|
@ -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"}
|
48
client/dist/js/eventbus.js
vendored
Normal file
48
client/dist/js/eventbus.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/eventbus.js.map
vendored
Normal file
1
client/dist/js/eventbus.js.map
vendored
Normal file
|
@ -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"}
|
13
client/dist/js/helpers/collapseNetwork.js
vendored
Normal file
13
client/dist/js/helpers/collapseNetwork.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/collapseNetwork.js.map
vendored
Normal file
1
client/dist/js/helpers/collapseNetwork.js.map
vendored
Normal file
|
@ -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"}
|
15
client/dist/js/helpers/colorClass.js
vendored
Normal file
15
client/dist/js/helpers/colorClass.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/colorClass.js.map
vendored
Normal file
1
client/dist/js/helpers/colorClass.js.map
vendored
Normal file
|
@ -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"}
|
378
client/dist/js/helpers/contextMenu.js
vendored
Normal file
378
client/dist/js/helpers/contextMenu.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/contextMenu.js.map
vendored
Normal file
1
client/dist/js/helpers/contextMenu.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
5
client/dist/js/helpers/distance.js
vendored
Normal file
5
client/dist/js/helpers/distance.js
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
function distance([x1, y1], [x2, y2]) {
|
||||
return Math.hypot(x1 - x2, y1 - y2);
|
||||
}
|
||||
export default distance;
|
||||
//# sourceMappingURL=distance.js.map
|
1
client/dist/js/helpers/distance.js.map
vendored
Normal file
1
client/dist/js/helpers/distance.js.map
vendored
Normal file
|
@ -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"}
|
9
client/dist/js/helpers/friendlysize.js
vendored
Normal file
9
client/dist/js/helpers/friendlysize.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/friendlysize.js.map
vendored
Normal file
1
client/dist/js/helpers/friendlysize.js.map
vendored
Normal file
|
@ -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"}
|
13
client/dist/js/helpers/ircmessageparser/anyIntersection.js
vendored
Normal file
13
client/dist/js/helpers/ircmessageparser/anyIntersection.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/ircmessageparser/anyIntersection.js.map
vendored
Normal file
1
client/dist/js/helpers/ircmessageparser/anyIntersection.js.map
vendored
Normal file
|
@ -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"}
|
5
client/dist/js/helpers/ircmessageparser/cleanIrcMessage.js
vendored
Normal file
5
client/dist/js/helpers/ircmessageparser/cleanIrcMessage.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/ircmessageparser/cleanIrcMessage.js.map
vendored
Normal file
1
client/dist/js/helpers/ircmessageparser/cleanIrcMessage.js.map
vendored
Normal file
|
@ -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"}
|
30
client/dist/js/helpers/ircmessageparser/fill.js
vendored
Normal file
30
client/dist/js/helpers/ircmessageparser/fill.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/ircmessageparser/fill.js.map
vendored
Normal file
1
client/dist/js/helpers/ircmessageparser/fill.js.map
vendored
Normal file
|
@ -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"}
|
37
client/dist/js/helpers/ircmessageparser/findChannels.js
vendored
Normal file
37
client/dist/js/helpers/ircmessageparser/findChannels.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/ircmessageparser/findChannels.js.map
vendored
Normal file
1
client/dist/js/helpers/ircmessageparser/findChannels.js.map
vendored
Normal file
|
@ -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"}
|
16
client/dist/js/helpers/ircmessageparser/findEmoji.js
vendored
Normal file
16
client/dist/js/helpers/ircmessageparser/findEmoji.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/ircmessageparser/findEmoji.js.map
vendored
Normal file
1
client/dist/js/helpers/ircmessageparser/findEmoji.js.map
vendored
Normal file
|
@ -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"}
|
|
@ -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
|
1
client/dist/js/helpers/ircmessageparser/findLinks.js.map
vendored
Normal file
1
client/dist/js/helpers/ircmessageparser/findLinks.js.map
vendored
Normal file
|
@ -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"}
|
22
client/dist/js/helpers/ircmessageparser/findNames.js
vendored
Normal file
22
client/dist/js/helpers/ircmessageparser/findNames.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/ircmessageparser/findNames.js.map
vendored
Normal file
1
client/dist/js/helpers/ircmessageparser/findNames.js.map
vendored
Normal file
|
@ -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"}
|
44
client/dist/js/helpers/ircmessageparser/merge.js
vendored
Normal file
44
client/dist/js/helpers/ircmessageparser/merge.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/ircmessageparser/merge.js.map
vendored
Normal file
1
client/dist/js/helpers/ircmessageparser/merge.js.map
vendored
Normal file
|
@ -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"}
|
198
client/dist/js/helpers/ircmessageparser/parseStyle.js
vendored
Normal file
198
client/dist/js/helpers/ircmessageparser/parseStyle.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/ircmessageparser/parseStyle.js.map
vendored
Normal file
1
client/dist/js/helpers/ircmessageparser/parseStyle.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"parseStyle.js","sourceRoot":"","sources":["../../../../js/helpers/ircmessageparser/parseStyle.js"],"names":[],"mappings":"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"}
|
12
client/dist/js/helpers/isChannelCollapsed.js
vendored
Normal file
12
client/dist/js/helpers/isChannelCollapsed.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/isChannelCollapsed.js.map
vendored
Normal file
1
client/dist/js/helpers/isChannelCollapsed.js.map
vendored
Normal file
|
@ -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"}
|
11
client/dist/js/helpers/isIgnoredKeybind.js
vendored
Normal file
11
client/dist/js/helpers/isIgnoredKeybind.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/isIgnoredKeybind.js.map
vendored
Normal file
1
client/dist/js/helpers/isIgnoredKeybind.js.map
vendored
Normal file
|
@ -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"}
|
85
client/dist/js/helpers/listenForTwoFingerSwipes.js
vendored
Normal file
85
client/dist/js/helpers/listenForTwoFingerSwipes.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/listenForTwoFingerSwipes.js.map
vendored
Normal file
1
client/dist/js/helpers/listenForTwoFingerSwipes.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"listenForTwoFingerSwipes.js","sourceRoot":"","sources":["../../../js/helpers/listenForTwoFingerSwipes.js"],"names":[],"mappings":"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"}
|
4
client/dist/js/helpers/localetime.js
vendored
Normal file
4
client/dist/js/helpers/localetime.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/localetime.js.map
vendored
Normal file
1
client/dist/js/helpers/localetime.js.map
vendored
Normal file
|
@ -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"}
|
177
client/dist/js/helpers/parse.js
vendored
Normal file
177
client/dist/js/helpers/parse.js
vendored
Normal file
|
@ -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 <span dir="auto">
|
||||
// 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
|
1
client/dist/js/helpers/parse.js.map
vendored
Normal file
1
client/dist/js/helpers/parse.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../js/helpers/parse.js"],"names":[],"mappings":"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"}
|
43
client/dist/js/helpers/parseIrcUri.js
vendored
Normal file
43
client/dist/js/helpers/parseIrcUri.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/parseIrcUri.js.map
vendored
Normal file
1
client/dist/js/helpers/parseIrcUri.js.map
vendored
Normal file
|
@ -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"}
|
8
client/dist/js/helpers/roundBadgeNumber.js
vendored
Normal file
8
client/dist/js/helpers/roundBadgeNumber.js
vendored
Normal file
|
@ -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
|
1
client/dist/js/helpers/roundBadgeNumber.js.map
vendored
Normal file
1
client/dist/js/helpers/roundBadgeNumber.js.map
vendored
Normal file
|
@ -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"}
|
188
client/dist/js/keybinds.js
vendored
Normal file
188
client/dist/js/keybinds.js
vendored
Normal file
|
@ -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 <input> or <textarea>
|
||||
if (tagName === "INPUT" || tagName === "TEXTAREA") {
|
||||
return;
|
||||
}
|
||||
const input = document.getElementById("input");
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
input.focus();
|
||||
// On enter, focus the input but do not propagate the event
|
||||
// This way, a new line is not inserted
|
||||
if (e.which === 13) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
function scrollIntoViewNicely(el) {
|
||||
// Ideally this would use behavior: "smooth", but that does not consistently work in e.g. Chrome
|
||||
// https://github.com/iamdustan/smoothscroll/issues/28#issuecomment-364061459
|
||||
el.scrollIntoView({block: "center", inline: "nearest"});
|
||||
}
|
||||
//# sourceMappingURL=keybinds.js.map
|
1
client/dist/js/keybinds.js.map
vendored
Normal file
1
client/dist/js/keybinds.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
85
client/dist/js/loading-error-handlers.js
vendored
Normal file
85
client/dist/js/loading-error-handlers.js
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* eslint strict: 0 */
|
||||
"use strict";
|
||||
/*
|
||||
* This is a separate file for two reasons:
|
||||
* 1. CSP policy does not allow inline javascript
|
||||
* 2. It has to be a small javascript executed before all other scripts,
|
||||
* so that the timeout can be triggered while slow JS is loading
|
||||
*/
|
||||
(function () {
|
||||
const msg = document.getElementById("loading-page-message");
|
||||
msg.textContent = "Loading the app…";
|
||||
document
|
||||
.getElementById("loading-reload")
|
||||
.addEventListener("click", () => location.reload(true));
|
||||
const displayReload = () => {
|
||||
const loadingReload = document.getElementById("loading-reload");
|
||||
if (loadingReload) {
|
||||
loadingReload.style.visibility = "visible";
|
||||
}
|
||||
};
|
||||
const loadingSlowTimeout = setTimeout(() => {
|
||||
const loadingSlow = document.getElementById("loading-slow");
|
||||
loadingSlow.style.visibility = "visible";
|
||||
displayReload();
|
||||
}, 5000);
|
||||
const errorHandler = (e) => {
|
||||
msg.textContent = "An error has occurred that prevented the client from loading correctly.";
|
||||
const summary = document.createElement("summary");
|
||||
summary.textContent = "More details";
|
||||
const data = document.createElement("pre");
|
||||
data.textContent = e.message; // e is an ErrorEvent
|
||||
const info = document.createElement("p");
|
||||
info.textContent = "Open the developer tools of your browser for more information.";
|
||||
const details = document.createElement("details");
|
||||
details.appendChild(summary);
|
||||
details.appendChild(data);
|
||||
details.appendChild(info);
|
||||
msg.parentNode.insertBefore(details, msg.nextSibling);
|
||||
window.clearTimeout(loadingSlowTimeout);
|
||||
displayReload();
|
||||
};
|
||||
window.addEventListener("error", errorHandler);
|
||||
window.g_TheLoungeRemoveLoading = () => {
|
||||
delete window.g_TheLoungeRemoveLoading;
|
||||
window.clearTimeout(loadingSlowTimeout);
|
||||
window.removeEventListener("error", errorHandler);
|
||||
document.getElementById("loading").remove();
|
||||
};
|
||||
// Apply user theme as soon as possible, before any other code loads
|
||||
// This prevents flash of white while other code loads and socket connects
|
||||
try {
|
||||
const userSettings = JSON.parse(localStorage.getItem("settings"));
|
||||
const themeEl = document.getElementById("theme");
|
||||
if (
|
||||
typeof userSettings.theme === "string" &&
|
||||
themeEl.dataset.serverTheme !== userSettings.theme
|
||||
) {
|
||||
themeEl.attributes.href.value = `themes/${userSettings.theme}.css`;
|
||||
}
|
||||
if (
|
||||
typeof userSettings.userStyles === "string" &&
|
||||
!/[?&]nocss/.test(window.location.search)
|
||||
) {
|
||||
document.getElementById("user-specified-css").innerHTML = userSettings.userStyles;
|
||||
}
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
// Trigger early service worker registration
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.register("service-worker.js");
|
||||
// Handler for messages coming from the service worker
|
||||
const messageHandler = (event) => {
|
||||
if (event.data.type === "fetch-error") {
|
||||
errorHandler({
|
||||
message: `Service worker failed to fetch an url: ${event.data.message}`,
|
||||
});
|
||||
// Display only one fetch error
|
||||
navigator.serviceWorker.removeEventListener("message", messageHandler);
|
||||
}
|
||||
};
|
||||
navigator.serviceWorker.addEventListener("message", messageHandler);
|
||||
}
|
||||
})();
|
||||
//# sourceMappingURL=loading-error-handlers.js.map
|
1
client/dist/js/loading-error-handlers.js.map
vendored
Normal file
1
client/dist/js/loading-error-handlers.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"loading-error-handlers.js","sourceRoot":"","sources":["../../js/loading-error-handlers.js"],"names":[],"mappings":"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"}
|
42
client/dist/js/localStorage.js
vendored
Normal file
42
client/dist/js/localStorage.js
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
"use strict";
|
||||
// This is a simple localStorage wrapper because browser can throw errors
|
||||
// in different situations, including:
|
||||
// - Unable to store data if storage is full
|
||||
// - Local storage is blocked if "third-party cookies and site data" is disabled
|
||||
//
|
||||
// For more details, see:
|
||||
// https://stackoverflow.com/q/14555347/1935861
|
||||
// https://github.com/thelounge/thelounge/issues/2699
|
||||
// https://www.chromium.org/for-testers/bug-reporting-guidelines/uncaught-securityerror-failed-to-read-the-localstorage-property-from-window-access-is-denied-for-this-document
|
||||
export default {
|
||||
set(key, value) {
|
||||
try {
|
||||
window.localStorage.setItem(key, value);
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
},
|
||||
get(key) {
|
||||
try {
|
||||
return window.localStorage.getItem(key);
|
||||
} catch (e) {
|
||||
// Return null as if data is not set
|
||||
return null;
|
||||
}
|
||||
},
|
||||
remove(key) {
|
||||
try {
|
||||
window.localStorage.removeItem(key);
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
try {
|
||||
window.localStorage.clear();
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
},
|
||||
};
|
||||
//# sourceMappingURL=localStorage.js.map
|
1
client/dist/js/localStorage.js.map
vendored
Normal file
1
client/dist/js/localStorage.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"localStorage.js","sourceRoot":"","sources":["../../js/localStorage.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,yEAAyE;AACzE,sCAAsC;AACtC,4CAA4C;AAC5C,gFAAgF;AAChF,EAAE;AACF,yBAAyB;AACzB,+CAA+C;AAC/C,qDAAqD;AACrD,+KAA+K;AAE/K,eAAe;IACd,GAAG,CAAC,GAAW,EAAE,KAAa;QAC7B,IAAI;YACH,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;SACxC;QAAC,OAAO,CAAC,EAAE;YACX,EAAE;SACF;IACF,CAAC;IACD,GAAG,CAAC,GAAW;QACd,IAAI;YACH,OAAO,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;SACxC;QAAC,OAAO,CAAC,EAAE;YACX,oCAAoC;YACpC,OAAO,IAAI,CAAC;SACZ;IACF,CAAC;IACD,MAAM,CAAC,GAAW;QACjB,IAAI;YACH,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;SACpC;QAAC,OAAO,CAAC,EAAE;YACX,EAAE;SACF;IACF,CAAC;IACD,KAAK;QACJ,IAAI;YACH,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;SAC5B;QAAC,OAAO,CAAC,EAAE;YACX,EAAE;SACF;IACF,CAAC;CACD,CAAC"}
|
9
client/dist/js/location.js
vendored
Normal file
9
client/dist/js/location.js
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
"use strict";
|
||||
// This is a thin wrapper around `window.location`, in order to contain the
|
||||
// side-effects. Do not add logic to it as it cannot be tested, only mocked.
|
||||
export default {
|
||||
reload() {
|
||||
window.location.reload();
|
||||
},
|
||||
};
|
||||
//# sourceMappingURL=location.js.map
|
1
client/dist/js/location.js.map
vendored
Normal file
1
client/dist/js/location.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"location.js","sourceRoot":"","sources":["../../js/location.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,2EAA2E;AAC3E,4EAA4E;AAC5E,eAAe;IACd,MAAM;QACL,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC1B,CAAC;CACD,CAAC"}
|
180
client/dist/js/router.js
vendored
Normal file
180
client/dist/js/router.js
vendored
Normal file
|
@ -0,0 +1,180 @@
|
|||
"use strict";
|
||||
const constants = require("./constants");
|
||||
import Vue from "vue";
|
||||
import VueRouter from "vue-router";
|
||||
Vue.use(VueRouter);
|
||||
import SignIn from "../components/Windows/SignIn.vue";
|
||||
import Connect from "../components/Windows/Connect.vue";
|
||||
import Settings from "../components/Windows/Settings.vue";
|
||||
import Help from "../components/Windows/Help.vue";
|
||||
import Changelog from "../components/Windows/Changelog.vue";
|
||||
import NetworkEdit from "../components/Windows/NetworkEdit.vue";
|
||||
import SearchResults from "../components/Windows/SearchResults.vue";
|
||||
import RoutedChat from "../components/RoutedChat.vue";
|
||||
import store from "./store";
|
||||
import AppearanceSettings from "../components/Settings/Appearance.vue";
|
||||
import GeneralSettings from "../components/Settings/General.vue";
|
||||
import AccountSettings from "../components/Settings/Account.vue";
|
||||
import NotificationSettings from "../components/Settings/Notifications.vue";
|
||||
const router = new VueRouter({
|
||||
routes: [
|
||||
{
|
||||
name: "SignIn",
|
||||
path: "/sign-in",
|
||||
component: SignIn,
|
||||
beforeEnter(to, from, next) {
|
||||
// Prevent navigating to sign-in when already signed in
|
||||
if (store.state.appLoaded) {
|
||||
next(false);
|
||||
return;
|
||||
}
|
||||
next();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Connect",
|
||||
path: "/connect",
|
||||
component: Connect,
|
||||
props: (route) => ({queryParams: route.query}),
|
||||
},
|
||||
{
|
||||
path: "/settings",
|
||||
component: Settings,
|
||||
children: [
|
||||
{
|
||||
name: "General",
|
||||
path: "",
|
||||
component: GeneralSettings,
|
||||
},
|
||||
{
|
||||
name: "Appearance",
|
||||
path: "appearance",
|
||||
component: AppearanceSettings,
|
||||
},
|
||||
{
|
||||
name: "Account",
|
||||
path: "account",
|
||||
component: AccountSettings,
|
||||
},
|
||||
{
|
||||
name: "Notifications",
|
||||
path: "notifications",
|
||||
component: NotificationSettings,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Help",
|
||||
path: "/help",
|
||||
component: Help,
|
||||
},
|
||||
{
|
||||
name: "Changelog",
|
||||
path: "/changelog",
|
||||
component: Changelog,
|
||||
},
|
||||
{
|
||||
name: "NetworkEdit",
|
||||
path: "/edit-network/:uuid",
|
||||
component: NetworkEdit,
|
||||
},
|
||||
{
|
||||
name: "RoutedChat",
|
||||
path: "/chan-:id",
|
||||
component: RoutedChat,
|
||||
},
|
||||
{
|
||||
name: "SearchResults",
|
||||
path: "/chan-:id/search",
|
||||
component: SearchResults,
|
||||
},
|
||||
],
|
||||
});
|
||||
router.beforeEach((to, from, next) => {
|
||||
// If user is not yet signed in, wait for appLoaded state to change
|
||||
// unless they are trying to open SignIn (which can be triggered in auth.js)
|
||||
if (!store.state.appLoaded && to.name !== "SignIn") {
|
||||
store.watch(
|
||||
(state) => state.appLoaded,
|
||||
() => next()
|
||||
);
|
||||
return;
|
||||
}
|
||||
next();
|
||||
});
|
||||
router.beforeEach((to, from, next) => {
|
||||
// Disallow navigating to non-existing routes
|
||||
if (!to.matched.length) {
|
||||
next(false);
|
||||
return;
|
||||
}
|
||||
// Disallow navigating to invalid channels
|
||||
if (to.name === "RoutedChat" && !store.getters.findChannel(Number(to.params.id))) {
|
||||
next(false);
|
||||
return;
|
||||
}
|
||||
// Disallow navigating to invalid networks
|
||||
if (to.name === "NetworkEdit" && !store.getters.findNetwork(to.params.uuid)) {
|
||||
next(false);
|
||||
return;
|
||||
}
|
||||
// Handle closing image viewer with the browser back button
|
||||
if (!router.app.$refs.app) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
const imageViewer = router.app.$root.$refs.app.$refs.imageViewer;
|
||||
if (imageViewer && imageViewer.link) {
|
||||
imageViewer.closeViewer();
|
||||
next(false);
|
||||
return;
|
||||
}
|
||||
next();
|
||||
});
|
||||
router.afterEach((to) => {
|
||||
if (store.state.appLoaded) {
|
||||
if (window.innerWidth <= constants.mobileViewportPixels) {
|
||||
store.commit("sidebarOpen", false);
|
||||
}
|
||||
}
|
||||
if (store.state.activeChannel) {
|
||||
const channel = store.state.activeChannel.channel;
|
||||
if (to.name !== "RoutedChat") {
|
||||
store.commit("activeChannel", null);
|
||||
}
|
||||
// When switching out of a channel, mark everything as read
|
||||
if (channel.messages.length > 0) {
|
||||
channel.firstUnread = channel.messages[channel.messages.length - 1].id;
|
||||
}
|
||||
if (channel.messages.length > 100) {
|
||||
channel.messages.splice(0, channel.messages.length - 100);
|
||||
channel.moreHistoryAvailable = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
function navigate(routeName, params = {}) {
|
||||
if (router.currentRoute.name) {
|
||||
router.push({name: routeName, params}).catch(() => {});
|
||||
} else {
|
||||
// If current route is null, replace the history entry
|
||||
// This prevents invalid entries from lingering in history,
|
||||
// and then the route guard preventing proper navigation
|
||||
router.replace({name: routeName, params}).catch(() => {});
|
||||
}
|
||||
}
|
||||
function switchToChannel(channel) {
|
||||
return navigate("RoutedChat", {id: channel.id});
|
||||
}
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.addEventListener("message", (event) => {
|
||||
if (event.data && event.data.type === "open") {
|
||||
const id = parseInt(event.data.channel.substr(5), 10); // remove "chan-" prefix
|
||||
const channelTarget = store.getters.findChannel(id);
|
||||
if (channelTarget) {
|
||||
switchToChannel(channelTarget.channel);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
export {router, navigate, switchToChannel};
|
||||
//# sourceMappingURL=router.js.map
|
1
client/dist/js/router.js.map
vendored
Normal file
1
client/dist/js/router.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../js/router.js"],"names":[],"mappings":"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"}
|
125
client/dist/js/settings.js
vendored
Normal file
125
client/dist/js/settings.js
vendored
Normal file
|
@ -0,0 +1,125 @@
|
|||
import socket from "./socket";
|
||||
const defaultSettingConfig = {
|
||||
apply() {},
|
||||
default: null,
|
||||
sync: null,
|
||||
};
|
||||
export const config = normalizeConfig({
|
||||
syncSettings: {
|
||||
default: true,
|
||||
sync: "never",
|
||||
apply(store, value, auto = false) {
|
||||
// If applied by settings/applyAll, do not emit to server
|
||||
if (value && !auto) {
|
||||
socket.emit("setting:get");
|
||||
}
|
||||
},
|
||||
},
|
||||
advanced: {
|
||||
default: false,
|
||||
},
|
||||
autocomplete: {
|
||||
default: true,
|
||||
},
|
||||
nickPostfix: {
|
||||
default: "",
|
||||
},
|
||||
coloredNicks: {
|
||||
default: true,
|
||||
},
|
||||
desktopNotifications: {
|
||||
default: false,
|
||||
sync: "never",
|
||||
apply(store, value) {
|
||||
store.commit("refreshDesktopNotificationState", null, {root: true});
|
||||
if ("Notification" in window && value && Notification.permission !== "granted") {
|
||||
Notification.requestPermission(() =>
|
||||
store.commit("refreshDesktopNotificationState", null, {root: true})
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
highlights: {
|
||||
default: "",
|
||||
sync: "always",
|
||||
},
|
||||
highlightExceptions: {
|
||||
default: "",
|
||||
sync: "always",
|
||||
},
|
||||
awayMessage: {
|
||||
default: "",
|
||||
sync: "always",
|
||||
},
|
||||
links: {
|
||||
default: true,
|
||||
},
|
||||
motd: {
|
||||
default: true,
|
||||
},
|
||||
notification: {
|
||||
default: true,
|
||||
sync: "never",
|
||||
},
|
||||
notifyAllMessages: {
|
||||
default: false,
|
||||
},
|
||||
showSeconds: {
|
||||
default: false,
|
||||
},
|
||||
use12hClock: {
|
||||
default: false,
|
||||
},
|
||||
statusMessages: {
|
||||
default: "condensed",
|
||||
},
|
||||
theme: {
|
||||
default: document.getElementById("theme").dataset.serverTheme,
|
||||
apply(store, value) {
|
||||
const themeEl = document.getElementById("theme");
|
||||
const themeUrl = `themes/${value}.css`;
|
||||
if (themeEl.attributes.href.value === themeUrl) {
|
||||
return;
|
||||
}
|
||||
themeEl.attributes.href.value = themeUrl;
|
||||
const newTheme = store.state.serverConfiguration.themes.filter(
|
||||
(theme) => theme.name === value
|
||||
)[0];
|
||||
const themeColor =
|
||||
newTheme.themeColor || document.querySelector('meta[name="theme-color"]').content;
|
||||
document.querySelector('meta[name="theme-color"]').content = themeColor;
|
||||
},
|
||||
},
|
||||
media: {
|
||||
default: true,
|
||||
},
|
||||
uploadCanvas: {
|
||||
default: true,
|
||||
},
|
||||
userStyles: {
|
||||
default: "",
|
||||
apply(store, value) {
|
||||
if (!/[?&]nocss/.test(window.location.search)) {
|
||||
document.getElementById("user-specified-css").innerHTML = value;
|
||||
}
|
||||
},
|
||||
},
|
||||
searchEnabled: {
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
export function createState() {
|
||||
const state = {};
|
||||
for (const settingName in config) {
|
||||
state[settingName] = config[settingName].default;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
function normalizeConfig(obj) {
|
||||
const newConfig = {};
|
||||
for (const settingName in obj) {
|
||||
newConfig[settingName] = {...defaultSettingConfig, ...obj[settingName]};
|
||||
}
|
||||
return newConfig;
|
||||
}
|
||||
//# sourceMappingURL=settings.js.map
|
1
client/dist/js/settings.js.map
vendored
Normal file
1
client/dist/js/settings.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../js/settings.js"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,UAAU,CAAC;AAE9B,MAAM,oBAAoB,GAAG;IAC5B,KAAK,KAAI,CAAC;IACV,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,IAAI;CACV,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,eAAe,CAAC;IACrC,YAAY,EAAE;QACb,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,OAAO;QACb,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,GAAG,KAAK;YAC/B,yDAAyD;YACzD,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE;gBACnB,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;aAC3B;QACF,CAAC;KACD;IACD,QAAQ,EAAE;QACT,OAAO,EAAE,KAAK;KACd;IACD,YAAY,EAAE;QACb,OAAO,EAAE,IAAI;KACb;IACD,WAAW,EAAE;QACZ,OAAO,EAAE,EAAE;KACX;IACD,YAAY,EAAE;QACb,OAAO,EAAE,IAAI;KACb;IACD,oBAAoB,EAAE;QACrB,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,OAAO;QACb,KAAK,CAAC,KAAK,EAAE,KAAK;YACjB,KAAK,CAAC,MAAM,CAAC,iCAAiC,EAAE,IAAI,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;YAEpE,IAAI,cAAc,IAAI,MAAM,IAAI,KAAK,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,EAAE;gBAC/E,YAAY,CAAC,iBAAiB,CAAC,GAAG,EAAE,CACnC,KAAK,CAAC,MAAM,CAAC,iCAAiC,EAAE,IAAI,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CACnE,CAAC;aACF;QACF,CAAC;KACD;IACD,UAAU,EAAE;QACX,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,QAAQ;KACd;IACD,mBAAmB,EAAE;QACpB,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,QAAQ;KACd;IACD,WAAW,EAAE;QACZ,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,QAAQ;KACd;IACD,KAAK,EAAE;QACN,OAAO,EAAE,IAAI;KACb;IACD,IAAI,EAAE;QACL,OAAO,EAAE,IAAI;KACb;IACD,YAAY,EAAE;QACb,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,OAAO;KACb;IACD,iBAAiB,EAAE;QAClB,OAAO,EAAE,KAAK;KACd;IACD,WAAW,EAAE;QACZ,OAAO,EAAE,KAAK;KACd;IACD,WAAW,EAAE;QACZ,OAAO,EAAE,KAAK;KACd;IACD,cAAc,EAAE;QACf,OAAO,EAAE,WAAW;KACpB;IACD,KAAK,EAAE;QACN,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW;QAC7D,KAAK,CAAC,KAAK,EAAE,KAAK;YACjB,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YACjD,MAAM,QAAQ,GAAG,UAAU,KAAK,MAAM,CAAC;YAEvC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE;gBAC/C,OAAO;aACP;YAED,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC;YACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAC7D,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,CAC/B,CAAC,CAAC,CAAC,CAAC;YACL,MAAM,UAAU,GACf,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,aAAa,CAAC,0BAA0B,CAAC,CAAC,OAAO,CAAC;YACnF,QAAQ,CAAC,aAAa,CAAC,0BAA0B,CAAC,CAAC,OAAO,GAAG,UAAU,CAAC;QACzE,CAAC;KACD;IACD,KAAK,EAAE;QACN,OAAO,EAAE,IAAI;KACb;IACD,YAAY,EAAE;QACb,OAAO,EAAE,IAAI;KACb;IACD,UAAU,EAAE;QACX,OAAO,EAAE,EAAE;QACX,KAAK,CAAC,KAAK,EAAE,KAAK;YACjB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBAC9C,QAAQ,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC;aAChE;QACF,CAAC;KACD;IACD,aAAa,EAAE;QACd,OAAO,EAAE,KAAK;KACd;CACD,CAAC,CAAC;AAEH,MAAM,UAAU,WAAW;IAC1B,MAAM,KAAK,GAAG,EAAE,CAAC;IAEjB,KAAK,MAAM,WAAW,IAAI,MAAM,EAAE;QACjC,KAAK,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC;KACjD;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,eAAe,CAAC,GAAG;IAC3B,MAAM,SAAS,GAAG,EAAE,CAAC;IAErB,KAAK,MAAM,WAAW,IAAI,GAAG,EAAE;QAC9B,SAAS,CAAC,WAAW,CAAC,GAAG,EAAC,GAAG,oBAAoB,EAAE,GAAG,GAAG,CAAC,WAAW,CAAC,EAAC,CAAC;KACxE;IAED,OAAO,SAAS,CAAC;AAClB,CAAC"}
|
81
client/dist/js/socket-events/auth.js
vendored
Normal file
81
client/dist/js/socket-events/auth.js
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
"use strict";
|
||||
import socket from "../socket";
|
||||
import storage from "../localStorage";
|
||||
import {router, navigate} from "../router";
|
||||
import store from "../store";
|
||||
import location from "../location";
|
||||
let lastServerHash = null;
|
||||
socket.on("auth:success", function () {
|
||||
store.commit("currentUserVisibleError", "Loading messages…");
|
||||
updateLoadingMessage();
|
||||
});
|
||||
socket.on("auth:failed", function () {
|
||||
storage.remove("token");
|
||||
if (store.state.appLoaded) {
|
||||
return reloadPage("Authentication failed, reloading…");
|
||||
}
|
||||
showSignIn();
|
||||
});
|
||||
socket.on("auth:start", function (serverHash) {
|
||||
// If we reconnected and serverHash differs, that means the server restarted
|
||||
// And we will reload the page to grab the latest version
|
||||
if (lastServerHash && serverHash !== lastServerHash) {
|
||||
return reloadPage("Server restarted, reloading…");
|
||||
}
|
||||
lastServerHash = serverHash;
|
||||
const user = storage.get("user");
|
||||
const token = storage.get("token");
|
||||
const doFastAuth = user && token;
|
||||
// If we reconnect and no longer have a stored token, reload the page
|
||||
if (store.state.appLoaded && !doFastAuth) {
|
||||
return reloadPage("Authentication failed, reloading…");
|
||||
}
|
||||
// If we have user and token stored, perform auth without showing sign-in first
|
||||
if (doFastAuth) {
|
||||
store.commit("currentUserVisibleError", "Authorizing…");
|
||||
updateLoadingMessage();
|
||||
let lastMessage = -1;
|
||||
for (const network of store.state.networks) {
|
||||
for (const chan of network.channels) {
|
||||
if (chan.messages.length > 0) {
|
||||
const id = chan.messages[chan.messages.length - 1].id;
|
||||
if (lastMessage < id) {
|
||||
lastMessage = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const openChannel =
|
||||
(store.state.activeChannel && store.state.activeChannel.channel.id) || null;
|
||||
socket.emit("auth:perform", {
|
||||
user,
|
||||
token,
|
||||
lastMessage,
|
||||
openChannel,
|
||||
hasConfig: store.state.serverConfiguration !== null,
|
||||
});
|
||||
} else {
|
||||
showSignIn();
|
||||
}
|
||||
});
|
||||
function showSignIn() {
|
||||
// TODO: this flashes grey background because it takes a little time for vue to mount signin
|
||||
if (window.g_TheLoungeRemoveLoading) {
|
||||
window.g_TheLoungeRemoveLoading();
|
||||
}
|
||||
if (router.currentRoute.name !== "SignIn") {
|
||||
navigate("SignIn");
|
||||
}
|
||||
}
|
||||
function reloadPage(message) {
|
||||
socket.disconnect();
|
||||
store.commit("currentUserVisibleError", message);
|
||||
location.reload(true);
|
||||
}
|
||||
function updateLoadingMessage() {
|
||||
const loading = document.getElementById("loading-page-message");
|
||||
if (loading) {
|
||||
loading.textContent = store.state.currentUserVisibleError;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=auth.js.map
|
1
client/dist/js/socket-events/auth.js.map
vendored
Normal file
1
client/dist/js/socket-events/auth.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../js/socket-events/auth.js"],"names":[],"mappings":"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"}
|
32
client/dist/js/socket-events/changelog.js
vendored
Normal file
32
client/dist/js/socket-events/changelog.js
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
"use strict";
|
||||
import socket from "../socket";
|
||||
import store from "../store";
|
||||
socket.on("changelog", function (data) {
|
||||
store.commit("versionData", data);
|
||||
store.commit("versionDataExpired", false);
|
||||
let status;
|
||||
if (data.latest) {
|
||||
status = "new-version";
|
||||
} else if (data.packages) {
|
||||
status = "new-packages";
|
||||
} else if (data.current.changelog) {
|
||||
status = "up-to-date";
|
||||
} else {
|
||||
status = "error";
|
||||
}
|
||||
store.commit("versionStatus", status);
|
||||
// When there is a button to refresh the checker available, display it when
|
||||
// data is expired. Before that, server would return same information anyway.
|
||||
if (data.expiresAt) {
|
||||
const expires = data.expiresAt - Date.now();
|
||||
if (expires > 0) {
|
||||
setTimeout(() => store.commit("versionDataExpired", true), expires);
|
||||
} else {
|
||||
store.commit("versionDataExpired", true);
|
||||
}
|
||||
}
|
||||
});
|
||||
socket.on("changelog:newversion", () => {
|
||||
store.state.serverConfiguration.isUpdateAvailable = true;
|
||||
});
|
||||
//# sourceMappingURL=changelog.js.map
|
1
client/dist/js/socket-events/changelog.js.map
vendored
Normal file
1
client/dist/js/socket-events/changelog.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../../js/socket-events/changelog.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,OAAO,KAAK,MAAM,UAAU,CAAC;AAE7B,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,UAAU,IAAI;IACpC,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IAClC,KAAK,CAAC,MAAM,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;IAE1C,IAAI,MAAM,CAAC;IAEX,IAAI,IAAI,CAAC,MAAM,EAAE;QAChB,MAAM,GAAG,aAAa,CAAC;KACvB;SAAM,IAAI,IAAI,CAAC,QAAQ,EAAE;QACzB,MAAM,GAAG,cAAc,CAAC;KACxB;SAAM,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;QAClC,MAAM,GAAG,YAAY,CAAC;KACtB;SAAM;QACN,MAAM,GAAG,OAAO,CAAC;KACjB;IAED,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAEtC,2EAA2E;IAC3E,6EAA6E;IAC7E,IAAI,IAAI,CAAC,SAAS,EAAE;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE5C,IAAI,OAAO,GAAG,CAAC,EAAE;YAChB,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;SACpE;aAAM;YACN,KAAK,CAAC,MAAM,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;SACzC;KACD;AACF,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACtC,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,iBAAiB,GAAG,IAAI,CAAC;AAC1D,CAAC,CAAC,CAAC"}
|
8
client/dist/js/socket-events/commands.js
vendored
Normal file
8
client/dist/js/socket-events/commands.js
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
const constants = require("../constants");
|
||||
import socket from "../socket";
|
||||
socket.on("commands", function (commands) {
|
||||
if (commands) {
|
||||
constants.commands = commands;
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=commands.js.map
|
1
client/dist/js/socket-events/commands.js.map
vendored
Normal file
1
client/dist/js/socket-events/commands.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../js/socket-events/commands.js"],"names":[],"mappings":"AAAA,MAAM,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAC1C,OAAO,MAAM,MAAM,WAAW,CAAC;AAE/B,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,QAAQ;IACvC,IAAI,QAAQ,EAAE;QACb,SAAS,CAAC,QAAQ,GAAG,QAAQ,CAAC;KAC9B;AACF,CAAC,CAAC,CAAC"}
|
28
client/dist/js/socket-events/configuration.js
vendored
Normal file
28
client/dist/js/socket-events/configuration.js
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
"use strict";
|
||||
import socket from "../socket";
|
||||
import upload from "../upload";
|
||||
import store from "../store";
|
||||
socket.once("configuration", function (data) {
|
||||
store.commit("serverConfiguration", data);
|
||||
// 'theme' setting depends on serverConfiguration.themes so
|
||||
// settings cannot be applied before this point
|
||||
store.dispatch("settings/applyAll");
|
||||
if (data.fileUpload) {
|
||||
upload.initialize();
|
||||
}
|
||||
// If localStorage contains a theme that does not exist on this server, switch
|
||||
// back to its default theme.
|
||||
const currentTheme = data.themes.find((t) => t.name === store.state.settings.theme);
|
||||
if (currentTheme === undefined) {
|
||||
store.dispatch("settings/update", {name: "theme", value: data.defaultTheme, sync: true});
|
||||
} else if (currentTheme.themeColor) {
|
||||
document.querySelector('meta[name="theme-color"]').content = currentTheme.themeColor;
|
||||
}
|
||||
if (document.body.classList.contains("public")) {
|
||||
window.addEventListener("beforeunload", (e) => {
|
||||
e.preventDefault();
|
||||
e.returnValue = "Are you sure you want to navigate away from this page?";
|
||||
});
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=configuration.js.map
|
1
client/dist/js/socket-events/configuration.js.map
vendored
Normal file
1
client/dist/js/socket-events/configuration.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"configuration.js","sourceRoot":"","sources":["../../../js/socket-events/configuration.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,OAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,OAAO,KAAK,MAAM,UAAU,CAAC;AAE7B,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,UAAU,IAAI;IAC1C,KAAK,CAAC,MAAM,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;IAE1C,2DAA2D;IAC3D,+CAA+C;IAC/C,KAAK,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IAEpC,IAAI,IAAI,CAAC,UAAU,EAAE;QACpB,MAAM,CAAC,UAAU,EAAE,CAAC;KACpB;IAED,8EAA8E;IAC9E,6BAA6B;IAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEpF,IAAI,YAAY,KAAK,SAAS,EAAE;QAC/B,KAAK,CAAC,QAAQ,CAAC,iBAAiB,EAAE,EAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;KACzF;SAAM,IAAI,YAAY,CAAC,UAAU,EAAE;QACnC,QAAQ,CAAC,aAAa,CAAC,0BAA0B,CAAC,CAAC,OAAO,GAAG,YAAY,CAAC,UAAU,CAAC;KACrF;IAED,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAC/C,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE;YAC7C,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,CAAC,CAAC,WAAW,GAAG,wDAAwD,CAAC;QAC1E,CAAC,CAAC,CAAC;KACH;AACF,CAAC,CAAC,CAAC"}
|
57
client/dist/js/socket-events/connection.js
vendored
Normal file
57
client/dist/js/socket-events/connection.js
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
import store from "../store";
|
||||
import socket from "../socket";
|
||||
socket.on("disconnect", handleDisconnect);
|
||||
socket.on("connect_error", handleDisconnect);
|
||||
socket.on("error", handleDisconnect);
|
||||
socket.io.on("reconnect_attempt", function (attempt) {
|
||||
store.commit("currentUserVisibleError", `Reconnecting… (attempt ${attempt})`);
|
||||
updateLoadingMessage();
|
||||
});
|
||||
socket.on("connecting", function () {
|
||||
store.commit("currentUserVisibleError", "Connecting…");
|
||||
updateLoadingMessage();
|
||||
});
|
||||
socket.on("connect", function () {
|
||||
// Clear send buffer when reconnecting, socket.io would emit these
|
||||
// immediately upon connection and it will have no effect, so we ensure
|
||||
// nothing is sent to the server that might have happened.
|
||||
socket.sendBuffer = [];
|
||||
store.commit("currentUserVisibleError", "Finalizing connection…");
|
||||
updateLoadingMessage();
|
||||
});
|
||||
function handleDisconnect(data) {
|
||||
const message = data.message || data;
|
||||
store.commit("isConnected", false);
|
||||
if (!socket.io.reconnection()) {
|
||||
store.commit(
|
||||
"currentUserVisibleError",
|
||||
`Disconnected from the server (${message}), The Lounge does not reconnect in public mode.`
|
||||
);
|
||||
updateLoadingMessage();
|
||||
return;
|
||||
}
|
||||
store.commit("currentUserVisibleError", `Waiting to reconnect… (${message})`);
|
||||
updateLoadingMessage();
|
||||
// If the server shuts down, socket.io skips reconnection
|
||||
// and we have to manually call connect to start the process
|
||||
// However, do not reconnect if TL client manually closed the connection
|
||||
if (socket.io.skipReconnect && message !== "io client disconnect") {
|
||||
requestIdleCallback(() => socket.connect(), 2000);
|
||||
}
|
||||
}
|
||||
function requestIdleCallback(callback, timeout) {
|
||||
if (window.requestIdleCallback) {
|
||||
// During an idle period the user agent will run idle callbacks in FIFO order
|
||||
// until either the idle period ends or there are no more idle callbacks eligible to be run.
|
||||
window.requestIdleCallback(callback, {timeout});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
function updateLoadingMessage() {
|
||||
const loading = document.getElementById("loading-page-message");
|
||||
if (loading) {
|
||||
loading.textContent = store.state.currentUserVisibleError;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=connection.js.map
|
1
client/dist/js/socket-events/connection.js.map
vendored
Normal file
1
client/dist/js/socket-events/connection.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../js/socket-events/connection.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,UAAU,CAAC;AAC7B,OAAO,MAAM,MAAM,WAAW,CAAC;AAE/B,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;AAC1C,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;AAC7C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;AAErC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,EAAE,UAAU,OAAO;IAClD,KAAK,CAAC,MAAM,CAAC,yBAAyB,EAAE,0BAA0B,OAAO,GAAG,CAAC,CAAC;IAC9E,oBAAoB,EAAE,CAAC;AACxB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE;IACvB,KAAK,CAAC,MAAM,CAAC,yBAAyB,EAAE,aAAa,CAAC,CAAC;IACvD,oBAAoB,EAAE,CAAC;AACxB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE;IACpB,kEAAkE;IAClE,uEAAuE;IACvE,0DAA0D;IAC1D,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;IAEvB,KAAK,CAAC,MAAM,CAAC,yBAAyB,EAAE,wBAAwB,CAAC,CAAC;IAClE,oBAAoB,EAAE,CAAC;AACxB,CAAC,CAAC,CAAC;AAEH,SAAS,gBAAgB,CAAC,IAAI;IAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;IAErC,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAEnC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE;QAC9B,KAAK,CAAC,MAAM,CACX,yBAAyB,EACzB,iCAAiC,OAAO,kDAAkD,CAC1F,CAAC;QACF,oBAAoB,EAAE,CAAC;QACvB,OAAO;KACP;IAED,KAAK,CAAC,MAAM,CAAC,yBAAyB,EAAE,0BAA0B,OAAO,GAAG,CAAC,CAAC;IAC9E,oBAAoB,EAAE,CAAC;IAEvB,yDAAyD;IACzD,4DAA4D;IAC5D,wEAAwE;IACxE,IAAI,MAAM,CAAC,EAAE,CAAC,aAAa,IAAI,OAAO,KAAK,sBAAsB,EAAE;QAClE,mBAAmB,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC;KAClD;AACF,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAQ,EAAE,OAAO;IAC7C,IAAI,MAAM,CAAC,mBAAmB,EAAE;QAC/B,6EAA6E;QAC7E,4FAA4F;QAC5F,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,EAAC,OAAO,EAAC,CAAC,CAAC;KAChD;SAAM;QACN,QAAQ,EAAE,CAAC;KACX;AACF,CAAC;AAED,SAAS,oBAAoB;IAC5B,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,sBAAsB,CAAC,CAAC;IAEhE,IAAI,OAAO,EAAE;QACZ,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC;KAC1D;AACF,CAAC"}
|
12
client/dist/js/socket-events/history_clear.js
vendored
Normal file
12
client/dist/js/socket-events/history_clear.js
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
"use strict";
|
||||
import socket from "../socket";
|
||||
import store from "../store";
|
||||
socket.on("history:clear", function (data) {
|
||||
const {channel} = store.getters.findChannel(data.target);
|
||||
channel.messages = [];
|
||||
channel.unread = 0;
|
||||
channel.highlight = 0;
|
||||
channel.firstUnread = 0;
|
||||
channel.moreHistoryAvailable = false;
|
||||
});
|
||||
//# sourceMappingURL=history_clear.js.map
|
1
client/dist/js/socket-events/history_clear.js.map
vendored
Normal file
1
client/dist/js/socket-events/history_clear.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"history_clear.js","sourceRoot":"","sources":["../../../js/socket-events/history_clear.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,OAAO,KAAK,MAAM,UAAU,CAAC;AAE7B,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,UAAU,IAAI;IACxC,MAAM,EAAC,OAAO,EAAC,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEzD,OAAO,CAAC,QAAQ,GAAG,EAAE,CAAC;IACtB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;IACtB,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC;IACxB,OAAO,CAAC,oBAAoB,GAAG,KAAK,CAAC;AACtC,CAAC,CAAC,CAAC"}
|
29
client/dist/js/socket-events/index.js
vendored
Normal file
29
client/dist/js/socket-events/index.js
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
"use strict";
|
||||
import "./connection";
|
||||
import "./auth";
|
||||
import "./commands";
|
||||
import "./init";
|
||||
import "./join";
|
||||
import "./more";
|
||||
import "./msg";
|
||||
import "./msg_preview";
|
||||
import "./msg_special";
|
||||
import "./names";
|
||||
import "./network";
|
||||
import "./nick";
|
||||
import "./open";
|
||||
import "./part";
|
||||
import "./quit";
|
||||
import "./sync_sort";
|
||||
import "./topic";
|
||||
import "./users";
|
||||
import "./sign_out";
|
||||
import "./sessions_list";
|
||||
import "./configuration";
|
||||
import "./changelog";
|
||||
import "./setting";
|
||||
import "./history_clear";
|
||||
import "./mentions";
|
||||
import "./search";
|
||||
import "./mute_changed";
|
||||
//# sourceMappingURL=index.js.map
|
1
client/dist/js/socket-events/index.js.map
vendored
Normal file
1
client/dist/js/socket-events/index.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../js/socket-events/index.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,cAAc,CAAC;AACtB,OAAO,QAAQ,CAAC;AAChB,OAAO,YAAY,CAAC;AACpB,OAAO,QAAQ,CAAC;AAChB,OAAO,QAAQ,CAAC;AAChB,OAAO,QAAQ,CAAC;AAChB,OAAO,OAAO,CAAC;AACf,OAAO,eAAe,CAAC;AACvB,OAAO,eAAe,CAAC;AACvB,OAAO,SAAS,CAAC;AACjB,OAAO,WAAW,CAAC;AACnB,OAAO,QAAQ,CAAC;AAChB,OAAO,QAAQ,CAAC;AAChB,OAAO,QAAQ,CAAC;AAChB,OAAO,QAAQ,CAAC;AAChB,OAAO,aAAa,CAAC;AACrB,OAAO,SAAS,CAAC;AACjB,OAAO,SAAS,CAAC;AACjB,OAAO,YAAY,CAAC;AACpB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,aAAa,CAAC;AACrB,OAAO,WAAW,CAAC;AACnB,OAAO,iBAAiB,CAAC;AACzB,OAAO,YAAY,CAAC;AACpB,OAAO,UAAU,CAAC;AAClB,OAAO,gBAAgB,CAAC"}
|
154
client/dist/js/socket-events/init.js
vendored
Normal file
154
client/dist/js/socket-events/init.js
vendored
Normal file
|
@ -0,0 +1,154 @@
|
|||
"use strict";
|
||||
import Vue from "vue";
|
||||
import socket from "../socket";
|
||||
import storage from "../localStorage";
|
||||
import {router, switchToChannel, navigate} from "../router";
|
||||
import store from "../store";
|
||||
import parseIrcUri from "../helpers/parseIrcUri";
|
||||
socket.on("init", function (data) {
|
||||
store.commit("networks", mergeNetworkData(data.networks));
|
||||
store.commit("isConnected", true);
|
||||
store.commit("currentUserVisibleError", null);
|
||||
if (data.token) {
|
||||
storage.set("token", data.token);
|
||||
}
|
||||
if (!store.state.appLoaded) {
|
||||
store.commit("appLoaded");
|
||||
socket.emit("setting:get");
|
||||
if (window.g_TheLoungeRemoveLoading) {
|
||||
window.g_TheLoungeRemoveLoading();
|
||||
}
|
||||
Vue.nextTick(() => {
|
||||
// If we handled query parameters like irc:// links or just general
|
||||
// connect parameters in public mode, then nothing to do here
|
||||
if (!handleQueryParams()) {
|
||||
// If we are on an unknown route or still on SignIn component
|
||||
// then we can open last known channel on server, or Connect window if none
|
||||
if (!router.currentRoute.name || router.currentRoute.name === "SignIn") {
|
||||
const channel = store.getters.findChannel(data.active);
|
||||
if (channel) {
|
||||
switchToChannel(channel.channel);
|
||||
} else if (store.state.networks.length > 0) {
|
||||
// Server is telling us to open a channel that does not exist
|
||||
// For example, it can be unset if you first open the page after server start
|
||||
switchToChannel(store.state.networks[0].channels[0]);
|
||||
} else {
|
||||
navigate("Connect");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
function mergeNetworkData(newNetworks) {
|
||||
const collapsedNetworks = new Set(JSON.parse(storage.get("thelounge.networks.collapsed")));
|
||||
for (let n = 0; n < newNetworks.length; n++) {
|
||||
const network = newNetworks[n];
|
||||
const currentNetwork = store.getters.findNetwork(network.uuid);
|
||||
// If this network is new, set some default variables and initalize channel variables
|
||||
if (!currentNetwork) {
|
||||
network.isJoinChannelShown = false;
|
||||
network.isCollapsed = collapsedNetworks.has(network.uuid);
|
||||
network.channels.forEach(store.getters.initChannel);
|
||||
continue;
|
||||
}
|
||||
// Merge received network object into existing network object on the client
|
||||
// so the object reference stays the same (e.g. for currentChannel state)
|
||||
for (const key in network) {
|
||||
if (!Object.prototype.hasOwnProperty.call(network, key)) {
|
||||
continue;
|
||||
}
|
||||
// Channels require extra care to be merged correctly
|
||||
if (key === "channels") {
|
||||
currentNetwork.channels = mergeChannelData(
|
||||
currentNetwork.channels,
|
||||
network.channels
|
||||
);
|
||||
} else {
|
||||
currentNetwork[key] = network[key];
|
||||
}
|
||||
}
|
||||
newNetworks[n] = currentNetwork;
|
||||
}
|
||||
return newNetworks;
|
||||
}
|
||||
function mergeChannelData(oldChannels, newChannels) {
|
||||
for (let c = 0; c < newChannels.length; c++) {
|
||||
const channel = newChannels[c];
|
||||
const currentChannel = oldChannels.find((chan) => chan.id === channel.id);
|
||||
// This is a new channel that was joined while client was disconnected, initialize it
|
||||
if (!currentChannel) {
|
||||
store.getters.initChannel(channel);
|
||||
continue;
|
||||
}
|
||||
// Merge received channel object into existing currentChannel
|
||||
// so the object references are exactly the same (e.g. in store.state.activeChannel)
|
||||
for (const key in channel) {
|
||||
if (!Object.prototype.hasOwnProperty.call(channel, key)) {
|
||||
continue;
|
||||
}
|
||||
// Server sends an empty users array, client requests it whenever needed
|
||||
if (key === "users") {
|
||||
if (channel.type === "channel") {
|
||||
if (
|
||||
store.state.activeChannel &&
|
||||
store.state.activeChannel.channel === currentChannel
|
||||
) {
|
||||
// For currently open channel, request the user list straight away
|
||||
socket.emit("names", {
|
||||
target: channel.id,
|
||||
});
|
||||
} else {
|
||||
// For all other channels, mark the user list as outdated
|
||||
// so an update will be requested whenever user switches to these channels
|
||||
currentChannel.usersOutdated = true;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Server sends total count of messages in memory, we compare it to amount of messages
|
||||
// on the client, and decide whether theres more messages to load from server
|
||||
if (key === "totalMessages") {
|
||||
currentChannel.moreHistoryAvailable =
|
||||
channel.totalMessages > currentChannel.messages.length;
|
||||
continue;
|
||||
}
|
||||
// Reconnection only sends new messages, so merge it on the client
|
||||
// Only concat if server sent us less than 100 messages so we don't introduce gaps
|
||||
if (key === "messages" && currentChannel.messages && channel.messages.length < 100) {
|
||||
currentChannel.messages = currentChannel.messages.concat(channel.messages);
|
||||
} else {
|
||||
currentChannel[key] = channel[key];
|
||||
}
|
||||
}
|
||||
newChannels[c] = currentChannel;
|
||||
}
|
||||
return newChannels;
|
||||
}
|
||||
function handleQueryParams() {
|
||||
if (!("URLSearchParams" in window)) {
|
||||
return false;
|
||||
}
|
||||
const params = new URLSearchParams(document.location.search);
|
||||
const cleanParams = () => {
|
||||
// Remove query parameters from url without reloading the page
|
||||
const cleanUri = window.location.origin + window.location.pathname + window.location.hash;
|
||||
window.history.replaceState({}, document.title, cleanUri);
|
||||
};
|
||||
if (params.has("uri")) {
|
||||
// Set default connection settings from IRC protocol links
|
||||
const uri = params.get("uri");
|
||||
const queryParams = parseIrcUri(uri);
|
||||
cleanParams();
|
||||
router.push({name: "Connect", query: queryParams});
|
||||
return true;
|
||||
} else if (document.body.classList.contains("public") && document.location.search) {
|
||||
// Set default connection settings from url params
|
||||
const queryParams = Object.fromEntries(params.entries());
|
||||
cleanParams();
|
||||
router.push({name: "Connect", query: queryParams});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//# sourceMappingURL=init.js.map
|
1
client/dist/js/socket-events/init.js.map
vendored
Normal file
1
client/dist/js/socket-events/init.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
18
client/dist/js/socket-events/join.js
vendored
Normal file
18
client/dist/js/socket-events/join.js
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
"use strict";
|
||||
import socket from "../socket";
|
||||
import store from "../store";
|
||||
import {switchToChannel} from "../router";
|
||||
socket.on("join", function (data) {
|
||||
store.getters.initChannel(data.chan);
|
||||
const network = store.getters.findNetwork(data.network);
|
||||
if (!network) {
|
||||
return;
|
||||
}
|
||||
network.channels.splice(data.index || -1, 0, data.chan);
|
||||
// Queries do not automatically focus, unless the user did a whois
|
||||
if (data.chan.type === "query" && !data.shouldOpen) {
|
||||
return;
|
||||
}
|
||||
switchToChannel(store.getters.findChannel(data.chan.id).channel);
|
||||
});
|
||||
//# sourceMappingURL=join.js.map
|
1
client/dist/js/socket-events/join.js.map
vendored
Normal file
1
client/dist/js/socket-events/join.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"join.js","sourceRoot":"","sources":["../../../js/socket-events/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,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,IAAI;IAC/B,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAErC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAExD,IAAI,CAAC,OAAO,EAAE;QACb,OAAO;KACP;IAED,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAExD,kEAAkE;IAClE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;QACnD,OAAO;KACP;IAED,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;AAClE,CAAC,CAAC,CAAC"}
|
7
client/dist/js/socket-events/mentions.js
vendored
Normal file
7
client/dist/js/socket-events/mentions.js
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
import socket from "../socket";
|
||||
import store from "../store";
|
||||
socket.on("mentions:list", function (data) {
|
||||
store.commit("mentions", data);
|
||||
});
|
||||
//# sourceMappingURL=mentions.js.map
|
1
client/dist/js/socket-events/mentions.js.map
vendored
Normal file
1
client/dist/js/socket-events/mentions.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"mentions.js","sourceRoot":"","sources":["../../../js/socket-events/mentions.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,OAAO,KAAK,MAAM,UAAU,CAAC;AAE7B,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,UAAU,IAAI;IACxC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC"}
|
24
client/dist/js/socket-events/more.js
vendored
Normal file
24
client/dist/js/socket-events/more.js
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
"use strict";
|
||||
import Vue from "vue";
|
||||
import socket from "../socket";
|
||||
import store from "../store";
|
||||
socket.on("more", function (data) {
|
||||
const channel = store.getters.findChannel(data.chan)?.channel;
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
channel.inputHistory = channel.inputHistory.concat(
|
||||
data.messages
|
||||
.filter((m) => m.self && m.text && m.type === "message")
|
||||
.map((m) => m.text)
|
||||
.reverse()
|
||||
.slice(null, 100 - channel.inputHistory.length)
|
||||
);
|
||||
channel.moreHistoryAvailable =
|
||||
data.totalMessages > channel.messages.length + data.messages.length;
|
||||
channel.messages.unshift(...data.messages);
|
||||
Vue.nextTick(() => {
|
||||
channel.historyLoading = false;
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=more.js.map
|
1
client/dist/js/socket-events/more.js.map
vendored
Normal file
1
client/dist/js/socket-events/more.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"more.js","sourceRoot":"","sources":["../../../js/socket-events/more.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,OAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,OAAO,KAAK,MAAM,UAAU,CAAC;AAE7B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,IAAI;IAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAE9D,IAAI,CAAC,OAAO,EAAE;QACb,OAAO;KACP;IAED,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,CACjD,IAAI,CAAC,QAAQ;SACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;SACvD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,OAAO,EAAE;SACT,KAAK,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAChD,CAAC;IACF,OAAO,CAAC,oBAAoB;QAC3B,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;IACrE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE3C,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE;QACjB,OAAO,CAAC,cAAc,GAAG,KAAK,CAAC;IAChC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
166
client/dist/js/socket-events/msg.js
vendored
Normal file
166
client/dist/js/socket-events/msg.js
vendored
Normal file
|
@ -0,0 +1,166 @@
|
|||
"use strict";
|
||||
import socket from "../socket";
|
||||
import cleanIrcMessage from "../helpers/ircmessageparser/cleanIrcMessage";
|
||||
import store from "../store";
|
||||
import {switchToChannel} from "../router";
|
||||
let pop;
|
||||
try {
|
||||
pop = new Audio();
|
||||
pop.src = "audio/pop.wav";
|
||||
} catch (e) {
|
||||
pop = {
|
||||
play() {},
|
||||
};
|
||||
}
|
||||
socket.on("msg", function (data) {
|
||||
const receivingChannel = store.getters.findChannel(data.chan);
|
||||
if (!receivingChannel) {
|
||||
return;
|
||||
}
|
||||
let channel = receivingChannel.channel;
|
||||
let isActiveChannel =
|
||||
store.state.activeChannel && store.state.activeChannel.channel === channel;
|
||||
// Display received notices and errors in currently active channel.
|
||||
// Reloading the page will put them back into the lobby window.
|
||||
if (data.msg.showInActive) {
|
||||
// We only want to put errors/notices in active channel if they arrive on the same network
|
||||
if (
|
||||
store.state.activeChannel &&
|
||||
store.state.activeChannel.network === receivingChannel.network
|
||||
) {
|
||||
channel = store.state.activeChannel.channel;
|
||||
// Do not update unread/highlight counters for this channel
|
||||
// as we are putting this message in the active channel
|
||||
isActiveChannel = true;
|
||||
if (data.chan === channel.id) {
|
||||
// If active channel is the intended channel for this message,
|
||||
// remove the showInActive flag
|
||||
delete data.msg.showInActive;
|
||||
} else {
|
||||
data.chan = channel.id;
|
||||
}
|
||||
} else {
|
||||
delete data.msg.showInActive;
|
||||
}
|
||||
}
|
||||
// Do not set unread counter for channel if it is currently active on this client
|
||||
// It may increase on the server before it processes channel open event from this client
|
||||
if (!isActiveChannel) {
|
||||
if (typeof data.highlight !== "undefined") {
|
||||
channel.highlight = data.highlight;
|
||||
}
|
||||
if (typeof data.unread !== "undefined") {
|
||||
channel.unread = data.unread;
|
||||
}
|
||||
}
|
||||
channel.messages.push(data.msg);
|
||||
if (data.msg.self) {
|
||||
channel.firstUnread = data.msg.id;
|
||||
} else {
|
||||
notifyMessage(data.chan, channel, store.state.activeChannel, data.msg);
|
||||
}
|
||||
let messageLimit = 0;
|
||||
if (!isActiveChannel) {
|
||||
// If message arrives in non active channel, keep only 100 messages
|
||||
messageLimit = 100;
|
||||
} else if (channel.scrolledToBottom) {
|
||||
// If message arrives in active channel, keep 1500 messages if scroll is currently at the bottom
|
||||
// One history load may load up to 1000 messages at once if condendesed or hidden events are enabled
|
||||
messageLimit = 1500;
|
||||
}
|
||||
if (messageLimit > 0 && channel.messages.length > messageLimit) {
|
||||
channel.messages.splice(0, channel.messages.length - messageLimit);
|
||||
channel.moreHistoryAvailable = true;
|
||||
}
|
||||
if (channel.type === "channel") {
|
||||
updateUserList(channel, data.msg);
|
||||
}
|
||||
});
|
||||
function notifyMessage(targetId, channel, activeChannel, msg) {
|
||||
if (channel.muted) {
|
||||
return;
|
||||
}
|
||||
if (msg.highlight || (store.state.settings.notifyAllMessages && msg.type === "message")) {
|
||||
if (!document.hasFocus() || !activeChannel || activeChannel.channel !== channel) {
|
||||
if (store.state.settings.notification) {
|
||||
try {
|
||||
pop.play();
|
||||
} catch (exception) {
|
||||
// On mobile, sounds can not be played without user interaction.
|
||||
}
|
||||
}
|
||||
if (
|
||||
store.state.settings.desktopNotifications &&
|
||||
"Notification" in window &&
|
||||
Notification.permission === "granted"
|
||||
) {
|
||||
let title;
|
||||
let body;
|
||||
if (msg.type === "invite") {
|
||||
title = "New channel invite:";
|
||||
body = msg.from.nick + " invited you to " + msg.channel;
|
||||
} else {
|
||||
title = msg.from.nick;
|
||||
if (channel.type !== "query") {
|
||||
title += ` (${channel.name})`;
|
||||
}
|
||||
if (msg.type === "message") {
|
||||
title += " says:";
|
||||
}
|
||||
body = cleanIrcMessage(msg.text);
|
||||
}
|
||||
const timestamp = Date.parse(msg.time);
|
||||
try {
|
||||
if (store.state.hasServiceWorker) {
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.active.postMessage({
|
||||
type: "notification",
|
||||
chanId: targetId,
|
||||
timestamp: timestamp,
|
||||
title: title,
|
||||
body: body,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
const notify = new Notification(title, {
|
||||
tag: `chan-${targetId}`,
|
||||
badge: "img/icon-alerted-black-transparent-bg-72x72px.png",
|
||||
icon: "img/icon-alerted-grey-bg-192x192px.png",
|
||||
body: body,
|
||||
timestamp: timestamp,
|
||||
});
|
||||
notify.addEventListener("click", function () {
|
||||
this.close();
|
||||
window.focus();
|
||||
const channelTarget = store.getters.findChannel(targetId);
|
||||
if (channelTarget) {
|
||||
switchToChannel(channelTarget);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (exception) {
|
||||
// `new Notification(...)` is not supported and should be silenced.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function updateUserList(channel, msg) {
|
||||
if (msg.type === "message" || msg.type === "action") {
|
||||
const user = channel.users.find((u) => u.nick === msg.from.nick);
|
||||
if (user) {
|
||||
user.lastMessage = new Date(msg.time).getTime() || Date.now();
|
||||
}
|
||||
} else if (msg.type === "quit" || msg.type === "part") {
|
||||
const idx = channel.users.findIndex((u) => u.nick === msg.from.nick);
|
||||
if (idx > -1) {
|
||||
channel.users.splice(idx, 1);
|
||||
}
|
||||
} else if (msg.type === "kick") {
|
||||
const idx = channel.users.findIndex((u) => u.nick === msg.target.nick);
|
||||
if (idx > -1) {
|
||||
channel.users.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=msg.js.map
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue