diff --git a/client/js/localStorage.js b/client/js/localStorage.js new file mode 100644 index 00000000..3b08b3bd --- /dev/null +++ b/client/js/localStorage.js @@ -0,0 +1,19 @@ +"use strict"; + +module.exports = { + set: function(key, value) { + try { + window.localStorage.setItem(key, value); + } catch (e) { + // Do nothing. If we end up here, web storage quota exceeded, or user is + // in Safari's private browsing where localStorage's setItem is not + // available. See http://stackoverflow.com/q/14555347/1935861. + } + }, + get: function(key) { + return window.localStorage.getItem(key); + }, + remove: function(key, value) { + window.localStorage.removeItem(key, value); + } +}; diff --git a/client/js/lounge.js b/client/js/lounge.js index 1857339e..40a52b34 100644 --- a/client/js/lounge.js +++ b/client/js/lounge.js @@ -17,6 +17,7 @@ const slideoutMenu = require("./libs/slideout"); const templates = require("../views"); const socket = require("./socket"); const constants = require("./constants"); +const storage = require("./localStorage"); $(function() { var sidebar = $("#sidebar, #footer"); @@ -40,15 +41,6 @@ $(function() { var favicon = $("#favicon"); - function setLocalStorageItem(key, value) { - try { - window.localStorage.setItem(key, value); - } catch (e) { - // Do nothing. If we end up here, web storage quota exceeded, or user is - // in Safari's private browsing where localStorage's setItem is not - // available. See http://stackoverflow.com/q/14555347/1935861. - } - } socket.on("auth", function(data) { var login = $("#sign-in"); var token; @@ -56,14 +48,14 @@ $(function() { login.find(".btn").prop("disabled", false); if (!data.success) { - window.localStorage.removeItem("token"); + storage.remove("token"); var error = login.find(".error"); error.show().closest("form").one("submit", function() { error.hide(); }); } else { - token = window.localStorage.getItem("token"); + token = storage.get("token"); if (token) { $("#loading-page-message").text("Authorizing…"); socket.emit("auth", {token: token}); @@ -72,7 +64,7 @@ $(function() { var input = login.find("input[name='user']"); if (input.val() === "") { - input.val(window.localStorage.getItem("user") || ""); + input.val(storage.get("user") || ""); } if (token) { return; @@ -106,8 +98,8 @@ $(function() { }); } - if (data.token && window.localStorage.getItem("token") !== null) { - setLocalStorageItem("token", data.token); + if (data.token && storage.get("token") !== null) { + storage.set("token", data.token); } passwordForm @@ -130,9 +122,9 @@ $(function() { } if (data.token && $("#sign-in-remember").is(":checked")) { - setLocalStorageItem("token", data.token); + storage.set("token", data.token); } else { - window.localStorage.removeItem("token"); + storage.remove("token"); } $("body").removeClass("signed-out"); @@ -198,7 +190,7 @@ $(function() { var chan = chat.find(target); var template = "msg"; - if (!data.msg.highlight && !data.msg.self && (type === "message" || type === "notice") && highlights.some(function(h) { + if (!data.msg.highlight && !data.msg.self && (type === "message" || type === "notice") && options.highlights.some(function(h) { return data.msg.text.toLocaleLowerCase().indexOf(h.toLocaleLowerCase()) > -1; })) { data.msg.highlight = true; @@ -527,127 +519,10 @@ $(function() { socket.on("names", renderChannelUsers); - var userStyles = $("#user-specified-css"); - var highlights = []; - var options = $.extend({ - coloredNicks: true, - desktopNotifications: false, - join: true, - links: true, - mode: true, - motd: true, - nick: true, - notification: true, - notifyAllMessages: false, - part: true, - quit: true, - theme: $("#theme").attr("href").replace(/^themes\/(.*).css$/, "$1"), // Extracts default theme name, set on the server configuration - thumbnails: true, - userStyles: userStyles.text(), - }, JSON.parse(window.localStorage.getItem("settings"))); + var options = require("./options"); var windows = $("#windows"); - (function SettingsScope() { - var settings = $("#settings"); - - for (var i in options) { - if (i === "userStyles") { - if (!/[?&]nocss/.test(window.location.search)) { - $(document.head).find("#user-specified-css").html(options[i]); - } - settings.find("#user-specified-css-input").val(options[i]); - } else if (i === "highlights") { - settings.find("input[name=" + i + "]").val(options[i]); - } else if (i === "theme") { - $("#theme").attr("href", "themes/" + options[i] + ".css"); - settings.find("select[name=" + i + "]").val(options[i]); - } else if (options[i]) { - settings.find("input[name=" + i + "]").prop("checked", true); - } - } - - settings.on("change", "input, select, textarea", function() { - var self = $(this); - var name = self.attr("name"); - - if (self.attr("type") === "checkbox") { - options[name] = self.prop("checked"); - } else { - options[name] = self.val(); - } - - setLocalStorageItem("settings", JSON.stringify(options)); - - if ([ - "join", - "mode", - "motd", - "nick", - "part", - "quit", - "notifyAllMessages", - ].indexOf(name) !== -1) { - chat.toggleClass("hide-" + name, !self.prop("checked")); - } else if (name === "coloredNicks") { - chat.toggleClass("colored-nicks", self.prop("checked")); - } else if (name === "theme") { - $("#theme").attr("href", "themes/" + options[name] + ".css"); - } else if (name === "userStyles") { - userStyles.html(options[name]); - } else if (name === "highlights") { - var highlightString = options[name]; - highlights = highlightString.split(",").map(function(h) { - return h.trim(); - }).filter(function(h) { - // Ensure we don't have empty string in the list of highlights - // otherwise, users get notifications for everything - return h !== ""; - }); - } - }).find("input") - .trigger("change"); - - $("#desktopNotifications").on("change", function() { - if ($(this).prop("checked") && Notification.permission !== "granted") { - Notification.requestPermission(updateDesktopNotificationStatus); - } - }); - - // Updates the checkbox and warning in settings when the Settings page is - // opened or when the checkbox state is changed. - // When notifications are not supported, this is never called (because - // checkbox state can not be changed). - var updateDesktopNotificationStatus = function() { - if (Notification.permission === "denied") { - desktopNotificationsCheckbox.attr("disabled", true); - desktopNotificationsCheckbox.attr("checked", false); - warningBlocked.show(); - } else { - if (Notification.permission === "default" && desktopNotificationsCheckbox.prop("checked")) { - desktopNotificationsCheckbox.attr("checked", false); - } - desktopNotificationsCheckbox.attr("disabled", false); - warningBlocked.hide(); - } - }; - - // If browser does not support notifications, override existing settings and - // display proper message in settings. - var desktopNotificationsCheckbox = $("#desktopNotifications"); - var warningUnsupported = $("#warnUnsupportedDesktopNotifications"); - var warningBlocked = $("#warnBlockedDesktopNotifications"); - warningBlocked.hide(); - if (("Notification" in window)) { - warningUnsupported.hide(); - windows.on("show", "#settings", updateDesktopNotificationStatus); - } else { - options.desktopNotifications = false; - desktopNotificationsCheckbox.attr("disabled", true); - desktopNotificationsCheckbox.attr("checked", false); - } - }()); - var viewport = $("#viewport"); var sidebarSlide = slideoutMenu(viewport[0], sidebar[0]); var contextMenuContainer = $("#context-menu-container"); @@ -1027,7 +902,7 @@ $(function() { }); sidebar.on("click", "#sign-out", function() { - window.localStorage.removeItem("token"); + storage.remove("token"); location.reload(); }); @@ -1236,7 +1111,7 @@ $(function() { } }); if (values.user) { - setLocalStorageItem("user", values.user); + storage.set("user", values.user); } socket.emit( event, values diff --git a/client/js/options.js b/client/js/options.js new file mode 100644 index 00000000..24265a56 --- /dev/null +++ b/client/js/options.js @@ -0,0 +1,124 @@ +"use strict"; +const $ = require("jquery"); +const settings = $("#settings"); +const userStyles = $("#user-specified-css"); +const storage = require("./localStorage"); + +const windows = $("#windows"); +const chat = $("#chat"); + +const options = $.extend({ + coloredNicks: true, + desktopNotifications: false, + join: true, + links: true, + mode: true, + motd: false, + nick: true, + notification: true, + notifyAllMessages: false, + part: true, + quit: true, + theme: $("#theme").attr("href").replace(/^themes\/(.*).css$/, "$1"), // Extracts default theme name, set on the server configuration + thumbnails: true, + userStyles: userStyles.text(), + highlights: [] +}, JSON.parse(storage.get("settings"))); + +module.exports = options; + +for (var i in options) { + if (i === "userStyles") { + if (!/[?&]nocss/.test(window.location.search)) { + $(document.head).find("#user-specified-css").html(options[i]); + } + settings.find("#user-specified-css-input").val(options[i]); + } else if (i === "highlights") { + settings.find("input[name=" + i + "]").val(options[i]); + } else if (i === "theme") { + $("#theme").attr("href", "themes/" + options[i] + ".css"); + settings.find("select[name=" + i + "]").val(options[i]); + } else if (options[i]) { + settings.find("input[name=" + i + "]").prop("checked", true); + } +} + +settings.on("change", "input, select, textarea", function() { + var self = $(this); + var name = self.attr("name"); + + if (self.attr("type") === "checkbox") { + options[name] = self.prop("checked"); + } else { + options[name] = self.val(); + } + + storage.set("settings", JSON.stringify(options)); + + if ([ + "join", + "mode", + "motd", + "nick", + "part", + "quit", + "notifyAllMessages", + ].indexOf(name) !== -1) { + chat.toggleClass("hide-" + name, !self.prop("checked")); + } else if (name === "coloredNicks") { + chat.toggleClass("colored-nicks", self.prop("checked")); + } else if (name === "theme") { + $("#theme").attr("href", "themes/" + options[name] + ".css"); + } else if (name === "userStyles") { + userStyles.html(options[name]); + } else if (name === "highlights") { + var highlightString = options[name]; + options.highlights = highlightString.split(",").map(function(h) { + return h.trim(); + }).filter(function(h) { + // Ensure we don't have empty string in the list of highlights + // otherwise, users get notifications for everything + return h !== ""; + }); + } +}).find("input") + .trigger("change"); + +$("#desktopNotifications").on("change", function() { + if ($(this).prop("checked") && Notification.permission !== "granted") { + Notification.requestPermission(updateDesktopNotificationStatus); + } +}); + +// Updates the checkbox and warning in settings when the Settings page is +// opened or when the checkbox state is changed. +// When notifications are not supported, this is never called (because +// checkbox state can not be changed). +var updateDesktopNotificationStatus = function() { + if (Notification.permission === "denied") { + desktopNotificationsCheckbox.attr("disabled", true); + desktopNotificationsCheckbox.attr("checked", false); + warningBlocked.show(); + } else { + if (Notification.permission === "default" && desktopNotificationsCheckbox.prop("checked")) { + desktopNotificationsCheckbox.attr("checked", false); + } + desktopNotificationsCheckbox.attr("disabled", false); + warningBlocked.hide(); + } +}; + +// If browser does not support notifications, override existing settings and +// display proper message in settings. +var desktopNotificationsCheckbox = $("#desktopNotifications"); +var warningUnsupported = $("#warnUnsupportedDesktopNotifications"); +var warningBlocked = $("#warnBlockedDesktopNotifications"); +warningBlocked.hide(); +if (("Notification" in window)) { + warningUnsupported.hide(); + windows.on("show", "#settings", updateDesktopNotificationStatus); +} else { + options.desktopNotifications = false; + desktopNotificationsCheckbox.attr("disabled", true); + desktopNotificationsCheckbox.attr("checked", false); +}