diff --git a/client/js/lounge.js b/client/js/lounge.js index fdeeba13..440920f2 100644 --- a/client/js/lounge.js +++ b/client/js/lounge.js @@ -27,7 +27,6 @@ $(function() { $(document.body).data("app-name", document.title); - var windows = $("#windows"); var viewport = $("#viewport"); var sidebarSlide = slideoutMenu(viewport[0], sidebar[0]); var contextMenuContainer = $("#context-menu-container"); @@ -484,18 +483,6 @@ $(function() { container.html(templates.user_filtered({matches: result})).show(); }); - var forms = $("#sign-in, #connect, #change-password"); - - windows.on("show", "#sign-in", function() { - $(this).find("input").each(function() { - var self = $(this); - if (self.val() === "") { - self.focus(); - return false; - } - }); - }); - if ($("body").hasClass("public") && (window.location.hash === "#connect" || window.location.hash === "")) { $("#connect").one("show", function() { var params = URI(document.location.search); @@ -522,56 +509,6 @@ $(function() { }); } - forms.on("submit", "form", function(e) { - e.preventDefault(); - var event = "auth"; - var form = $(this); - form.find(".btn").attr("disabled", true); - - if (form.closest(".window").attr("id") === "connect") { - event = "conn"; - } else if (form.closest("div").attr("id") === "change-password") { - event = "change-password"; - } - - var values = {}; - $.each(form.serializeArray(), function(i, obj) { - if (obj.value !== "") { - values[obj.name] = obj.value; - } - }); - - if (values.user) { - storage.set("user", values.user); - } - - socket.emit( - event, values - ); - }); - - forms.on("focusin", ".nick", function() { - // Need to set the first "lastvalue", so it can be used in the below function - var nick = $(this); - nick.data("lastvalue", nick.val()); - }); - - forms.on("input", ".nick", function() { - var nick = $(this).val(); - var usernameInput = forms.find(".username"); - - // Because this gets called /after/ it has already changed, we need use the previous value - var lastValue = $(this).data("lastvalue"); - - // They were the same before the change, so update the username field - if (usernameInput.val() === lastValue) { - usernameInput.val(nick); - } - - // Store the "previous" value, for next time - $(this).data("lastvalue", nick); - }); - $(document).on("visibilitychange focus click", () => { if (sidebar.find(".highlight").length === 0) { utils.toggleNotificationMarkers(false); diff --git a/client/js/options.js b/client/js/options.js index f9621430..4faca65e 100644 --- a/client/js/options.js +++ b/client/js/options.js @@ -3,7 +3,6 @@ const $ = require("jquery"); require("jquery-textcomplete"); const escapeRegExp = require("lodash/escapeRegExp"); -const settings = $("#settings"); const userStyles = $("#user-specified-css"); const storage = require("./localStorage"); const tz = require("./libs/handlebars/tz"); @@ -35,6 +34,11 @@ for (const key in options) { } } +// Apply custom CSS on page load +if (typeof userOptions.userStyles === "string" && !/[?&]nocss/.test(window.location.search)) { + userStyles.html(userOptions.userStyles); +} + userOptions = null; module.exports = options; @@ -43,123 +47,126 @@ module.exports.shouldOpenMessagePreview = function(type) { return (options.links && type === "link") || (options.thumbnails && type === "image"); }; -for (var i in options) { - if (i === "userStyles") { - if (!/[?&]nocss/.test(window.location.search)) { - $(document.head).find("#user-specified-css").html(options[i]); +module.exports.initialize = () => { + module.exports.initialize = null; + + const settings = $("#settings"); + + for (var i in options) { + if (i === "userStyles") { + settings.find("#user-specified-css-input").val(options[i]); + } else if (i === "highlights") { + settings.find("input[name=" + i + "]").val(options[i]); + } else if (i === "statusMessages") { + settings.find(`input[name=${i}][value=${options[i]}]`) + .prop("checked", true); + } 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.find("#user-specified-css-input").val(options[i]); - } else if (i === "highlights") { - settings.find("input[name=" + i + "]").val(options[i]); - } else if (i === "statusMessages") { - settings.find(`input[name=${i}][value=${options[i]}]`) - .prop("checked", true); - } 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() { - const self = $(this); - const type = self.attr("type"); - const name = self.attr("name"); + settings.on("change", "input, select, textarea", function() { + const self = $(this); + const type = self.attr("type"); + const name = self.attr("name"); - if (type === "password") { - return; - } else if (type === "radio") { - if (self.prop("checked")) { + if (type === "password") { + return; + } else if (type === "radio") { + if (self.prop("checked")) { + options[name] = self.val(); + } + } else if (type === "checkbox") { + options[name] = self.prop("checked"); + } else { options[name] = self.val(); } - } else if (type === "checkbox") { - options[name] = self.prop("checked"); + + storage.set("settings", JSON.stringify(options)); + + if (name === "motd") { + chat.toggleClass("hide-" + name, !self.prop("checked")); + } else if (name === "statusMessages") { + chat.toggleClass("hide-status-messages", options[name] === "hidden"); + chat.toggleClass("condensed-status-messages", options[name] === "condensed"); + } 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 !== ""; + }); + // Construct regex with wordboundary for every highlight item + const highlightsTokens = options.highlights.map(function(h) { + return escapeRegExp(h); + }); + if (highlightsTokens && highlightsTokens.length) { + module.exports.highlightsRE = new RegExp("\\b(?:" + highlightsTokens.join("|") + ")\\b", "i"); + } else { + module.exports.highlightsRE = null; + } + } else if (name === "showSeconds") { + chat.find(".msg > .time").each(function() { + $(this).text(tz($(this).parent().data("time"))); + }); + chat.toggleClass("show-seconds", self.prop("checked")); + } else if (name === "autocomplete") { + if (self.prop("checked")) { + $("#input").trigger("autocomplete:on"); + } else { + $("#input").textcomplete("destroy"); + } + } + }).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[name] = self.val(); - } - - storage.set("settings", JSON.stringify(options)); - - if (name === "motd") { - chat.toggleClass("hide-" + name, !self.prop("checked")); - } else if (name === "statusMessages") { - chat.toggleClass("hide-status-messages", options[name] === "hidden"); - chat.toggleClass("condensed-status-messages", options[name] === "condensed"); - } 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 !== ""; - }); - // Construct regex with wordboundary for every highlight item - const highlightsTokens = options.highlights.map(function(h) { - return escapeRegExp(h); - }); - if (highlightsTokens && highlightsTokens.length) { - module.exports.highlightsRE = new RegExp("\\b(?:" + highlightsTokens.join("|") + ")\\b", "i"); - } else { - module.exports.highlightsRE = null; - } - } else if (name === "showSeconds") { - chat.find(".msg > .time").each(function() { - $(this).text(tz($(this).parent().data("time"))); - }); - chat.toggleClass("show-seconds", self.prop("checked")); - } else if (name === "autocomplete") { - if (self.prop("checked")) { - $("#input").trigger("autocomplete:on"); - } else { - $("#input").textcomplete("destroy"); - } - } -}).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") { + options.desktopNotifications = false; 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); -} diff --git a/client/js/socket-events/configuration.js b/client/js/socket-events/configuration.js index 3a4c324e..901170ca 100644 --- a/client/js/socket-events/configuration.js +++ b/client/js/socket-events/configuration.js @@ -3,10 +3,71 @@ const $ = require("jquery"); const socket = require("../socket"); const templates = require("../../views"); +const options = require("../options"); +const webpush = require("../webpush"); +const storage = require("../localStorage"); socket.on("configuration", function(data) { + if (!options.initialize) { + return; + } + $("#settings").html(templates.windows.settings(data)); $("#connect").html(templates.windows.connect(data)); - require("../options"); + $("#play").on("click", () => { + const pop = new Audio(); + pop.src = "audio/pop.ogg"; + pop.play(); + }); + + options.initialize(); + webpush.initialize(); + + // TODO: #sign-in needs to be handled in auth.js otherwise its broken + const forms = $("#sign-in, #connect, #change-password"); + + forms.on("submit", "form", function() { + const form = $(this); + const event = form.data("event"); + + form.find(".btn").attr("disabled", true); + + const values = {}; + $.each(form.serializeArray(), function(i, obj) { + if (obj.value !== "") { + values[obj.name] = obj.value; + } + }); + + if (values.user) { + storage.set("user", values.user); + } + + socket.emit(event, values); + + return false; + }); + + forms.on("focusin", ".nick", function() { + // Need to set the first "lastvalue", so it can be used in the below function + const nick = $(this); + nick.data("lastvalue", nick.val()); + }); + + forms.on("input", ".nick", function() { + const nick = $(this).val(); + const usernameInput = forms.find(".username"); + + // Because this gets called /after/ it has already changed, we need use the previous value + const lastValue = $(this).data("lastvalue"); + + // They were the same before the change, so update the username field + if (usernameInput.val() === lastValue) { + usernameInput.val(nick); + } + + // Store the "previous" value, for next time + $(this).data("lastvalue", nick); + }); }); diff --git a/client/js/socket-events/msg.js b/client/js/socket-events/msg.js index 585dc7ef..d8f50958 100644 --- a/client/js/socket-events/msg.js +++ b/client/js/socket-events/msg.js @@ -21,8 +21,6 @@ try { }; } -$("#play").on("click", () => pop.play()); - socket.on("msg", function(data) { // We set a maximum timeout of 2 seconds so that messages don't take too long to appear. utils.requestIdleCallback(() => processReceivedMessage(data), 2000); diff --git a/client/js/webpush.js b/client/js/webpush.js index 16eb9dd8..bffe65c7 100644 --- a/client/js/webpush.js +++ b/client/js/webpush.js @@ -4,7 +4,7 @@ const $ = require("jquery"); const storage = require("./localStorage"); const socket = require("./socket"); -const pushNotificationsButton = $("#pushNotifications"); +let pushNotificationsButton; let clientSubscribed = null; let applicationServerKey; @@ -29,7 +29,13 @@ module.exports.configurePushNotifications = (subscribedOnServer, key) => { } }; -if (isAllowedServiceWorkersHost()) { +module.exports.initialize = () => { + pushNotificationsButton = $("#pushNotifications"); + + if (!isAllowedServiceWorkersHost()) { + return; + } + $("#pushNotificationsHttps").hide(); if ("serviceWorker" in navigator) { @@ -57,7 +63,7 @@ if (isAllowedServiceWorkersHost()) { $("#pushNotificationsUnsupported span").text(err); }); } -} +}; function onPushButton() { pushNotificationsButton.attr("disabled", true); diff --git a/client/views/windows/connect.tpl b/client/views/windows/connect.tpl index b52244d8..9ef5d09e 100644 --- a/client/views/windows/connect.tpl +++ b/client/views/windows/connect.tpl @@ -1,7 +1,7 @@