Move options to vuex

Co-Authored-By: Tim Miller-Williams <timmw@users.noreply.github.com>
This commit is contained in:
Pavel Djundik 2019-11-03 20:05:19 +02:00
parent 743ae987ec
commit c26de4cf6a
14 changed files with 124 additions and 92 deletions

View File

@ -4,9 +4,9 @@
id="chat" id="chat"
:data-id="channel.id" :data-id="channel.id"
:class="{ :class="{
'hide-motd': !this.$root.settings.motd, 'hide-motd': !$store.state.settings.motd,
'colored-nicks': this.$root.settings.coloredNicks, 'colored-nicks': $store.state.settings.coloredNicks,
'show-seconds': this.$root.settings.showSeconds, 'show-seconds': $store.state.settings.showSeconds,
}" }"
> >
<div <div

View File

@ -92,7 +92,7 @@ export default {
}, },
}, },
mounted() { mounted() {
if (this.$root.settings.autocomplete) { if (this.$store.state.settings.autocomplete) {
require("../js/autocompletion").enable(this.$refs.input); require("../js/autocompletion").enable(this.$refs.input);
} }

View File

@ -207,8 +207,8 @@ export default {
case "error": case "error":
defaultState = defaultState =
this.link.error === "image-too-big" this.link.error === "image-too-big"
? this.$root.settings.media ? this.$store.state.settings.media
: this.$root.settings.links; : this.$store.state.settings.links;
break; break;
case "loading": case "loading":
@ -216,11 +216,11 @@ export default {
break; break;
case "link": case "link":
defaultState = this.$root.settings.links; defaultState = this.$store.state.settings.links;
break; break;
default: default:
defaultState = this.$root.settings.media; defaultState = this.$store.state.settings.media;
} }
this.link.shown = this.link.shown && defaultState; this.link.shown = this.link.shown && defaultState;

View File

@ -90,7 +90,7 @@ export default {
}, },
computed: { computed: {
messageTime() { messageTime() {
const format = this.$root.settings.showSeconds const format = this.$store.state.settings.showSeconds
? constants.timeFormats.msgWithSeconds ? constants.timeFormats.msgWithSeconds
: constants.timeFormats.msgDefault; : constants.timeFormats.msgDefault;

View File

@ -80,14 +80,14 @@ export default {
} }
// If actions are hidden, just return a message list with them excluded // If actions are hidden, just return a message list with them excluded
if (this.$root.settings.statusMessages === "hidden") { if (this.$store.state.settings.statusMessages === "hidden") {
return this.channel.messages.filter( return this.channel.messages.filter(
(message) => !constants.condensedTypes.includes(message.type) (message) => !constants.condensedTypes.includes(message.type)
); );
} }
// If actions are not condensed, just return raw message list // If actions are not condensed, just return raw message list
if (this.$root.settings.statusMessages !== "condensed") { if (this.$store.state.settings.statusMessages !== "condensed") {
return this.channel.messages; return this.channel.messages;
} }

View File

@ -10,7 +10,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<label class="opt"> <label class="opt">
<input <input
v-model="$store.state.serverConfiguration.advanced" :checked="$store.state.settings.advanced"
type="checkbox" type="checkbox"
name="advanced" name="advanced"
/> />
@ -37,8 +37,7 @@
<div <div
v-if=" v-if="
!$store.state.serverConfiguration.public && !$store.state.serverConfiguration.public && $store.state.settings.advanced
$store.state.serverConfiguration.advanced
" "
class="col-sm-12" class="col-sm-12"
> >
@ -56,21 +55,21 @@
</h2> </h2>
<label class="opt"> <label class="opt">
<input <input
v-model="$root.settings.syncSettings" :checked="$store.state.settings.syncSettings"
type="checkbox" type="checkbox"
name="syncSettings" name="syncSettings"
/> />
Synchronize settings with other clients Synchronize settings with other clients
</label> </label>
<p v-if="!$root.settings.syncSettings" class="sync-warning-override"> <p v-if="!$store.state.settings.syncSettings" class="sync-warning-override">
<strong>Warning</strong> Checking this box will override the settings of <strong>Warning</strong> Checking this box will override the settings of
this client with those stored on the server. this client with those stored on the server.
</p> </p>
<p v-if="!$root.settings.syncSettings" class="sync-warning-base"> <p v-if="!$store.state.settings.syncSettings" class="sync-warning-base">
<strong>Warning</strong> No settings have been synced before. Enabling this <strong>Warning</strong> No settings have been synced before. Enabling this
will sync all settings of this client as the base for other clients. will sync all settings of this client as the base for other clients.
</p> </p>
<div v-if="$root.settings.syncSettings" class="opt force-sync-button"> <div v-if="$store.state.settings.syncSettings" class="opt force-sync-button">
<button type="button" class="btn" @click="onForceSyncClick"> <button type="button" class="btn" @click="onForceSyncClick">
Force sync settings Force sync settings
</button> </button>
@ -83,14 +82,14 @@
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<label class="opt"> <label class="opt">
<input v-model="$root.settings.motd" type="checkbox" name="motd" /> <input :checked="$store.state.settings.motd" type="checkbox" name="motd" />
Show <abbr title="Message Of The Day">MOTD</abbr> Show <abbr title="Message Of The Day">MOTD</abbr>
</label> </label>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<label class="opt"> <label class="opt">
<input <input
v-model="$root.settings.showSeconds" :checked="$store.state.settings.showSeconds"
type="checkbox" type="checkbox"
name="showSeconds" name="showSeconds"
/> />
@ -114,7 +113,7 @@
<div class="col-sm-12"> <div class="col-sm-12">
<label class="opt"> <label class="opt">
<input <input
v-model="$root.settings.statusMessages" :checked="$store.state.settings.statusMessages === 'shown'"
type="radio" type="radio"
name="statusMessages" name="statusMessages"
value="shown" value="shown"
@ -123,7 +122,7 @@
</label> </label>
<label class="opt"> <label class="opt">
<input <input
v-model="$root.settings.statusMessages" :checked="$store.state.settings.statusMessages === 'condensed'"
type="radio" type="radio"
name="statusMessages" name="statusMessages"
value="condensed" value="condensed"
@ -132,7 +131,7 @@
</label> </label>
<label class="opt"> <label class="opt">
<input <input
v-model="$root.settings.statusMessages" :checked="$store.state.settings.statusMessages === 'hidden'"
type="radio" type="radio"
name="statusMessages" name="statusMessages"
value="hidden" value="hidden"
@ -146,7 +145,7 @@
<div class="col-sm-12"> <div class="col-sm-12">
<label class="opt"> <label class="opt">
<input <input
v-model="$root.settings.coloredNicks" :checked="$store.state.settings.coloredNicks"
type="checkbox" type="checkbox"
name="coloredNicks" name="coloredNicks"
/> />
@ -154,21 +153,21 @@
</label> </label>
<label class="opt"> <label class="opt">
<input <input
v-model="$root.settings.autocomplete" :checked="$store.state.settings.autocomplete"
type="checkbox" type="checkbox"
name="autocomplete" name="autocomplete"
/> />
Enable autocomplete Enable autocomplete
</label> </label>
</div> </div>
<div v-if="$store.state.serverConfiguration.advanced" class="col-sm-12"> <div v-if="$store.state.settings.advanced" class="col-sm-12">
<label class="opt"> <label class="opt">
<label for="nickPostfix" class="sr-only" <label for="nickPostfix" class="sr-only">
>Nick autocomplete postfix (e.g. <code>, </code>)</label Nick autocomplete postfix (e.g. <code>, </code>)
> </label>
<input <input
id="nickPostfix" id="nickPostfix"
v-model="$root.settings.nickPostfix" :value="$store.state.settings.nickPostfix"
type="text" type="text"
name="nickPostfix" name="nickPostfix"
class="input" class="input"
@ -184,7 +183,7 @@
<label for="theme-select" class="sr-only">Theme</label> <label for="theme-select" class="sr-only">Theme</label>
<select <select
id="theme-select" id="theme-select"
v-model="$root.settings.theme" :value="$store.state.settings.theme"
name="theme" name="theme"
class="input" class="input"
> >
@ -198,19 +197,27 @@
</select> </select>
</div> </div>
<template v-if="$store.state.serverConfiguration.prefetch"> <template v-if="$store.state.settings.prefetch">
<div class="col-sm-12"> <div class="col-sm-12">
<h2>Link previews</h2> <h2>Link previews</h2>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<label class="opt"> <label class="opt">
<input type="checkbox" name="media" /> <input
:checked="$store.state.settings.media"
type="checkbox"
name="media"
/>
Auto-expand media Auto-expand media
</label> </label>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<label class="opt"> <label class="opt">
<input v-model="$root.settings.links" type="checkbox" name="links" /> <input
:checked="$store.state.settings.links"
type="checkbox"
name="links"
/>
Auto-expand websites Auto-expand websites
</label> </label>
</div> </div>
@ -276,7 +283,7 @@
<div class="col-sm-12"> <div class="col-sm-12">
<label class="opt"> <label class="opt">
<input <input
v-model="$root.settings.notification" :checked="$store.state.settings.notification"
type="checkbox" type="checkbox"
name="notification" name="notification"
/> />
@ -289,10 +296,10 @@
</div> </div>
</div> </div>
<div v-if="$store.state.serverConfiguration.advanced" class="col-sm-12"> <div v-if="$store.state.settings.advanced" class="col-sm-12">
<label class="opt"> <label class="opt">
<input <input
v-model="$root.settings.notifyAllMessages" :checked="$store.state.settings.notifyAllMessages"
type="checkbox" type="checkbox"
name="notifyAllMessages" name="notifyAllMessages"
/> />
@ -300,14 +307,14 @@
</label> </label>
</div> </div>
<div v-if="$store.state.serverConfiguration.advanced" class="col-sm-12"> <div v-if="$store.state.settings.advanced" class="col-sm-12">
<label class="opt"> <label class="opt">
<label for="highlights" class="sr-only" <label for="highlights" class="sr-only">
>Custom highlights (comma-separated keywords)</label Custom highlights (comma-separated keywords)
> </label>
<input <input
id="highlights" id="highlights"
v-model="$root.settings.highlights" :value="$store.state.settings.highlights"
type="text" type="text"
name="highlights" name="highlights"
class="input" class="input"
@ -327,9 +334,9 @@
<h2>Change password</h2> <h2>Change password</h2>
</div> </div>
<div class="col-sm-12 password-container"> <div class="col-sm-12 password-container">
<label for="old_password_input" class="sr-only" <label for="old_password_input" class="sr-only">
>Enter current password</label Enter current password
> </label>
<RevealPassword v-slot:default="slotProps"> <RevealPassword v-slot:default="slotProps">
<input <input
id="old_password_input" id="old_password_input"
@ -341,9 +348,9 @@
</RevealPassword> </RevealPassword>
</div> </div>
<div class="col-sm-12 password-container"> <div class="col-sm-12 password-container">
<label for="new_password_input" class="sr-only" <label for="new_password_input" class="sr-only">
>Enter desired new password</label Enter desired new password
> </label>
<RevealPassword v-slot:default="slotProps"> <RevealPassword v-slot:default="slotProps">
<input <input
id="new_password_input" id="new_password_input"
@ -355,9 +362,9 @@
</RevealPassword> </RevealPassword>
</div> </div>
<div class="col-sm-12 password-container"> <div class="col-sm-12 password-container">
<label for="verify_password_input" class="sr-only" <label for="verify_password_input" class="sr-only">
>Repeat new password</label Repeat new password
> </label>
<RevealPassword v-slot:default="slotProps"> <RevealPassword v-slot:default="slotProps">
<input <input
id="verify_password_input" id="verify_password_input"
@ -387,16 +394,16 @@
</div> </div>
</div> </div>
<div v-if="$store.state.serverConfiguration.advanced" class="col-sm-12"> <div v-if="$store.state.settings.advanced" class="col-sm-12">
<h2>Custom Stylesheet</h2> <h2>Custom Stylesheet</h2>
</div> </div>
<div v-if="$store.state.serverConfiguration.advanced" class="col-sm-12"> <div v-if="$store.state.settings.advanced" class="col-sm-12">
<label for="user-specified-css-input" class="sr-only" <label for="user-specified-css-input" class="sr-only">
>Custom stylesheet. You can override any style with CSS here.</label Custom stylesheet. You can override any style with CSS here.
> </label>
<textarea <textarea
id="user-specified-css-input" id="user-specified-css-input"
v-model="$root.settings.userStyles" :value="$store.state.settings.userStyles"
class="input" class="input"
name="userStyles" name="userStyles"
placeholder="/* You can override any style with CSS here */" placeholder="/* You can override any style with CSS here */"
@ -416,7 +423,7 @@
<div id="session-list"> <div id="session-list">
<p v-if="$store.state.sessions.length == 0">Loading</p> <p v-if="$store.state.sessions.length == 0">Loading</p>
<p v-else-if="$store.getters.otherSessions.length == 0"> <p v-else-if="$store.getters.otherSessions.length == 0">
<em>You are not currently logged in to any other device.</em>' <em>You are not currently logged in to any other device.</em>
</p> </p>
<template v-else> <template v-else>
<Session <Session

View File

@ -6,7 +6,6 @@ const Mousetrap = require("mousetrap");
const {Textcomplete, Textarea} = require("textcomplete"); const {Textcomplete, Textarea} = require("textcomplete");
const emojiMap = require("./libs/simplemap.json"); const emojiMap = require("./libs/simplemap.json");
const constants = require("./constants"); const constants = require("./constants");
const {vueApp} = require("./vue");
const store = require("./store").default; const store = require("./store").default;
let input; let input;
@ -62,7 +61,7 @@ const nicksStrategy = {
}, },
replace([, original], position = 1) { replace([, original], position = 1) {
// If no postfix specified, return autocompleted nick as-is // If no postfix specified, return autocompleted nick as-is
if (!vueApp.settings.nickPostfix) { if (!store.state.settings.nickPostfix) {
return original; return original;
} }
@ -72,7 +71,7 @@ const nicksStrategy = {
} }
// If nick is first in the input, append specified postfix // If nick is first in the input, append specified postfix
return original + vueApp.settings.nickPostfix; return original + store.state.settings.nickPostfix;
}, },
index: 1, index: 1,
}; };

View File

@ -3,7 +3,6 @@
const $ = require("jquery"); const $ = require("jquery");
const storage = require("./localStorage"); const storage = require("./localStorage");
const socket = require("./socket"); const socket = require("./socket");
const {vueApp} = require("./vue");
const store = require("./store").default; const store = require("./store").default;
require("../js/autocompletion"); require("../js/autocompletion");
@ -13,7 +12,7 @@ const $userStyles = $("#user-specified-css");
const noCSSparamReg = /[?&]nocss/; const noCSSparamReg = /[?&]nocss/;
// Default settings // Default settings
const settings = vueApp.settings; const settings = store.state.settings;
const noSync = ["syncSettings"]; const noSync = ["syncSettings"];
@ -28,7 +27,7 @@ let userSettings = JSON.parse(storage.get("settings")) || false;
if (!userSettings) { if (!userSettings) {
// Enable sync by default if there are no user defined settings. // Enable sync by default if there are no user defined settings.
settings.syncSettings = true; store.commit("settings/syncSettings", true);
} else { } else {
for (const key in settings) { for (const key in settings) {
// Older The Lounge versions converted highlights to an array, turn it back into a string // Older The Lounge versions converted highlights to an array, turn it back into a string
@ -41,7 +40,7 @@ if (!userSettings) {
typeof userSettings[key] !== "undefined" && typeof userSettings[key] !== "undefined" &&
typeof settings[key] === typeof userSettings[key] typeof settings[key] === typeof userSettings[key]
) { ) {
settings[key] = userSettings[key]; store.commit(`settings/${key}`, userSettings[key]);
} }
} }
} }
@ -118,7 +117,7 @@ function settingSetEmit(name, value) {
// When sync is `true` the setting will also be sent to the backend for syncing. // When sync is `true` the setting will also be sent to the backend for syncing.
function updateSetting(name, value, sync) { function updateSetting(name, value, sync) {
settings[name] = value; store.commit(`settings/${name}`, value);
storage.set("settings", JSON.stringify(settings)); storage.set("settings", JSON.stringify(settings));
applySetting(name, value); applySetting(name, value);

View File

@ -41,7 +41,7 @@ socket.on("configuration", function(data) {
// If localStorage contains a theme that does not exist on this server, switch // If localStorage contains a theme that does not exist on this server, switch
// back to its default theme. // back to its default theme.
const currentTheme = data.themes.find((t) => t.name === options.settings.theme); const currentTheme = data.themes.find((t) => t.name === store.state.settings.theme);
if (currentTheme === undefined) { if (currentTheme === undefined) {
options.processSetting("theme", data.defaultTheme, true); options.processSetting("theme", data.defaultTheme, true);

View File

@ -2,7 +2,6 @@
const $ = require("jquery"); const $ = require("jquery");
const socket = require("../socket"); const socket = require("../socket");
const options = require("../options");
const cleanIrcMessage = require("../libs/handlebars/ircmessageparser/cleanIrcMessage"); const cleanIrcMessage = require("../libs/handlebars/ircmessageparser/cleanIrcMessage");
const webpush = require("../webpush"); const webpush = require("../webpush");
const {vueApp} = require("../vue"); const {vueApp} = require("../vue");
@ -99,9 +98,9 @@ socket.on("msg", function(data) {
function notifyMessage(targetId, channel, activeChannel, msg) { function notifyMessage(targetId, channel, activeChannel, msg) {
const button = $("#sidebar .chan[data-id='" + targetId + "']"); const button = $("#sidebar .chan[data-id='" + targetId + "']");
if (msg.highlight || (options.settings.notifyAllMessages && msg.type === "message")) { if (msg.highlight || (store.state.settings.notifyAllMessages && msg.type === "message")) {
if (!document.hasFocus() || !activeChannel || activeChannel.channel !== channel) { if (!document.hasFocus() || !activeChannel || activeChannel.channel !== channel) {
if (options.settings.notification) { if (store.state.settings.notification) {
try { try {
pop.play(); pop.play();
} catch (exception) { } catch (exception) {
@ -110,7 +109,7 @@ function notifyMessage(targetId, channel, activeChannel, msg) {
} }
if ( if (
options.settings.desktopNotifications && store.state.settings.desktopNotifications &&
"Notification" in window && "Notification" in window &&
Notification.permission === "granted" Notification.permission === "granted"
) { ) {

View File

@ -2,11 +2,12 @@
const socket = require("../socket"); const socket = require("../socket");
const options = require("../options"); const options = require("../options");
const store = require("../store").default;
function evaluateSetting(name, value) { function evaluateSetting(name, value) {
if ( if (
options.settings.syncSettings && store.state.settings.syncSettings &&
options.settings[name] !== value && store.state.settings[name] !== value &&
!options.noSync.includes(name) !options.noSync.includes(name)
) { ) {
options.processSetting(name, value, true); options.processSetting(name, value, true);

View File

@ -0,0 +1,37 @@
function createMutator(propertyName) {
return [
propertyName,
(state, value) => {
state[propertyName] = value;
},
];
}
function createMutators(keys) {
return Object.fromEntries(keys.map(createMutator));
}
const state = {
syncSettings: false,
advanced: false,
autocomplete: true,
nickPostfix: "",
coloredNicks: true,
desktopNotifications: false,
highlights: "",
links: true,
motd: true,
notification: true,
notifyAllMessages: false,
showSeconds: false,
statusMessages: "condensed",
theme: document.getElementById("theme").dataset.serverTheme,
media: true,
userStyles: "",
};
export default {
namespaced: true,
state,
mutations: createMutators(Object.keys(state)),
};

View File

@ -1,10 +1,15 @@
import Vue from "vue"; import Vue from "vue";
import Vuex from "vuex"; import Vuex from "vuex";
import settings from "./store-settings";
const storage = require("./localStorage"); const storage = require("./localStorage");
Vue.use(Vuex); Vue.use(Vuex);
const store = new Vuex.Store({ const store = new Vuex.Store({
modules: {
settings,
},
state: { state: {
activeChannel: null, activeChannel: null,
currentUserVisibleError: null, currentUserVisibleError: null,
@ -54,7 +59,10 @@ const store = new Vuex.Store({
state.networks = networks; state.networks = networks;
}, },
removeNetwork(state, networkId) { removeNetwork(state, networkId) {
state.networks.splice(store.state.networks.findIndex((n) => n.uuid === networkId), 1); state.networks.splice(
store.state.networks.findIndex((n) => n.uuid === networkId),
1
);
}, },
sortNetworks(state, sortFn) { sortNetworks(state, sortFn) {
state.networks.sort(sortFn); state.networks.sort(sortFn);

View File

@ -23,24 +23,6 @@ const vueApp = new Vue({
el: "#viewport", el: "#viewport",
data: { data: {
initialized: false, initialized: false,
settings: {
syncSettings: false,
advanced: false,
autocomplete: true,
nickPostfix: "",
coloredNicks: true,
desktopNotifications: false,
highlights: "",
links: true,
motd: true,
notification: true,
notifyAllMessages: false,
showSeconds: false,
statusMessages: "condensed",
theme: document.getElementById("theme").dataset.serverTheme,
media: true,
userStyles: "",
},
}, },
router, router,
mounted() { mounted() {