serverless-ircd 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +6 -1
- package/.gitmodules +3 -0
- package/CHANGELOG.md +214 -0
- package/README.md +110 -23
- package/apps/aws-stack/package.json +1 -1
- package/apps/cf-tcp-container/package.json +1 -1
- package/apps/cf-worker/package.json +1 -1
- package/apps/cf-worker/src/origin-allowlist.ts +99 -0
- package/apps/cf-worker/src/worker.ts +89 -9
- package/apps/cf-worker/tests/fixtures/web-dist/app/index.html +18 -0
- package/apps/cf-worker/tests/fixtures/web-dist/index.html +18 -0
- package/apps/cf-worker/tests/origin-allowlist.test.ts +101 -0
- package/apps/cf-worker/tests/smoke.test.ts +28 -2
- package/apps/cf-worker/tests/ws-origin.test.ts +89 -0
- package/apps/cf-worker/wrangler.test.toml +23 -0
- package/apps/cf-worker/wrangler.toml +54 -0
- package/apps/local-cli/package.json +1 -1
- package/apps/web/landing/index.html +217 -0
- package/apps/web/package.json +28 -0
- package/apps/web/scripts/build.mjs +125 -0
- package/apps/web/src/build-env.ts +43 -0
- package/apps/web/src/config-schema.ts +138 -0
- package/apps/web/static/config.json +28 -0
- package/apps/web/static/config.prod.json +28 -0
- package/apps/web/static/config.staging.json +28 -0
- package/apps/web/tests/build-env.test.ts +63 -0
- package/apps/web/tests/build-smoke.test.ts +103 -0
- package/apps/web/tests/config-schema.test.ts +432 -0
- package/apps/web/tests/workspace.test.ts +12 -0
- package/apps/web/tsconfig.json +10 -0
- package/apps/web/upstream/.browserslistrc +3 -0
- package/apps/web/upstream/.editorconfig +9 -0
- package/apps/web/upstream/.eslintignore +3 -0
- package/apps/web/upstream/.eslintrc.js +90 -0
- package/apps/web/upstream/.github/FUNDING.yml +12 -0
- package/apps/web/upstream/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- package/apps/web/upstream/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/apps/web/upstream/.github/workflows/push.yml +26 -0
- package/apps/web/upstream/.github/workflows/release.yml +33 -0
- package/apps/web/upstream/.github/workflows/release_manual.yml +55 -0
- package/apps/web/upstream/.prettierrc.js +9 -0
- package/apps/web/upstream/.stylelintignore +5 -0
- package/apps/web/upstream/.stylelintrc.js +21 -0
- package/apps/web/upstream/LICENSE +201 -0
- package/apps/web/upstream/README.md +76 -0
- package/apps/web/upstream/babel.config.js +25 -0
- package/apps/web/upstream/crowdin.yml +3 -0
- package/apps/web/upstream/index.html +35 -0
- package/apps/web/upstream/jest.config.js +7 -0
- package/apps/web/upstream/jsdoc.json +22 -0
- package/apps/web/upstream/package.json +80 -0
- package/apps/web/upstream/scripts/pre-commit +43 -0
- package/apps/web/upstream/src/components/App.vue +516 -0
- package/apps/web/upstream/src/components/AppSettings.vue +587 -0
- package/apps/web/upstream/src/components/AutoComplete.vue +284 -0
- package/apps/web/upstream/src/components/Avatar.vue +105 -0
- package/apps/web/upstream/src/components/AwayStatusIndicator.vue +77 -0
- package/apps/web/upstream/src/components/BufferKey.vue +121 -0
- package/apps/web/upstream/src/components/BufferSettings.vue +97 -0
- package/apps/web/upstream/src/components/Captcha.vue +85 -0
- package/apps/web/upstream/src/components/ChannelBanlist.vue +96 -0
- package/apps/web/upstream/src/components/ChannelInfo.vue +159 -0
- package/apps/web/upstream/src/components/ChannelInvitelist.vue +276 -0
- package/apps/web/upstream/src/components/ChannelList.vue +345 -0
- package/apps/web/upstream/src/components/Container.vue +401 -0
- package/apps/web/upstream/src/components/ContainerHeader.vue +522 -0
- package/apps/web/upstream/src/components/ControlInput.vue +1016 -0
- package/apps/web/upstream/src/components/LoadingAnimation.vue +104 -0
- package/apps/web/upstream/src/components/MediaViewer.vue +199 -0
- package/apps/web/upstream/src/components/MessageInfo.vue +192 -0
- package/apps/web/upstream/src/components/MessageList.vue +1028 -0
- package/apps/web/upstream/src/components/MessageListAvatar.vue +20 -0
- package/apps/web/upstream/src/components/MessageListMessageCompact.vue +361 -0
- package/apps/web/upstream/src/components/MessageListMessageInline.vue +257 -0
- package/apps/web/upstream/src/components/MessageListMessageModern.vue +430 -0
- package/apps/web/upstream/src/components/NetworkSettings.vue +528 -0
- package/apps/web/upstream/src/components/Nicklist.vue +309 -0
- package/apps/web/upstream/src/components/NicklistUser.vue +181 -0
- package/apps/web/upstream/src/components/NotConnected.vue +271 -0
- package/apps/web/upstream/src/components/SelfUser.vue +283 -0
- package/apps/web/upstream/src/components/ServerSelector.vue +162 -0
- package/apps/web/upstream/src/components/ServerView.vue +126 -0
- package/apps/web/upstream/src/components/SettingsAdvanced.vue +232 -0
- package/apps/web/upstream/src/components/SettingsAliases.vue +121 -0
- package/apps/web/upstream/src/components/Sidebar.vue +429 -0
- package/apps/web/upstream/src/components/SidebarAboutBuffer.vue +288 -0
- package/apps/web/upstream/src/components/SidebarState.vue +145 -0
- package/apps/web/upstream/src/components/StartupError.vue +35 -0
- package/apps/web/upstream/src/components/StateBrowser.vue +420 -0
- package/apps/web/upstream/src/components/StateBrowserBuffer.vue +124 -0
- package/apps/web/upstream/src/components/StateBrowserNetwork.vue +823 -0
- package/apps/web/upstream/src/components/StateBrowserUsermenu.vue +162 -0
- package/apps/web/upstream/src/components/TypingStatusIndicator.vue +34 -0
- package/apps/web/upstream/src/components/TypingUsersList.vue +56 -0
- package/apps/web/upstream/src/components/UrlEmbed.vue +149 -0
- package/apps/web/upstream/src/components/UserBox.vue +728 -0
- package/apps/web/upstream/src/components/inputtools/Emoji.vue +67 -0
- package/apps/web/upstream/src/components/inputtools/TextStyle.vue +142 -0
- package/apps/web/upstream/src/components/startups/CommonLayout.vue +208 -0
- package/apps/web/upstream/src/components/startups/CustomServer.vue +495 -0
- package/apps/web/upstream/src/components/startups/KiwiBnc.vue +361 -0
- package/apps/web/upstream/src/components/startups/Personal.vue +317 -0
- package/apps/web/upstream/src/components/startups/Welcome.vue +544 -0
- package/apps/web/upstream/src/components/startups/ZncLogin.vue +229 -0
- package/apps/web/upstream/src/components/utils/InputConfirm.vue +68 -0
- package/apps/web/upstream/src/components/utils/InputPrompt.vue +118 -0
- package/apps/web/upstream/src/components/utils/InputText.vue +172 -0
- package/apps/web/upstream/src/components/utils/IrcInput.vue +579 -0
- package/apps/web/upstream/src/components/utils/PluginWrapper.vue +26 -0
- package/apps/web/upstream/src/components/utils/TabbedView.vue +149 -0
- package/apps/web/upstream/src/components/utils/TransitionExpand.vue +97 -0
- package/apps/web/upstream/src/helpers/Colours.js +128 -0
- package/apps/web/upstream/src/helpers/IrcdDiffs.js +26 -0
- package/apps/web/upstream/src/helpers/Md5.js +193 -0
- package/apps/web/upstream/src/helpers/Misc.js +401 -0
- package/apps/web/upstream/src/helpers/TextFormatting.js +237 -0
- package/apps/web/upstream/src/libs/AliasRewriter.js +157 -0
- package/apps/web/upstream/src/libs/AudioManager.js +60 -0
- package/apps/web/upstream/src/libs/BouncerMiddleware.js +247 -0
- package/apps/web/upstream/src/libs/BouncerProvider.js +551 -0
- package/apps/web/upstream/src/libs/ChathistoryMiddleware.js +153 -0
- package/apps/web/upstream/src/libs/ConfigLoader.js +94 -0
- package/apps/web/upstream/src/libs/EmojiProvider.js +46 -0
- package/apps/web/upstream/src/libs/GlobalApi.js +346 -0
- package/apps/web/upstream/src/libs/IPC.js +51 -0
- package/apps/web/upstream/src/libs/InputHandler.js +921 -0
- package/apps/web/upstream/src/libs/IrcClient.js +1506 -0
- package/apps/web/upstream/src/libs/Logger.js +71 -0
- package/apps/web/upstream/src/libs/Message.js +169 -0
- package/apps/web/upstream/src/libs/MessageFormatter.js +364 -0
- package/apps/web/upstream/src/libs/MessageParser.js +249 -0
- package/apps/web/upstream/src/libs/Notifications.js +78 -0
- package/apps/web/upstream/src/libs/ServerConnection.js +270 -0
- package/apps/web/upstream/src/libs/ServerSession.js +102 -0
- package/apps/web/upstream/src/libs/SoundBleep.js +20 -0
- package/apps/web/upstream/src/libs/StatePersistence.js +90 -0
- package/apps/web/upstream/src/libs/ThemeManager.js +128 -0
- package/apps/web/upstream/src/libs/TypingMiddleware.js +105 -0
- package/apps/web/upstream/src/libs/WindowTitle.js +63 -0
- package/apps/web/upstream/src/libs/batchedAdd.js +74 -0
- package/apps/web/upstream/src/libs/bufferTools.js +177 -0
- package/apps/web/upstream/src/libs/polyfill/Element.closest.js +18 -0
- package/apps/web/upstream/src/libs/renderers/Html.js +113 -0
- package/apps/web/upstream/src/libs/settingTools.js +31 -0
- package/apps/web/upstream/src/libs/state/BufferState.js +703 -0
- package/apps/web/upstream/src/libs/state/NetworkState.js +158 -0
- package/apps/web/upstream/src/libs/state/UserState.js +89 -0
- package/apps/web/upstream/src/libs/state/common.js +26 -0
- package/apps/web/upstream/src/libs/state.js +961 -0
- package/apps/web/upstream/src/libs/storage/Local.js +51 -0
- package/apps/web/upstream/src/main.js +566 -0
- package/apps/web/upstream/src/res/autocompleteCommands.js +31 -0
- package/apps/web/upstream/src/res/configTemplates.js +373 -0
- package/apps/web/upstream/src/res/globalStyle.css +277 -0
- package/apps/web/upstream/src/res/kiwiLoadingLogo.png +0 -0
- package/apps/web/upstream/src/res/locales/app.af-ZA.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.ar-SA.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.bg-BG.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.bs-BA.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.ca-ES.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.cs-CZ.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.da-DK.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.de-DE.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.dev.po +1246 -0
- package/apps/web/upstream/src/res/locales/app.el-GR.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.en-US.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.es-419.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.es-AR.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.es-EM.po +536 -0
- package/apps/web/upstream/src/res/locales/app.es-ES.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.es-US.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.eu-ES.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.fi-FI.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.fr-FR.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.gl-ES.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.he-IL.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.hi-IN.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.hu-HU.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.id-ID.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.it-IT.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.ja-JP.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.ko-KR.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.nl-NL.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.no-NO.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.pl-PL.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.pt-BR.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.pt-PT.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.ro-RO.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.ru-RU.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.sl-SI.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.sq-AL.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.sr-SP.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.sv-SE.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.tr-TR.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.uk-UA.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.vi-VN.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.zh-CN.po +1145 -0
- package/apps/web/upstream/src/res/locales/app.zh-TW.po +1145 -0
- package/apps/web/upstream/src/res/localesList.json +27 -0
- package/apps/web/upstream/src/res/logo.png +0 -0
- package/apps/web/upstream/src/thirdparty/about.html +43 -0
- package/apps/web/upstream/src/thirdparty/index.js +5 -0
- package/apps/web/upstream/src/thirdparty/kiwiirccom.vue +185 -0
- package/apps/web/upstream/static/config.json +28 -0
- package/apps/web/upstream/static/emoticons/smile.png +0 -0
- package/apps/web/upstream/static/favicon.png +0 -0
- package/apps/web/upstream/static/highlight.mp3 +0 -0
- package/apps/web/upstream/static/highlight.ogg +0 -0
- package/apps/web/upstream/static/locales/.gitignore +2 -0
- package/apps/web/upstream/static/plugins/customise.html.example +10 -0
- package/apps/web/upstream/static/themes/coffee/theme.css +145 -0
- package/apps/web/upstream/static/themes/common/base.css +1064 -0
- package/apps/web/upstream/static/themes/dark/theme.css +196 -0
- package/apps/web/upstream/static/themes/default/theme.css +92 -0
- package/apps/web/upstream/static/themes/elite/theme.css +248 -0
- package/apps/web/upstream/static/themes/grayfox/theme.css +143 -0
- package/apps/web/upstream/static/themes/nightswatch/theme.css +367 -0
- package/apps/web/upstream/static/themes/osprey/theme.css +115 -0
- package/apps/web/upstream/static/themes/radioactive/theme.css +1211 -0
- package/apps/web/upstream/static/themes/sky/theme.css +107 -0
- package/apps/web/upstream/tests/unit/BatchAdd.spec.js +174 -0
- package/apps/web/upstream/tests/unit/MessageParser.spec.js +125 -0
- package/apps/web/upstream/tests/unit/Misc.spec.js +24 -0
- package/apps/web/upstream/tests/unit/NetworkState.spec.js +58 -0
- package/apps/web/upstream/tests/unit/StartupError.spec.js +20 -0
- package/apps/web/upstream/vue.config.js +150 -0
- package/apps/web/upstream/yarn.lock +9767 -0
- package/apps/web/vitest.config.ts +13 -0
- package/biome.json +1 -0
- package/docs/Home.md +1 -0
- package/docs/WebClientGuide.md +535 -0
- package/package.json +2 -2
- package/packages/aws-adapter/package.json +1 -1
- package/packages/cf-adapter/package.json +1 -1
- package/packages/cf-adapter/tests/cf-harness.ts +12 -1
- package/packages/in-memory-runtime/package.json +1 -1
- package/packages/irc-core/package.json +1 -1
- package/packages/irc-core/reports/mutation/mutation.html +342 -0
- package/packages/irc-core/tests/batch.test.ts +15 -0
- package/packages/irc-core/tests/numerics.test.ts +13 -0
- package/packages/irc-core/tests/parser.test.ts +109 -0
- package/packages/irc-server/package.json +1 -1
- package/packages/irc-test-support/package.json +1 -1
- package/packages/irc-test-support/src/scenarios.ts +24 -2
- package/tools/ci-hardening/package.json +1 -1
- package/tools/load-test/package.json +1 -1
- package/tools/tcp-ws-forwarder/package.json +1 -1
|
@@ -0,0 +1,961 @@
|
|
|
1
|
+
'kiwi public';
|
|
2
|
+
|
|
3
|
+
import Vue from 'vue';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
|
|
6
|
+
import * as Misc from '@/helpers/Misc';
|
|
7
|
+
import * as TextFormatting from '@/helpers/TextFormatting';
|
|
8
|
+
import { configTemplates } from '@/res/configTemplates';
|
|
9
|
+
import NetworkState from './state/NetworkState';
|
|
10
|
+
import BufferState from './state/BufferState';
|
|
11
|
+
import UserState from './state/UserState';
|
|
12
|
+
import Message from './Message';
|
|
13
|
+
|
|
14
|
+
function createNewState() {
|
|
15
|
+
const stateObj = {
|
|
16
|
+
// May be set by a StatePersistence instance
|
|
17
|
+
persistence: null,
|
|
18
|
+
|
|
19
|
+
// Settings may be overridden via config.json
|
|
20
|
+
settings: configTemplates.default,
|
|
21
|
+
user_settings: {
|
|
22
|
+
},
|
|
23
|
+
connection: {
|
|
24
|
+
// disconnected / connecting / connected
|
|
25
|
+
status: 'connected',
|
|
26
|
+
sessionId: '',
|
|
27
|
+
},
|
|
28
|
+
ui: {
|
|
29
|
+
active_network: 0,
|
|
30
|
+
active_buffer: '',
|
|
31
|
+
last_active_buffers: [],
|
|
32
|
+
app_has_focus: true,
|
|
33
|
+
app_width: 0,
|
|
34
|
+
app_height: 0,
|
|
35
|
+
is_touch: false,
|
|
36
|
+
is_narrow: false,
|
|
37
|
+
favicon_counter: 0,
|
|
38
|
+
current_input: '',
|
|
39
|
+
input_history: [],
|
|
40
|
+
input_history_pos: 0,
|
|
41
|
+
show_advanced_tab: false,
|
|
42
|
+
},
|
|
43
|
+
networks: [],
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const userDict = new Vue({
|
|
47
|
+
data() {
|
|
48
|
+
return {
|
|
49
|
+
networks: {},
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
/*
|
|
53
|
+
(network id): {
|
|
54
|
+
(lowercase nick): UserState,
|
|
55
|
+
(lowercase nick): UserState,
|
|
56
|
+
},
|
|
57
|
+
*/
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const bufferDict = new Vue({
|
|
61
|
+
data() {
|
|
62
|
+
return {
|
|
63
|
+
networks: {},
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
/*
|
|
67
|
+
(network id): [
|
|
68
|
+
BufferState,
|
|
69
|
+
BufferState,
|
|
70
|
+
]
|
|
71
|
+
*/
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Messages are seperate from the above state object to keep them from being reactive. Saves CPU
|
|
75
|
+
const messages = [
|
|
76
|
+
/* {
|
|
77
|
+
networkid: 1,
|
|
78
|
+
buffer: '#kiwiirc',
|
|
79
|
+
messages: [
|
|
80
|
+
Message,
|
|
81
|
+
Message
|
|
82
|
+
],
|
|
83
|
+
}, */
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
const availableStartups = Object.create(null);
|
|
87
|
+
|
|
88
|
+
const state = new Vue({
|
|
89
|
+
data: stateObj,
|
|
90
|
+
methods: {
|
|
91
|
+
// Export enough state so that it can be imported in future to resume
|
|
92
|
+
exportState(includeBuffers) {
|
|
93
|
+
let toExport = {};
|
|
94
|
+
|
|
95
|
+
if (includeBuffers) {
|
|
96
|
+
toExport.networks = state.networks.map((network) => {
|
|
97
|
+
let networkObj = {
|
|
98
|
+
id: network.id,
|
|
99
|
+
name: network.name,
|
|
100
|
+
connection: {
|
|
101
|
+
nick: network.connection.nick,
|
|
102
|
+
server: network.connection.server,
|
|
103
|
+
port: network.connection.port,
|
|
104
|
+
tls: network.connection.tls,
|
|
105
|
+
path: network.connection.path,
|
|
106
|
+
password: network.connection.password,
|
|
107
|
+
direct: network.connection.direct,
|
|
108
|
+
encoding: network.connection.encoding,
|
|
109
|
+
bncnetid: network.connection.bncnetid,
|
|
110
|
+
},
|
|
111
|
+
auto_commands: network.auto_commands,
|
|
112
|
+
settings: _.cloneDeep(network.settings),
|
|
113
|
+
username: network.username,
|
|
114
|
+
gecos: network.gecos,
|
|
115
|
+
password: network.password,
|
|
116
|
+
hidden: network.hidden,
|
|
117
|
+
is_bnc: network.is_bnc,
|
|
118
|
+
buffers: [],
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
networkObj.buffers = network.buffers.map((buffer) => {
|
|
122
|
+
let bufferObj = {
|
|
123
|
+
name: buffer.name,
|
|
124
|
+
key: buffer.key,
|
|
125
|
+
enabled: !!buffer.enabled,
|
|
126
|
+
settings: _.cloneDeep(buffer.settings),
|
|
127
|
+
latest_messages: [],
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
buffer.latest_messages.forEach((msg) => {
|
|
131
|
+
bufferObj.latest_messages.push(msg.serialise());
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return bufferObj;
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return networkObj;
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
toExport.user_settings = state.user_settings;
|
|
142
|
+
|
|
143
|
+
return JSON.stringify(toExport);
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
// Import a previously exported state to continue that state
|
|
147
|
+
importState(stateStr) {
|
|
148
|
+
let importObj = JSON.parse(stateStr);
|
|
149
|
+
if (importObj && importObj.networks) {
|
|
150
|
+
this.resetState();
|
|
151
|
+
importObj.networks.forEach((importNetwork) => {
|
|
152
|
+
let network = new NetworkState(
|
|
153
|
+
importNetwork.id,
|
|
154
|
+
state,
|
|
155
|
+
userDict,
|
|
156
|
+
bufferDict
|
|
157
|
+
);
|
|
158
|
+
network.name = importNetwork.name;
|
|
159
|
+
network.connection = { ...network.connection, ...importNetwork.connection };
|
|
160
|
+
network.auto_commands = importNetwork.auto_commands || '';
|
|
161
|
+
network.settings = importNetwork.settings;
|
|
162
|
+
// First check importNetwork.nick as this was used in older versions
|
|
163
|
+
// TODO: Eventually remove this importNetwork.nick check
|
|
164
|
+
network.nick = importNetwork.nick || importNetwork.connection.nick;
|
|
165
|
+
if (!network.connection.nick && importNetwork.nick) {
|
|
166
|
+
network.connection.nick = importNetwork.nick;
|
|
167
|
+
}
|
|
168
|
+
network.username = importNetwork.username;
|
|
169
|
+
network.gecos = importNetwork.gecos;
|
|
170
|
+
network.password = importNetwork.password;
|
|
171
|
+
network.hidden = importNetwork.hidden;
|
|
172
|
+
network.is_bnc = importNetwork.is_bnc;
|
|
173
|
+
|
|
174
|
+
this.networks.push(network);
|
|
175
|
+
|
|
176
|
+
importNetwork.buffers.forEach((impBuffer) => {
|
|
177
|
+
let buffer = new BufferState(
|
|
178
|
+
impBuffer.name,
|
|
179
|
+
network.id,
|
|
180
|
+
state,
|
|
181
|
+
messages
|
|
182
|
+
);
|
|
183
|
+
buffer.key = impBuffer.key;
|
|
184
|
+
buffer.enabled = !!impBuffer.enabled;
|
|
185
|
+
buffer.settings = impBuffer.settings;
|
|
186
|
+
|
|
187
|
+
let latestMessages = impBuffer.latest_messages || [];
|
|
188
|
+
latestMessages.forEach((msg) => {
|
|
189
|
+
buffer.latest_messages.push(new Message(msg));
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
network.buffers.push(buffer);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (importObj && importObj.user_settings) {
|
|
198
|
+
this.user_settings = importObj.user_settings;
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
resetState() {
|
|
203
|
+
this.$set(this.$data, 'user_settings', {});
|
|
204
|
+
this.$set(this.$data, 'networks', []);
|
|
205
|
+
messages.splice(0);
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
setting(name, val) {
|
|
209
|
+
if (typeof val !== 'undefined') {
|
|
210
|
+
if (val === this.getSetting('settings.' + name)) {
|
|
211
|
+
// Remove setting from user_settings if its the default
|
|
212
|
+
return this.setSetting('user_settings.' + name, null);
|
|
213
|
+
}
|
|
214
|
+
// Setting any setting always goes into the user own settings space
|
|
215
|
+
return this.setSetting('user_settings.' + name, val);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Check the user specific settings before reverting to global settings
|
|
219
|
+
let userSetting = this.getSetting('user_settings.' + name);
|
|
220
|
+
let result = typeof userSetting !== 'undefined' ?
|
|
221
|
+
userSetting :
|
|
222
|
+
this.getSetting('settings.' + name);
|
|
223
|
+
|
|
224
|
+
return result;
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
// Accept 'dotted.notation' to read a state property of any depth
|
|
228
|
+
getSetting(name) {
|
|
229
|
+
let parts = name.split('.');
|
|
230
|
+
let val = this.$data;
|
|
231
|
+
|
|
232
|
+
for (let i = 0; i < parts.length; i++) {
|
|
233
|
+
val = val[parts[i]];
|
|
234
|
+
if (typeof val === 'undefined') {
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return val;
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
// Accept 'dotted.notation' to set a state property of any depth
|
|
243
|
+
setSetting(name, newVal) {
|
|
244
|
+
let parts = name.split('.');
|
|
245
|
+
let val = this.$data;
|
|
246
|
+
|
|
247
|
+
for (let i = 0; i < parts.length; i++) {
|
|
248
|
+
let propName = parts[i];
|
|
249
|
+
let nextVal = val[propName];
|
|
250
|
+
|
|
251
|
+
if (i < parts.length - 1 && typeof nextVal === 'undefined') {
|
|
252
|
+
nextVal = this.$set(val, propName, {});
|
|
253
|
+
} else if (i === parts.length - 1) {
|
|
254
|
+
if (newVal === null) {
|
|
255
|
+
this.$delete(val, propName);
|
|
256
|
+
} else {
|
|
257
|
+
this.$set(val, propName, newVal);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
val = nextVal;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return val;
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
getActiveNetwork() {
|
|
268
|
+
return this.getNetwork(this.ui.active_network);
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
getNetwork(networkid) {
|
|
272
|
+
let network = _.find(this.networks, {
|
|
273
|
+
id: networkid,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
return network;
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
getNetworkFromAddress(netAddr) {
|
|
280
|
+
return _.find(this.networks, (net) => {
|
|
281
|
+
let isMatch = netAddr.toLowerCase() === net.connection.server.toLowerCase();
|
|
282
|
+
return isMatch;
|
|
283
|
+
});
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
getNetworkFromBncNetId(bncnetid) {
|
|
287
|
+
return _.find(this.networks, (net) => bncnetid === net.connection.bncnetid);
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
addNetwork(name, nick, serverInfo) {
|
|
291
|
+
// Find the current largest ID and increment it by 1
|
|
292
|
+
function networkidReduce(currentMax, network) {
|
|
293
|
+
return network.id > currentMax ?
|
|
294
|
+
network.id :
|
|
295
|
+
currentMax;
|
|
296
|
+
}
|
|
297
|
+
let networkid = serverInfo.channelId ?
|
|
298
|
+
parseInt(serverInfo.channelId, 10) :
|
|
299
|
+
_.reduce(this.networks, networkidReduce, 0) + 1;
|
|
300
|
+
|
|
301
|
+
let network = new NetworkState(networkid, state, userDict, bufferDict);
|
|
302
|
+
network.name = name;
|
|
303
|
+
network.username = serverInfo.username;
|
|
304
|
+
network.gecos = serverInfo.gecos;
|
|
305
|
+
network.password = serverInfo.account_password || '';
|
|
306
|
+
network.connection.password = serverInfo.password;
|
|
307
|
+
network.connection.nick = nick;
|
|
308
|
+
network.connection.server = serverInfo.server || '';
|
|
309
|
+
network.connection.port = serverInfo.port || 6667;
|
|
310
|
+
network.connection.tls = serverInfo.tls || false;
|
|
311
|
+
network.connection.path = serverInfo.path || '';
|
|
312
|
+
network.connection.direct = !!serverInfo.direct;
|
|
313
|
+
network.connection.path = serverInfo.path || '';
|
|
314
|
+
network.connection.encoding = serverInfo.encoding || 'utf8';
|
|
315
|
+
network.connection.bncnetid = serverInfo.bncnetid || '';
|
|
316
|
+
|
|
317
|
+
if (serverInfo.services) {
|
|
318
|
+
network.services = serverInfo.services;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
this.networks.push(network);
|
|
322
|
+
|
|
323
|
+
// Add the server server buffer
|
|
324
|
+
this.addBuffer(network.id, '*').joined = true;
|
|
325
|
+
|
|
326
|
+
let eventObj = { network };
|
|
327
|
+
state.$emit('network.new', eventObj);
|
|
328
|
+
|
|
329
|
+
return network;
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
removeNetwork(networkid) {
|
|
333
|
+
let network = this.getNetwork(networkid);
|
|
334
|
+
if (!network) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (network.state === 'connected') {
|
|
339
|
+
network.ircClient.quit();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
while (network.buffers.length > 0) {
|
|
343
|
+
this.removeBuffer(network.buffers[0]);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
let findNewNetwork = false;
|
|
347
|
+
if (network === this.getActiveNetwork()) {
|
|
348
|
+
findNewNetwork = true;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
let idx = this.networks.indexOf(network);
|
|
352
|
+
this.networks.splice(idx, 1);
|
|
353
|
+
|
|
354
|
+
if (findNewNetwork) {
|
|
355
|
+
this.openLastActiveBuffer();
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
let eventObj = { network };
|
|
359
|
+
state.$emit('network.removed', eventObj);
|
|
360
|
+
},
|
|
361
|
+
|
|
362
|
+
getActiveBuffer() {
|
|
363
|
+
return this.getBufferByName(this.ui.active_network, this.ui.active_buffer);
|
|
364
|
+
},
|
|
365
|
+
|
|
366
|
+
setActiveBuffer(networkid, bufferName) {
|
|
367
|
+
if (!networkid) {
|
|
368
|
+
this.ui.active_network = 0;
|
|
369
|
+
this.ui.active_buffer = '';
|
|
370
|
+
} else {
|
|
371
|
+
if (this.settings.useBufferHistory && this.ui.active_network) {
|
|
372
|
+
// Keep track of last 20 viewed buffers. When closing buffers we can go back
|
|
373
|
+
// to one of the previous ones
|
|
374
|
+
this.ui.last_active_buffers.push({
|
|
375
|
+
networkid: this.ui.active_network,
|
|
376
|
+
bufferName: this.ui.active_buffer,
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
let lastActive = this.ui.last_active_buffers;
|
|
380
|
+
this.ui.last_active_buffers = lastActive.splice(lastActive.length - 20);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
this.ui.active_network = networkid;
|
|
384
|
+
this.ui.active_buffer = bufferName;
|
|
385
|
+
|
|
386
|
+
// Clear any unread messages counters for this buffer
|
|
387
|
+
let buffer = this.getBufferByName(networkid, bufferName);
|
|
388
|
+
if (buffer && buffer.flags.unread) {
|
|
389
|
+
buffer.flags.unread = 0;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Update the buffers last read time
|
|
393
|
+
if (buffer) {
|
|
394
|
+
buffer.markAsRead(true);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
|
|
399
|
+
openLastActiveBuffer: function openLastActiveBuffer() {
|
|
400
|
+
// if not using buffer history, just unset the active buffer
|
|
401
|
+
if (!this.settings.useBufferHistory) {
|
|
402
|
+
this.setActiveBuffer();
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
let targetNetwork;
|
|
407
|
+
let targetBuffer;
|
|
408
|
+
let lastActive = this.ui.last_active_buffers;
|
|
409
|
+
|
|
410
|
+
// Find the last buffer in our history that still exists
|
|
411
|
+
for (let i = lastActive.length - 1; i >= 0; i--) {
|
|
412
|
+
let network = this.getNetwork(lastActive[i].networkid);
|
|
413
|
+
if (!network) {
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
let buffer = network.bufferByName(lastActive[i].bufferName);
|
|
418
|
+
if (!buffer) {
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
targetNetwork = network;
|
|
423
|
+
targetBuffer = buffer;
|
|
424
|
+
|
|
425
|
+
// Trim the buffer history to this point
|
|
426
|
+
lastActive.splice(i);
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Try to find a suitable buffer
|
|
431
|
+
if (!targetBuffer) {
|
|
432
|
+
let network = this.getActiveNetwork() || this.networks[0];
|
|
433
|
+
if (network) {
|
|
434
|
+
targetNetwork = network;
|
|
435
|
+
let buffer = network.buffers[1];
|
|
436
|
+
if (buffer) {
|
|
437
|
+
targetBuffer = buffer;
|
|
438
|
+
} else {
|
|
439
|
+
targetBuffer = network.serverBuffer();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (targetBuffer) {
|
|
445
|
+
this.setActiveBuffer(targetNetwork.id, targetBuffer.name);
|
|
446
|
+
} else {
|
|
447
|
+
this.setActiveBuffer();
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
|
|
451
|
+
updateBufferLastRead(networkid, bufferName) {
|
|
452
|
+
let buffer = this.getBufferByName(networkid, bufferName);
|
|
453
|
+
if (buffer) {
|
|
454
|
+
buffer.last_read = Date.now();
|
|
455
|
+
buffer.active_timeout = null;
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
|
|
459
|
+
getOrAddBufferByName(networkid, bufferName) {
|
|
460
|
+
let network = this.getNetwork(networkid);
|
|
461
|
+
if (!network) {
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
let toMatch = bufferName.toLowerCase();
|
|
466
|
+
let buffer = _.find(network.buffers, (b) => b.name.toLowerCase() === toMatch);
|
|
467
|
+
|
|
468
|
+
if (!buffer) {
|
|
469
|
+
buffer = this.addBuffer(networkid, bufferName);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
return buffer;
|
|
473
|
+
},
|
|
474
|
+
|
|
475
|
+
getBufferByName(networkid, bufferName) {
|
|
476
|
+
if (!bufferName) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
let network = this.getNetwork(networkid);
|
|
481
|
+
if (!network) {
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
let toMatch = bufferName.toLowerCase();
|
|
486
|
+
let buffer = _.find(network.buffers, (b) => b.name.toLowerCase() === toMatch);
|
|
487
|
+
|
|
488
|
+
return buffer;
|
|
489
|
+
},
|
|
490
|
+
|
|
491
|
+
addBuffer(networkid, bufferName) {
|
|
492
|
+
if (!bufferName) {
|
|
493
|
+
return false;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// If we already have this buffer, don't re-add it
|
|
497
|
+
let buffer = this.getBufferByName(networkid, bufferName);
|
|
498
|
+
if (buffer) {
|
|
499
|
+
return buffer;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Make sure we at least we have this network
|
|
503
|
+
let network = this.getNetwork(networkid);
|
|
504
|
+
if (!network) {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
buffer = new BufferState(bufferName, network.id, state, messages);
|
|
509
|
+
network.buffers.push(buffer);
|
|
510
|
+
|
|
511
|
+
let eventObj = { buffer };
|
|
512
|
+
state.$emit('buffer.new', eventObj);
|
|
513
|
+
|
|
514
|
+
return buffer;
|
|
515
|
+
},
|
|
516
|
+
|
|
517
|
+
removeBuffer(buffer) {
|
|
518
|
+
let isActiveBuffer = (this.getActiveBuffer() === buffer);
|
|
519
|
+
|
|
520
|
+
let network = this.getNetwork(buffer.networkid);
|
|
521
|
+
if (!network) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
let eventObj = { buffer };
|
|
526
|
+
state.$emit('buffer.close', eventObj);
|
|
527
|
+
|
|
528
|
+
let bufferIdx = network.buffers.indexOf(buffer);
|
|
529
|
+
if (bufferIdx > -1) {
|
|
530
|
+
network.buffers.splice(bufferIdx, 1);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
let messageIdx = _.findIndex(messages, {
|
|
534
|
+
networkid: network.id,
|
|
535
|
+
buffer: buffer.name,
|
|
536
|
+
});
|
|
537
|
+
if (messageIdx > -1) {
|
|
538
|
+
messages.splice(messageIdx, 1);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (buffer.isChannel() && buffer.joined) {
|
|
542
|
+
network.ircClient.part(buffer.name);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// Remove the user from network state if no remaining common channels
|
|
546
|
+
if (buffer.isQuery()) {
|
|
547
|
+
let remainingBuffers = state.getBuffersWithUser(network.id, buffer.name);
|
|
548
|
+
if (remainingBuffers.length === 0) {
|
|
549
|
+
state.removeUser(network.d, {
|
|
550
|
+
nick: buffer.name,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
if (isActiveBuffer) {
|
|
556
|
+
this.openLastActiveBuffer();
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Remove this buffer from any users
|
|
560
|
+
/* eslint-disable guard-for-in */
|
|
561
|
+
Object.keys(buffer.users).forEach((nick) => {
|
|
562
|
+
let user = buffer.users[nick];
|
|
563
|
+
delete user.buffers[buffer.id];
|
|
564
|
+
});
|
|
565
|
+
},
|
|
566
|
+
|
|
567
|
+
addMessage(buffer, message) {
|
|
568
|
+
// Some messages try to be added after a network has been removed, meaning no buffer
|
|
569
|
+
// will be available
|
|
570
|
+
if (!buffer || !buffer.getNetwork()) {
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
let user = this.getUser(buffer.networkid, message.nick);
|
|
575
|
+
let bufferMessage = new Message(message, user);
|
|
576
|
+
if (user && user.ignore) {
|
|
577
|
+
bufferMessage.ignore = true;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
buffer.addMessage(bufferMessage);
|
|
581
|
+
|
|
582
|
+
// Increment the unread counter if this buffer is not active
|
|
583
|
+
let includeAsActivity = false;
|
|
584
|
+
let typesForActivty = ['privmsg', 'action', 'notice', 'wallops'];
|
|
585
|
+
if (buffer.setting('traffic_as_activity') && message.type === 'traffic') {
|
|
586
|
+
typesForActivty.push('traffic');
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (typesForActivty.indexOf(message.type) > -1) {
|
|
590
|
+
includeAsActivity = true;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if (buffer.setting('server_as_activity') && buffer.isServer()) {
|
|
594
|
+
includeAsActivity = true;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
let isActiveBuffer = (
|
|
598
|
+
buffer.networkid === this.ui.active_network &&
|
|
599
|
+
buffer.name === this.ui.active_buffer
|
|
600
|
+
);
|
|
601
|
+
|
|
602
|
+
let network = buffer.getNetwork();
|
|
603
|
+
let isNewMessage = message.time >= buffer.last_read;
|
|
604
|
+
let isHighlight = !network || buffer.isRaw() ?
|
|
605
|
+
false :
|
|
606
|
+
Misc.mentionsNick(bufferMessage.message, network.ircClient.user.nick);
|
|
607
|
+
|
|
608
|
+
if (message.type && message.type === 'invite') {
|
|
609
|
+
// Invites should be treated as highlights
|
|
610
|
+
isHighlight = true;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// Check for extra custom highlight words
|
|
614
|
+
let extraHighlights = (state.setting('highlights') || '').toLowerCase().split(' ');
|
|
615
|
+
if (!isHighlight && !buffer.isRaw() && extraHighlights.length > 0) {
|
|
616
|
+
extraHighlights.forEach((word) => {
|
|
617
|
+
if (!word) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
if (bufferMessage.message.toLowerCase().indexOf(word) > -1) {
|
|
622
|
+
isHighlight = true;
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (!buffer.isRaw() && state.setting('teamHighlights')) {
|
|
628
|
+
let m = bufferMessage.message;
|
|
629
|
+
let patterns = {
|
|
630
|
+
everyone: /(^|\s)@everybody($|\s|[,.;])/,
|
|
631
|
+
channel: /(^|\s)@channel($|\s|[,.;])/,
|
|
632
|
+
here: /(^|\s)@here($|\s|[,.;])/,
|
|
633
|
+
};
|
|
634
|
+
if (m.match(patterns.everyone) || m.match(patterns.channel)) {
|
|
635
|
+
isHighlight = true;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
if (m.match(patterns.here) && network && !network.away) {
|
|
639
|
+
isHighlight = true;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
bufferMessage.isHighlight = isHighlight;
|
|
644
|
+
|
|
645
|
+
if (isNewMessage && isActiveBuffer && state.ui.app_has_focus) {
|
|
646
|
+
buffer.last_read = message.time;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// Handle buffer flags
|
|
650
|
+
if (isNewMessage && includeAsActivity && !isActiveBuffer && !bufferMessage.ignore) {
|
|
651
|
+
buffer.incrementFlag('unread');
|
|
652
|
+
if (isHighlight) {
|
|
653
|
+
buffer.flag('highlight', true);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Handle any notifications
|
|
658
|
+
let settingAlertOn = buffer.setting('alert_on');
|
|
659
|
+
let isSelf = !network ? false : message.nick === network.nick;
|
|
660
|
+
if (
|
|
661
|
+
isNewMessage &&
|
|
662
|
+
settingAlertOn !== 'never' &&
|
|
663
|
+
message.type !== 'nick' &&
|
|
664
|
+
message.type !== 'mode' &&
|
|
665
|
+
message.type !== 'traffic' &&
|
|
666
|
+
!buffer.isSpecial() &&
|
|
667
|
+
!bufferMessage.ignore &&
|
|
668
|
+
!isSelf
|
|
669
|
+
) {
|
|
670
|
+
let notifyTitle = '';
|
|
671
|
+
let notifyMessage = message.nick ?
|
|
672
|
+
message.nick + ': ' :
|
|
673
|
+
'';
|
|
674
|
+
notifyMessage += message.message;
|
|
675
|
+
|
|
676
|
+
if (isHighlight) {
|
|
677
|
+
notifyTitle = TextFormatting.t('notification_mentioned', { channel: buffer.name });
|
|
678
|
+
} else if (settingAlertOn === 'message' && !isHighlight) {
|
|
679
|
+
notifyTitle = buffer.name;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (notifyTitle) {
|
|
683
|
+
this.$emit('notification.show', notifyMessage, {
|
|
684
|
+
title: notifyTitle,
|
|
685
|
+
onclick: () => {
|
|
686
|
+
state.setActiveBuffer(buffer.networkid, buffer.name);
|
|
687
|
+
|
|
688
|
+
// Newer webkit browser use parent.focus() while older webkit uses
|
|
689
|
+
// window.focus()
|
|
690
|
+
/* eslint-disable no-restricted-globals */
|
|
691
|
+
if (parent && parent.focus) {
|
|
692
|
+
parent.focus();
|
|
693
|
+
}
|
|
694
|
+
if (window.focus) {
|
|
695
|
+
window.focus();
|
|
696
|
+
}
|
|
697
|
+
},
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
if (
|
|
703
|
+
isActiveBuffer &&
|
|
704
|
+
!state.ui.app_has_focus &&
|
|
705
|
+
message.type !== 'traffic' &&
|
|
706
|
+
(
|
|
707
|
+
(buffer.setting('flash_title') === 'message') ||
|
|
708
|
+
(buffer.setting('flash_title') === 'highlight' && isHighlight)
|
|
709
|
+
)
|
|
710
|
+
) {
|
|
711
|
+
this.$emit('notification.title', true);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
this.$emit('message.new', { message: bufferMessage, buffer });
|
|
715
|
+
},
|
|
716
|
+
|
|
717
|
+
addMessageNoRepeat(buffer, message) {
|
|
718
|
+
// Add a message to the buffer only if it does not match the previous message
|
|
719
|
+
|
|
720
|
+
if (!buffer || !buffer.getNetwork()) {
|
|
721
|
+
// Some messages try to be added after a network has been removed,
|
|
722
|
+
// meaning no buffer will be available
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
let lastMessage = buffer.getLastMessage();
|
|
727
|
+
if (lastMessage && lastMessage.message === message.message) {
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
this.addMessage(buffer, message);
|
|
732
|
+
},
|
|
733
|
+
|
|
734
|
+
getUser(networkid, nick, usersArr_) {
|
|
735
|
+
let user = null;
|
|
736
|
+
let users = usersArr_;
|
|
737
|
+
|
|
738
|
+
if (!users) {
|
|
739
|
+
let network = this.getNetwork(networkid);
|
|
740
|
+
if (network) {
|
|
741
|
+
users = network.users;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
if (users) {
|
|
746
|
+
user = users[nick.toUpperCase()];
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
return user;
|
|
750
|
+
},
|
|
751
|
+
|
|
752
|
+
// Modify a networks user array without hitting vues reactive system until fn()
|
|
753
|
+
// has completed. Good for making large changes in bulk
|
|
754
|
+
usersTransaction(networkid, fn) {
|
|
755
|
+
let network = this.getNetwork(networkid);
|
|
756
|
+
if (!network) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
let users = Object.assign(Object.create(null), network.users);
|
|
761
|
+
fn(users);
|
|
762
|
+
network.users = users;
|
|
763
|
+
},
|
|
764
|
+
|
|
765
|
+
addUser(networkid, user, usersArr_) {
|
|
766
|
+
let network = null;
|
|
767
|
+
|
|
768
|
+
// Accept either a network ID or a direct network object
|
|
769
|
+
if (typeof networkid === 'number') {
|
|
770
|
+
network = this.getNetwork(networkid);
|
|
771
|
+
} else {
|
|
772
|
+
network = networkid;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if (!network) {
|
|
776
|
+
return null;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
let usersArr = usersArr_ || network.users;
|
|
780
|
+
let userObj = null;
|
|
781
|
+
|
|
782
|
+
if (!usersArr[user.nick.toUpperCase()]) {
|
|
783
|
+
userObj = usersArr[user.nick.toUpperCase()] = new UserState(user);
|
|
784
|
+
} else {
|
|
785
|
+
// Update the existing user object with any new info we have
|
|
786
|
+
userObj = state.getUser(network.id, user.nick, usersArr);
|
|
787
|
+
_.each(user, (val, prop) => {
|
|
788
|
+
if (typeof val !== 'undefined') {
|
|
789
|
+
userObj[prop] = val;
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
return userObj;
|
|
795
|
+
},
|
|
796
|
+
|
|
797
|
+
removeUser(networkid, user) {
|
|
798
|
+
let network = this.getNetwork(networkid);
|
|
799
|
+
if (!network) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
let buffers = state.getBuffersWithUser(networkid, user.nick);
|
|
804
|
+
buffers.forEach((buffer) => {
|
|
805
|
+
state.removeUserFromBuffer(buffer, user.nick);
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
this.$delete(network.users, user.nick.toUpperCase());
|
|
809
|
+
},
|
|
810
|
+
|
|
811
|
+
addMultipleUsersToBuffer(buffer, newUsers) {
|
|
812
|
+
let network = this.getNetwork(buffer.networkid);
|
|
813
|
+
let bufUsers = Object.assign(Object.create(null), buffer.users);
|
|
814
|
+
|
|
815
|
+
state.usersTransaction(network.id, (users) => {
|
|
816
|
+
newUsers.forEach((newUser) => {
|
|
817
|
+
let user = newUser.user;
|
|
818
|
+
let modes = newUser.modes;
|
|
819
|
+
let userObj = state.getUser(network.id, user.nick, users);
|
|
820
|
+
|
|
821
|
+
if (!userObj) {
|
|
822
|
+
userObj = this.addUser(network, user, users);
|
|
823
|
+
}
|
|
824
|
+
bufUsers[userObj.nick.toUpperCase()] = userObj;
|
|
825
|
+
|
|
826
|
+
// Add the buffer to the users buffer list
|
|
827
|
+
if (!userObj.buffers[buffer.id]) {
|
|
828
|
+
state.$set(userObj.buffers, buffer.id, {
|
|
829
|
+
modes: modes || [],
|
|
830
|
+
buffer: buffer,
|
|
831
|
+
});
|
|
832
|
+
} else {
|
|
833
|
+
userObj.buffers[buffer.id].modes = modes || [];
|
|
834
|
+
}
|
|
835
|
+
});
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
buffer.users = bufUsers;
|
|
839
|
+
},
|
|
840
|
+
|
|
841
|
+
addUserToBuffer(buffer, user, modes) {
|
|
842
|
+
let network = this.getNetwork(buffer.networkid);
|
|
843
|
+
let userObj = state.getUser(network.id, user.nick);
|
|
844
|
+
|
|
845
|
+
if (!userObj) {
|
|
846
|
+
userObj = this.addUser(network, user);
|
|
847
|
+
} else {
|
|
848
|
+
// Verify the user object is correct
|
|
849
|
+
_.each(user, (val, prop) => {
|
|
850
|
+
if (userObj[prop] !== val) {
|
|
851
|
+
userObj[prop] = val;
|
|
852
|
+
}
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
buffer.addUser(userObj);
|
|
857
|
+
|
|
858
|
+
// Add the buffer to the users buffer list
|
|
859
|
+
if (!userObj.buffers[buffer.id]) {
|
|
860
|
+
state.$set(userObj.buffers, buffer.id, {
|
|
861
|
+
modes: modes || [],
|
|
862
|
+
buffer: buffer,
|
|
863
|
+
});
|
|
864
|
+
} else {
|
|
865
|
+
state.$set(userObj.buffers[buffer.id], 'modes', modes || []);
|
|
866
|
+
}
|
|
867
|
+
},
|
|
868
|
+
|
|
869
|
+
removeUserFromBuffer(buffer, nick) {
|
|
870
|
+
buffer.removeUser(nick);
|
|
871
|
+
},
|
|
872
|
+
|
|
873
|
+
getBuffersWithUser(networkid, nick) {
|
|
874
|
+
let network = this.getNetwork(networkid);
|
|
875
|
+
if (!network) {
|
|
876
|
+
return [];
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
let buffers = [];
|
|
880
|
+
network.buffers.forEach((buffer) => {
|
|
881
|
+
if (buffer.hasNick(nick)) {
|
|
882
|
+
buffers.push(buffer);
|
|
883
|
+
} else if (nick === network.nick && buffer.isQuery()) {
|
|
884
|
+
buffers.push(buffer);
|
|
885
|
+
}
|
|
886
|
+
});
|
|
887
|
+
|
|
888
|
+
return buffers;
|
|
889
|
+
},
|
|
890
|
+
|
|
891
|
+
changeUserNick(networkid, oldNick, newNick) {
|
|
892
|
+
let network = this.getNetwork(networkid);
|
|
893
|
+
if (!network) {
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
let user = state.getUser(network.id, oldNick);
|
|
898
|
+
if (!user) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
let normalisedNew = newNick.toUpperCase();
|
|
903
|
+
let normalisedOld = oldNick.toUpperCase();
|
|
904
|
+
|
|
905
|
+
user.key = normalisedNew;
|
|
906
|
+
user.nick = newNick;
|
|
907
|
+
|
|
908
|
+
// If the nick has completely changed (ie. not just a case change) then update all
|
|
909
|
+
// associated buffers user lists
|
|
910
|
+
if (normalisedOld !== normalisedNew) {
|
|
911
|
+
state.$set(network.users, normalisedNew, network.users[normalisedOld]);
|
|
912
|
+
state.$delete(network.users, normalisedOld);
|
|
913
|
+
|
|
914
|
+
Object.keys(user.buffers).forEach((bufferId) => {
|
|
915
|
+
let buffer = user.buffers[bufferId].buffer;
|
|
916
|
+
if (!buffer.addUserBatch.queue().includes(user)) {
|
|
917
|
+
// The user is not in the queue to be added to the buffer
|
|
918
|
+
state.$set(buffer.users, normalisedNew, buffer.users[normalisedOld]);
|
|
919
|
+
state.$delete(buffer.users, normalisedOld);
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
let buffer = this.getBufferByName(network.id, oldNick);
|
|
925
|
+
if (buffer) {
|
|
926
|
+
buffer.rename(newNick);
|
|
927
|
+
}
|
|
928
|
+
},
|
|
929
|
+
|
|
930
|
+
getStartups() {
|
|
931
|
+
return availableStartups;
|
|
932
|
+
},
|
|
933
|
+
},
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
return state;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
let instance = null;
|
|
940
|
+
function singleton() {
|
|
941
|
+
instance = instance || createNewState();
|
|
942
|
+
return instance;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
singleton.create = function createState() {
|
|
946
|
+
return createNewState();
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
singleton.recreate = function recreateState() {
|
|
950
|
+
if (instance) {
|
|
951
|
+
instance.resetState();
|
|
952
|
+
instance.$destroy();
|
|
953
|
+
// eslint-disable-next-line
|
|
954
|
+
instance._watchers.splice(0, instance._watchers.length);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
instance = createNewState();
|
|
958
|
+
return instance;
|
|
959
|
+
};
|
|
960
|
+
|
|
961
|
+
export default singleton;
|