From 7e8be97b660be63ff3515dfd6f61b252eef9a130 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 30 Nov 2018 12:46:52 +0300 Subject: [PATCH] remove duplicated code from hotkey actions handler more xhrPost() refactoring --- js/feedlist.js | 2 +- js/functions.js | 86 ++++++++++++-- js/prefs.js | 306 ++++++++++++++++++------------------------------ js/tt-rss.js | 71 ++--------- 4 files changed, 206 insertions(+), 259 deletions(-) diff --git a/js/feedlist.js b/js/feedlist.js index e13d9d74c..4aa70a361 100644 --- a/js/feedlist.js +++ b/js/feedlist.js @@ -175,7 +175,7 @@ function feedlist_init() { loading_set_progress(50); document.onkeydown = hotkey_handler; - setTimeout(hotkey_prefix_timeout, 5*1000); + setInterval(hotkey_prefix_timeout, 5*1000); if (!getActiveFeedId()) { viewfeed({feed: -3}); diff --git a/js/functions.js b/js/functions.js index 100da5f85..c7530c8a8 100755 --- a/js/functions.js +++ b/js/functions.js @@ -5,6 +5,9 @@ let _label_base_index = -1024; let loading_progress = 0; let notify_hide_timerid = false; +let hotkey_prefix = 0; +let hotkey_prefix_pressed = false; + Ajax.Base.prototype.initialize = Ajax.Base.prototype.initialize.wrap( function (callOriginal, options) { @@ -27,14 +30,14 @@ Ajax.Base.prototype.initialize = Ajax.Base.prototype.initialize.wrap( function xhrPost(url, params, complete) { console.log("xhrPost:", params); - new Ajax.Request(url, { + return new Ajax.Request(url, { parameters: params, onComplete: complete }); } function xhrJson(url, params, complete) { - xhrPost(url, params, (reply) => { + return xhrPost(url, params, (reply) => { try { const obj = JSON.parse(reply.responseText); complete(obj); @@ -498,9 +501,6 @@ function hotkey_prefix_timeout() { hotkey_prefix = false; Element.hide('cmdline'); } - - setTimeout(hotkey_prefix_timeout, 1000); - } function uploadIconHandler(rc) { @@ -1087,8 +1087,25 @@ function backend_sanity_check_callback(transport) { console.log('reading init-params...'); for (const k in params) { - console.log("IP:", k, "=>", params[k]); - if (k == "label_base_index") _label_base_index = parseInt(params[k]); + switch (k) { + case "label_base_index": + _label_base_index = parseInt(params[k]) + break; + case "hotkeys": + // filter mnemonic definitions (used for help panel) from hotkeys map + // i.e. *(191)|Ctrl-/ -> *(191) + + const tmp = []; + for (const sequence in params[k][1]) { + const filtered = sequence.replace(/\|.*$/, ""); + tmp[filtered] = params[k][1][sequence]; + } + + params[k][1] = tmp; + break; + } + + console.log("IP:", k, "=>", params[k]); } init_params = params; @@ -1537,3 +1554,58 @@ function openArticlePopup(id) { w.opener = null; w.location = "backend.php?op=article&method=view&mode=raw&html=1&zoom=1&id=" + id + "&csrf_token=" + getInitParam("csrf_token"); } + +function keyevent_to_action(e) { + + const hotkeys_map = getInitParam("hotkeys"); + const keycode = e.which; + const keychar = String.fromCharCode(keycode).toLowerCase(); + + if (keycode == 27) { // escape and drop prefix + hotkey_prefix = false; + } + + if (keycode == 16 || keycode == 17) return; // ignore lone shift / ctrl + + if (!hotkey_prefix && hotkeys_map[0].indexOf(keychar) != -1) { + + const date = new Date(); + const ts = Math.round(date.getTime() / 1000); + + hotkey_prefix = keychar; + hotkey_prefix_pressed = ts; + + $("cmdline").innerHTML = keychar; + Element.show("cmdline"); + + e.stopPropagation(); + + return false; + } + + Element.hide("cmdline"); + + let hotkey_name = keychar.search(/[a-zA-Z0-9]/) != -1 ? keychar : "(" + keycode + ")"; + + // ensure ^*char notation + if (e.shiftKey) hotkey_name = "*" + hotkey_name; + if (e.ctrlKey) hotkey_name = "^" + hotkey_name; + if (e.altKey) hotkey_name = "+" + hotkey_name; + if (e.metaKey) hotkey_name = "%" + hotkey_name; + + const hotkey_full = hotkey_prefix ? hotkey_prefix + " " + hotkey_name : hotkey_name; + hotkey_prefix = false; + + let action_name = false; + + for (const sequence in hotkeys_map[1]) { + if (sequence == hotkey_full) { + action_name = hotkeys_map[1][sequence]; + break; + } + } + + console.log('keyevent_to_action', hotkey_full, '=>', action_name); + + return action_name; +} \ No newline at end of file diff --git a/js/prefs.js b/js/prefs.js index c4540fb62..1358b9404 100755 --- a/js/prefs.js +++ b/js/prefs.js @@ -1,8 +1,5 @@ /* global dijit, __ */ -let hotkey_prefix = false; -let hotkey_prefix_pressed = false; - let seq = ""; function notify_callback2(transport, sticky) { @@ -494,72 +491,62 @@ function editSelectedFeeds() { notify_progress("Loading, please wait..."); - const query = "backend.php?op=pref-feeds&method=editfeeds&ids=" + - param_escape(rows.toString()); - - console.log(query); - if (dijit.byId("feedEditDlg")) dijit.byId("feedEditDlg").destroyRecursive(); - new Ajax.Request("backend.php", { - parameters: query, - onComplete: function (transport) { - - notify(""); - - const dialog = new dijit.Dialog({ - id: "feedEditDlg", - title: __("Edit Multiple Feeds"), - style: "width: 600px", - getChildByName: function (name) { - let rv = null; - this.getChildren().each( - function (child) { - if (child.name == name) { - rv = child; - return; - } - }); - return rv; - }, - toggleField: function (checkbox, elem, label) { - this.getChildByName(elem).attr('disabled', !checkbox.checked); - - if ($(label)) - if (checkbox.checked) - $(label).removeClassName('insensitive'); - else - $(label).addClassName('insensitive'); - - }, - execute: function () { - if (this.validate() && confirm(__("Save changes to selected feeds?"))) { - const query = this.attr('value'); - - /* normalize unchecked checkboxes because [] is not serialized */ - - Object.keys(query).each((key) => { - let val = query[key]; - - if (typeof val == "object" && val.length == 0) - query[key] = ["off"]; - }); - - notify_progress("Saving data...", true); - - xhrPost("backend.php", query, () => { - dialog.hide(); - updateFeedList(); - }); - } - }, - content: transport.responseText - }); + xhrPost("backend.php", { op: "pref-feeds", method: "editfeeds", ids: rows.toString() }, (transport) => { + notify(""); - dialog.show(); + const dialog = new dijit.Dialog({ + id: "feedEditDlg", + title: __("Edit Multiple Feeds"), + style: "width: 600px", + getChildByName: function (name) { + let rv = null; + this.getChildren().each( + function (child) { + if (child.name == name) { + rv = child; + return; + } + }); + return rv; + }, + toggleField: function (checkbox, elem, label) { + this.getChildByName(elem).attr('disabled', !checkbox.checked); - } + if ($(label)) + if (checkbox.checked) + $(label).removeClassName('insensitive'); + else + $(label).addClassName('insensitive'); + + }, + execute: function () { + if (this.validate() && confirm(__("Save changes to selected feeds?"))) { + const query = this.attr('value'); + + /* normalize unchecked checkboxes because [] is not serialized */ + + Object.keys(query).each((key) => { + let val = query[key]; + + if (typeof val == "object" && val.length == 0) + query[key] = ["off"]; + }); + + notify_progress("Saving data...", true); + + xhrPost("backend.php", query, () => { + dialog.hide(); + updateFeedList(); + }); + } + }, + content: transport.responseText + }); + + dialog.show(); }); } @@ -613,57 +600,58 @@ function updateFilterList() { let search = ""; if (user_search) { search = user_search.value; } - new Ajax.Request("backend.php", { - parameters: "?op=pref-filters&search=" + param_escape(search), - onComplete: function(transport) { - dijit.byId('filterConfigTab').attr('content', transport.responseText); - notify(""); - } }); + xhrPost("backend.php", { op: "pref-filters", search: search }, (transport) => { + dijit.byId('filterConfigTab').attr('content', transport.responseText); + notify(""); + }); } function updateLabelList() { - new Ajax.Request("backend.php", { - parameters: "?op=pref-labels", - onComplete: function(transport) { - dijit.byId('labelConfigTab').attr('content', transport.responseText); - notify(""); - } }); + xhrPost("backend.php", { op: "pref-labels" }, (transport) => { + dijit.byId('labelConfigTab').attr('content', transport.responseText); + notify(""); + }); } function updatePrefsList() { - new Ajax.Request("backend.php", { - parameters: "?op=pref-prefs", - onComplete: function(transport) { - dijit.byId('genConfigTab').attr('content', transport.responseText); - notify(""); - } }); + xhrPost("backend.php", { op: "pref-prefs" }, (transport) => { + dijit.byId('genConfigTab').attr('content', transport.responseText); + notify(""); + }); } function updateSystemList() { - new Ajax.Request("backend.php", { - parameters: "?op=pref-system", - onComplete: function(transport) { - dijit.byId('systemConfigTab').attr('content', transport.responseText); - notify(""); - } }); + xhrPost("backend.php", { op: "pref-system" }, (transport) => { + dijit.byId('systemConfigTab').attr('content', transport.responseText); + notify(""); + }); } function selectTab(id, noupdate) { if (!noupdate) { notify_progress("Loading, please wait..."); - if (id == "feedConfig") { - updateFeedList(); - } else if (id == "filterConfig") { - updateFilterList(); - } else if (id == "labelConfig") { - updateLabelList(); - } else if (id == "genConfig") { - updatePrefsList(); - } else if (id == "userConfig") { - updateUsersList(); - } else if (id == "systemConfig") { - updateSystemList(); + switch (id) { + case "feedConfig": + updateFeedList(); + break; + case "filterConfig": + updateFilterList(); + break; + case "labelConfig": + updateLabelList(); + break; + case "genConfig": + updatePrefsList(); + break; + case "userConfig": + updateUsersList(); + break; + case "systemConfig": + updateSystemList(); + break; + default: + console.warn("unknown tab", id); } const tab = dijit.byId(id + "Tab"); @@ -692,7 +680,7 @@ function init_second_stage() { window.setTimeout(function() { editFeed(param) }, 100); } - setTimeout(hotkey_prefix_timeout, 5*1000); + setInterval(hotkey_prefix_timeout, 5*1000); } function init() { @@ -765,105 +753,41 @@ function init() { function validatePrefsReset() { - const ok = confirm(__("Reset to defaults?")); - - if (ok) { + if (confirm(__("Reset to defaults?"))) { const query = "?op=pref-prefs&method=resetconfig"; - console.log(query); - - new Ajax.Request("backend.php", { - parameters: query, - onComplete: function(transport) { - updatePrefsList(); - notify_info(transport.responseText); - } }); + xhrPost("backend.php", { op: "pref-prefs", method: "resetconfig" }, (transport) => { + updatePrefsList(); + notify_info(transport.responseText); + }); } return false; - } function pref_hotkey_handler(e) { - - if (e.target.nodeName == "INPUT" || e.target.nodeName == "TEXTAREA") return; - - let keycode = false; - let shift_key = false; - - const cmdline = $('cmdline'); - - try { - shift_key = e.shiftKey; - } catch (e) { - - } - - if (window.event) { - keycode = window.event.keyCode; - } else if (e) { - keycode = e.which; - } - - let keychar = String.fromCharCode(keycode); - - if (keycode == 27) { // escape - hotkey_prefix = false; - } - - if (keycode == 16) return; // ignore lone shift - if (keycode == 17) return; // ignore lone ctrl - - if (!shift_key) keychar = keychar.toLowerCase(); - - var hotkeys = getInitParam("hotkeys"); - - if (!hotkey_prefix && hotkeys[0].indexOf(keychar) != -1) { - - const date = new Date(); - const ts = Math.round(date.getTime() / 1000); - - hotkey_prefix = keychar; - hotkey_prefix_pressed = ts; - - cmdline.innerHTML = keychar; - Element.show(cmdline); - - return true; - } - - Element.hide(cmdline); - - let hotkey = keychar.search(/[a-zA-Z0-9]/) != -1 ? keychar : "(" + keycode + ")"; - hotkey = hotkey_prefix ? hotkey_prefix + " " + hotkey : hotkey; - hotkey_prefix = false; - - let hotkey_action = false; - var hotkeys = getInitParam("hotkeys"); - - for (const sequence in hotkeys[1]) { - if (sequence == hotkey) { - hotkey_action = hotkeys[1][sequence]; - break; - } - } - - switch (hotkey_action) { - case "feed_subscribe": - quickAddFeed(); - return false; - case "create_label": - addLabel(); - return false; - case "create_filter": - quickAddFilter(); - return false; - case "help_dialog": - //helpDialog("prefs"); - return false; - default: - console.log("unhandled action: " + hotkey_action + "; hotkey: " + hotkey); + if (e.target.nodeName == "INPUT" || e.target.nodeName == "TEXTAREA") return; + + const action_name = keyevent_to_action(e); + + if (action_name) { + switch (action_name) { + case "feed_subscribe": + quickAddFeed(); + return false; + case "create_label": + addLabel(); + return false; + case "create_filter": + quickAddFilter(); + return false; + case "help_dialog": + helpDialog("main"); + return false; + default: + console.log("unhandled action: " + action_name + "; keycode: " + e.which); + } } } diff --git a/js/tt-rss.js b/js/tt-rss.js index e25dff18e..eb00ad54b 100644 --- a/js/tt-rss.js +++ b/js/tt-rss.js @@ -1,13 +1,11 @@ /* global dijit, __ */ let global_unread = -1; -let hotkey_prefix = false; -let hotkey_prefix_pressed = false; -let hotkey_actions = {}; let _widescreen_mode = false; let _rpc_seq = 0; let _active_feed_id = 0; let _active_feed_is_cat = false; +let hotkey_actions = {}; function next_seq() { _rpc_seq += 1; @@ -596,7 +594,7 @@ function init_second_stage() { if ('sessionStorage' in window && window['sessionStorage'] !== null) sessionStorage.clear(); - const hotkeys = getInitParam("hotkeys"); + /*const hotkeys = getInitParam("hotkeys"); const tmp = []; for (const sequence in hotkeys[1]) { @@ -605,7 +603,7 @@ function init_second_stage() { } hotkeys[1] = tmp; - setInitParam("hotkeys", hotkeys); + setInitParam("hotkeys", hotkeys);*/ _widescreen_mode = getInitParam("widescreen"); switchPanelMode(_widescreen_mode); @@ -767,65 +765,18 @@ function viewModeChanged() { } function hotkey_handler(e) { - if (e.target.nodeName == "INPUT" || e.target.nodeName == "TEXTAREA") return; - let keycode = e.which; - - if (keycode == 27) { // escape and drop prefix - hotkey_prefix = false; - } - - if (keycode == 16 || keycode == 17) return; // ignore lone shift / ctrl - - const hotkeys = getInitParam("hotkeys"); - const keychar = String.fromCharCode(keycode).toLowerCase(); - - if (!hotkey_prefix && hotkeys[0].indexOf(keychar) != -1) { - - const date = new Date(); - const ts = Math.round(date.getTime() / 1000); - - hotkey_prefix = keychar; - hotkey_prefix_pressed = ts; - - $("cmdline").innerHTML = keychar; - Element.show("cmdline"); - - e.stopPropagation(); + const action_name = keyevent_to_action(e); - // returning false here literally disables ctrl-c in browser lol (because C is a valid prefix) - return true; - } - - Element.hide("cmdline"); - - let hotkey = keychar.search(/[a-zA-Z0-9]/) != -1 ? keychar : "(" + keycode + ")"; - - // ensure ^*char notation - if (e.shiftKey) hotkey = "*" + hotkey; - if (e.ctrlKey) hotkey = "^" + hotkey; - if (e.altKey) hotkey = "+" + hotkey; - if (e.metaKey) hotkey = "%" + hotkey; - - hotkey = hotkey_prefix ? hotkey_prefix + " " + hotkey : hotkey; - hotkey_prefix = false; - - let hotkey_action = false; + if (action_name) { + const action_func = hotkey_actions[action_name]; - for (const sequence in hotkeys[1]) { - if (sequence == hotkey) { - hotkey_action = hotkeys[1][sequence]; - break; - } - } - - const action = hotkey_actions[hotkey_action]; - - if (action != null) { - action(); - e.stopPropagation(); - return false; + if (action_func != null) { + action_func(); + e.stopPropagation(); + return false; + } } }