diff options
Diffstat (limited to 'js/App.js')
-rw-r--r-- | js/App.js | 81 |
1 files changed, 52 insertions, 29 deletions
@@ -18,6 +18,15 @@ const App = { is_prefs: false, LABEL_BASE_INDEX: -1024, _translations: {}, + Hash: { + get: function() { + return dojo.queryToObject(window.location.hash.substring(1)); + }, + set: function(params) { + const obj = dojo.queryToObject(window.location.hash.substring(1)); + window.location.hash = dojo.objectToQuery({...obj, ...params}); + } + }, l10n: { ngettext: function(msg1, msg2, n) { return self.__((parseInt(n) > 1) ? msg2 : msg1); @@ -52,8 +61,9 @@ const App = { return this.button_tag(value, "", {...{onclick: "App.dialogOf(this).hide()"}, ...attributes}); }, checkbox_tag: function(name, checked = false, value = "", attributes = {}, id = "") { + // checked !== '0' prevents mysql "boolean" false to be implicitly cast as true return `<input dojoType="dijit.form.CheckBox" type="checkbox" name="${App.escapeHtml(name)}" - ${checked ? "checked" : ""} + ${checked !== '0' && checked ? "checked" : ""} ${value ? `value="${App.escapeHtml(value)}"` : ""} ${this.attributes_to_string(attributes)} id="${App.escapeHtml(id)}">` }, @@ -418,7 +428,7 @@ const App = { if (error && error.code && error.code != App.Error.E_SUCCESS) { console.warn("handleRpcJson: fatal error", error); - this.Error.fatal(error.code); + this.Error.fatal(error.code, error.params); return false; } @@ -547,6 +557,7 @@ const App = { E_SUCCESS: "E_SUCCESS", E_UNAUTHORIZED: "E_UNAUTHORIZED", E_SCHEMA_MISMATCH: "E_SCHEMA_MISMATCH", + E_URL_SCHEME_MISMATCH: "E_URL_SCHEME_MISMATCH", fatal: function (error, params = {}) { if (error == App.Error.E_UNAUTHORIZED) { window.location.href = "index.php"; @@ -554,9 +565,14 @@ const App = { } else if (error == App.Error.E_SCHEMA_MISMATCH) { window.location.href = "public.php?op=dbupdate"; return; + } else if (error == App.Error.E_URL_SCHEME_MISMATCH) { + params.description = __("URL scheme reported by your browser (%a) doesn't match server-configured SELF_URL_PATH (%b), check X-Forwarded-Proto.") + .replace("%a", params.client_scheme) + .replace("%b", params.server_scheme); + params.info = `SELF_URL_PATH: ${params.self_url_path}\nCLIENT_LOCATION: ${document.location.href}` } - return this.report(__("Fatal error: %s").replace("%s", error), + return this.report(error, {...{title: __("Fatal error")}, ...params}); }, report: function(error, params = {}) { @@ -587,10 +603,13 @@ const App = { <div class='exception-contents'> <h3>${message}</h3> - <header>${__('Stack trace')}</header> + ${params.description ? `<p>${params.description}</p>` : ''} + + ${error.stack ? + `<header>${__('Stack trace')}</header> <section> <textarea readonly='readonly'>${error.stack}</textarea> - </section> + </section>` : ''} ${params && params.info ? ` @@ -650,7 +669,8 @@ const App = { op: "rpc", method: "sanityCheck", clientTzOffset: new Date().getTimezoneOffset() * 60, - hasSandbox: "sandbox" in document.createElement("iframe") + hasSandbox: "sandbox" in document.createElement("iframe"), + clientLocation: window.location.href }; xhr.json("backend.php", params, (reply) => { @@ -757,18 +777,15 @@ const App = { } }); - const toolbar = document.forms["toolbar-main"]; - - dijit.getEnclosingWidget(toolbar.view_mode).attr('value', - this.getInitParam("default_view_mode")); - - dijit.getEnclosingWidget(toolbar.order_by).attr('value', - this.getInitParam("default_view_order_by")); + dijit.byId('toolbar-main').setValues({ + view_mode: this.getInitParam("default_view_mode"), + order_by: this.getInitParam("default_view_order_by") + }); this.setLoadingProgress(50); this._widescreen_mode = this.getInitParam("widescreen"); - this.switchPanelMode(this._widescreen_mode); + this.setWidescreen(this._widescreen_mode); Headlines.initScrollHandler(); @@ -801,10 +818,23 @@ const App = { .then((reply) => { console.log('update reply', reply); - if (reply.id) { - App.byId("updates-available").show(); + const icon = App.byId("updates-available"); + + if (reply.changeset.id || reply.plugins.length > 0) { + icon.show(); + + const tips = []; + + if (reply.changeset.id) + tips.push(__("Updates for Tiny Tiny RSS are available.")); + + if (reply.plugins.length > 0) + tips.push(__("Updates for some local plugins are available.")); + + icon.setAttribute("title", tips.join("\n")); + } else { - App.byId("updates-available").hide(); + icon.hide(); } }); }, @@ -817,13 +847,6 @@ const App = { document.title = tmp; }, - onViewModeChanged: function() { - const view_mode = document.forms["toolbar-main"].view_mode.value; - - App.findAll("body")[0].setAttribute("view-mode", view_mode); - - return Feeds.reloadCurrent(''); - }, hotkeyHandler: function(event) { if (event.target.nodeName == "INPUT" || event.target.nodeName == "TEXTAREA") return; @@ -843,7 +866,7 @@ const App = { } } }, - switchPanelMode: function(wide) { + setWidescreen: function(wide) { const article_id = Article.getActive(); if (wide) { @@ -884,7 +907,7 @@ const App = { if (article_id) Article.view(article_id); - xhr.post("backend.php", {op: "rpc", method: "setpanelmode", wide: wide ? 1 : 0}); + xhr.post("backend.php", {op: "rpc", method: "setWidescreen", wide: wide ? 1 : 0}); }, initHotkeyActions: function() { if (this.is_prefs) { @@ -1144,7 +1167,7 @@ const App = { Cookie.set("ttrss_ci_width", 0); Cookie.set("ttrss_ci_height", 0); - this.switchPanelMode(this._widescreen_mode); + this.setWidescreen(this._widescreen_mode); } else { alert(__("Widescreen is not available in combined mode.")); } @@ -1234,7 +1257,7 @@ const App = { Cookie.set("ttrss_ci_width", 0); Cookie.set("ttrss_ci_height", 0); - this.switchPanelMode(this._widescreen_mode); + this.setWidescreen(this._widescreen_mode); } else { alert(__("Widescreen is not available in combined mode.")); } @@ -1245,6 +1268,6 @@ const App = { default: console.log("quickMenuGo: unknown action: " + opid); } - } + }, } |