summaryrefslogtreecommitdiff
path: root/js/App.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/App.js')
-rw-r--r--js/App.js81
1 files changed, 52 insertions, 29 deletions
diff --git a/js/App.js b/js/App.js
index bb8da578d..20498e692 100644
--- a/js/App.js
+++ b/js/App.js
@@ -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);
}
- }
+ },
}