thelounge/client/js/store.js
Reto Brunner e999171f29 Mentions window: filter list when we part a chan
Should some other client part a chan, then we need to clean
up the list from the mentions window in case it's open in ours.
2021-12-29 16:46:16 +01:00

230 lines
5.8 KiB
JavaScript

import Vue from "vue";
import Vuex from "vuex";
import {createSettingsStore} from "./store-settings";
import storage from "./localStorage";
const appName = document.title;
Vue.use(Vuex);
function detectDesktopNotificationState() {
if (!("Notification" in window)) {
return "unsupported";
} else if (Notification.permission === "granted") {
return "granted";
} else if (!window.isSecureContext) {
return "nohttps";
}
return "blocked";
}
const store = new Vuex.Store({
state: {
appLoaded: false,
activeChannel: null,
currentUserVisibleError: null,
desktopNotificationState: detectDesktopNotificationState(),
isAutoCompleting: false,
isConnected: false,
networks: [],
mentions: [],
hasServiceWorker: false,
pushNotificationState: "unsupported",
serverConfiguration: null,
sessions: [],
sidebarOpen: false,
sidebarDragging: false,
userlistOpen: storage.get("thelounge.state.userlist") !== "false",
versionData: null,
versionStatus: "loading",
versionDataExpired: false,
serverHasSettings: false,
messageSearchResults: null,
messageSearchInProgress: false,
searchEnabled: false,
},
mutations: {
appLoaded(state) {
state.appLoaded = true;
},
activeChannel(state, channel) {
state.activeChannel = channel;
},
currentUserVisibleError(state, error) {
state.currentUserVisibleError = error;
},
refreshDesktopNotificationState(state) {
state.desktopNotificationState = detectDesktopNotificationState();
},
isAutoCompleting(state, isAutoCompleting) {
state.isAutoCompleting = isAutoCompleting;
},
isConnected(state, payload) {
state.isConnected = payload;
},
networks(state, networks) {
state.networks = networks;
},
mentions(state, mentions) {
state.mentions = mentions;
},
removeNetwork(state, networkId) {
state.networks.splice(
store.state.networks.findIndex((n) => n.uuid === networkId),
1
);
},
sortNetworks(state, sortFn) {
state.networks.sort(sortFn);
},
hasServiceWorker(state) {
state.hasServiceWorker = true;
},
pushNotificationState(state, pushNotificationState) {
state.pushNotificationState = pushNotificationState;
},
serverConfiguration(state, serverConfiguration) {
state.serverConfiguration = serverConfiguration;
},
sessions(state, payload) {
state.sessions = payload;
},
sidebarOpen(state, payload) {
state.sidebarOpen = payload;
},
sidebarDragging(state, payload) {
state.sidebarDragging = payload;
},
toggleSidebar(state) {
state.sidebarOpen = !state.sidebarOpen;
},
toggleUserlist(state) {
state.userlistOpen = !state.userlistOpen;
},
userlistOpen(state, payload) {
state.userlistOpen = payload;
},
versionData(state, payload) {
state.versionData = payload;
},
versionStatus(state, payload) {
state.versionStatus = payload;
},
versionDataExpired(state, payload) {
state.versionDataExpired = payload;
},
serverHasSettings(state, value) {
state.serverHasSettings = value;
},
messageSearchInProgress(state, value) {
state.messageSearchInProgress = value;
},
messageSearchResults(state, value) {
state.messageSearchResults = value;
},
addMessageSearchResults(state, value) {
// Append the search results and add networks and channels to new messages
value.results = [...state.messageSearchResults.results, ...value.results];
state.messageSearchResults = value;
},
},
actions: {
partChannel({commit, state}, netChan) {
const mentions = state.mentions.filter((msg) => !(msg.chanId === netChan.channel.id));
commit("mentions", mentions);
},
},
getters: {
findChannelOnCurrentNetwork: (state) => (name) => {
name = name.toLowerCase();
return state.activeChannel.network.channels.find((c) => c.name.toLowerCase() === name);
},
findChannelOnNetwork: (state) => (networkUuid, channelName) => {
for (const network of state.networks) {
if (network.uuid !== networkUuid) {
continue;
}
for (const channel of network.channels) {
if (channel.name === channelName) {
return {network, channel};
}
}
}
return null;
},
findChannel: (state) => (id) => {
for (const network of state.networks) {
for (const channel of network.channels) {
if (channel.id === id) {
return {network, channel};
}
}
}
return null;
},
findNetwork: (state) => (uuid) => {
for (const network of state.networks) {
if (network.uuid === uuid) {
return network;
}
}
return null;
},
highlightCount(state) {
let highlightCount = 0;
for (const network of state.networks) {
for (const channel of network.channels) {
highlightCount += channel.highlight;
}
}
return highlightCount;
},
title(state, getters) {
const alertEventCount = getters.highlightCount ? `(${getters.highlightCount}) ` : "";
const channelname = state.activeChannel ? `${state.activeChannel.channel.name}` : "";
return alertEventCount + channelname + appName;
},
initChannel: () => (channel) => {
// TODO: This should be a mutation
channel.pendingMessage = "";
channel.inputHistoryPosition = 0;
channel.inputHistory = [""].concat(
channel.messages
.filter((m) => m.self && m.text && m.type === "message")
.map((m) => m.text)
.reverse()
.slice(null, 99)
);
channel.historyLoading = false;
channel.scrolledToBottom = true;
channel.editTopic = false;
channel.moreHistoryAvailable = channel.totalMessages > channel.messages.length;
delete channel.totalMessages;
if (channel.type === "channel") {
channel.usersOutdated = true;
}
return channel;
},
},
});
// Settings module is registered dynamically because it benefits
// from a direct reference to the store
store.registerModule("settings", createSettingsStore(store));
export default store;