From e8f9069c5c44fb4512247dbc9d280152e760331a Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Apr 2013 10:23:01 +0400 Subject: quickAddFeed: add placeholder select element to feeds dropdown --- js/functions.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'js/functions.js') diff --git a/js/functions.js b/js/functions.js index 82cfa9054..07eed2ad9 100644 --- a/js/functions.js +++ b/js/functions.js @@ -810,7 +810,7 @@ function quickAddFeed() { notify(''); Element.hide("feed_add_spinner"); - console.log("GOT RC: " + rc); + console.log(rc); switch (parseInt(rc['code'])) { case 1: @@ -866,6 +866,8 @@ function quickAddFeed() { while (select.getOptions().length > 0) select.removeOption(0); + select.addOption({value: '', label: __("Expand to select feed")}); + var count = 0; for (var feedUrl in feeds) { select.addOption({value: feedUrl, label: feeds[feedUrl]}); -- cgit v1.2.3-54-g00ecf From e43a9c4a01bf095b740e35711c79f6a0ca3374ba Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Apr 2013 13:16:14 +0400 Subject: add a %d articles selected element --- classes/feeds.php | 1 + js/functions.js | 6 ++++++ js/viewfeed.js | 24 ++++++++++++++++++++++++ tt-rss.css | 3 +++ 4 files changed, 34 insertions(+) (limited to 'js/functions.js') diff --git a/classes/feeds.php b/classes/feeds.php index 2f8dcb5ec..c7b7a83e6 100644 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -49,6 +49,7 @@ class Feeds extends Handler_Protected { // right part $reply .= ""; + $reply .= ""; $reply .= ""; if ($feed_site_url) { diff --git a/js/functions.js b/js/functions.js index 07eed2ad9..9336433ca 100644 --- a/js/functions.js +++ b/js/functions.js @@ -368,6 +368,9 @@ function toggleSelectRow2(sender, row, is_cdm) { row.addClassName('Selected'); else row.removeClassName('Selected'); + + if (typeof updateSelectedPrompt != undefined) + updateSelectedPrompt(); } @@ -379,6 +382,9 @@ function toggleSelectRow(sender, row) { row.addClassName('Selected'); else row.removeClassName('Selected'); + + if (typeof updateSelectedPrompt != undefined) + updateSelectedPrompt(); } function checkboxToggleElement(elem, id) { diff --git a/js/viewfeed.js b/js/viewfeed.js index da5ded64f..519ab3449 100644 --- a/js/viewfeed.js +++ b/js/viewfeed.js @@ -639,11 +639,33 @@ function toggleSelected(id, force_on) { if (cb) cb.attr("checked", true); } } + + updateSelectedPrompt(); } catch (e) { exception_error("toggleSelected", e); } } +function updateSelectedPrompt() { + try { + var count = getSelectedArticleIds2().size(); + var elem = $("selected_prompt"); + + if (elem) { + elem.innerHTML = ngettext("%d article selected", + "%d articles selected", count).replace("%d", count); + + if (count > 0) + Element.show(elem); + else + Element.hide(elem); + } + + } catch (e) { + exception_error("updateSelectedPrompt", e); + } +} + function toggleUnread_afh(effect) { try { @@ -960,6 +982,8 @@ function selectArticles(mode) { } }); + updateSelectedPrompt(); + } catch (e) { exception_error("selectArticles", e); } diff --git a/tt-rss.css b/tt-rss.css index 6067ca7d6..d2e854d8f 100644 --- a/tt-rss.css +++ b/tt-rss.css @@ -1019,3 +1019,6 @@ div.hl.active a.title { color : #4684ff; } +#selected_prompt { + margin-right : 25px; +} -- cgit v1.2.3-54-g00ecf From 95437e9e0756edacb835843074c12632c11a64b1 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 17 Apr 2013 10:50:46 +0400 Subject: tweak notify layout/display --- index.php | 2 +- js/functions.js | 44 ++++++++++++++------------------------------ prefs.php | 2 +- tt-rss.css | 27 +++++++++++++++++---------- 4 files changed, 33 insertions(+), 42 deletions(-) (limited to 'js/functions.js') diff --git a/index.php b/index.php index 2fa856631..066b25fa5 100644 --- a/index.php +++ b/index.php @@ -138,7 +138,7 @@ -
 
+ diff --git a/js/functions.js b/js/functions.js index 9336433ca..e02767504 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1,8 +1,8 @@ -var notify_silent = false; var loading_progress = 0; var sanity_check_done = false; var init_params = {}; var _label_base_index = -1024; +var notify_hide_timerid = false; Ajax.Base.prototype.initialize = Ajax.Base.prototype.initialize.wrap( function (callOriginal, options) { @@ -147,42 +147,28 @@ function param_unescape(arg) { return unescape(arg); } -var notify_hide_timerid = false; function hide_notify() { - var n = $("notify"); - if (n) { - n.style.display = "none"; - } -} - -function notify_silent_next() { - notify_silent = true; + Element.hide('notify'); } function notify_real(msg, no_hide, n_type) { - if (notify_silent) { - notify_silent = false; - return; - } - var n = $("notify"); - var nb = $("notify_body"); - if (!n || !nb) return; + if (!n) return; if (notify_hide_timerid) { window.clearTimeout(notify_hide_timerid); } if (msg == "") { - if (n.style.display == "block") { + if (Element.visible(n)) { notify_hide_timerid = window.setTimeout("hide_notify()", 0); } return; } else { - n.style.display = "block"; + Element.show(n); } /* types: @@ -194,33 +180,31 @@ function notify_real(msg, no_hide, n_type) { */ - msg = __(msg); + msg = " " + __(msg) + ""; if (n_type == 1) { n.className = "notify"; } else if (n_type == 2) { n.className = "notify progress"; - msg = " " + msg; + msg = "" + msg; + no_hide = true; } else if (n_type == 3) { n.className = "notify error"; - msg = " " + msg; + msg = "" + msg; } else if (n_type == 4) { n.className = "notify info"; - msg = " " + msg; - } - - if (no_hide) { - msg += " (" + - __("close") + ")"; + msg = "" + msg; } + msg += " "; // msg = " " + msg; - nb.innerHTML = msg; + n.innerHTML = msg; if (!no_hide) { - notify_hide_timerid = window.setTimeout("hide_notify()", 3000); + notify_hide_timerid = window.setTimeout("hide_notify()", 5*1000); } } diff --git a/prefs.php b/prefs.php index a047931c6..e3b62da70 100644 --- a/prefs.php +++ b/prefs.php @@ -93,7 +93,7 @@ -
 
+
diff --git a/tt-rss.css b/tt-rss.css index d2e854d8f..8e87d6598 100644 --- a/tt-rss.css +++ b/tt-rss.css @@ -132,14 +132,12 @@ a:hover { } #notify { - top : 25px; + bottom : 10px; right : 10px; border-width : 1px; border-style : solid; position : absolute; - display : none; - float : right; - font-size : 11px; + font-size : 12px; z-index : 99; padding : 5px; min-width : 200px; @@ -148,7 +146,21 @@ a:hover { #notify img { vertical-align : middle; - margin-right : 4px; + max-height : 14px; +} + +#notify span.msg { + width : 100%; +} + +#notify span.close { + text-align : right; +} + +#notify span { + display : table-cell; + vertical-align : middle; + padding : 4px; } .notify { @@ -171,11 +183,6 @@ a:hover { border-color : #ff0000; } -.notify.error span:hover { - color : red; - cursor : pointer; -} - .hl.Unread div.hlTitle { font-weight : bold; } -- cgit v1.2.3-54-g00ecf From ebec81a6fb2dff0b2fe6b569b021e057995ee6c7 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 19 Apr 2013 13:17:28 +0400 Subject: subscribe: verify XML before adding to the database; fetch: try to work around entity problems if initial parsing fails --- include/functions.php | 19 +++++++++++++++++++ include/rssfuncs.php | 29 ++++++++++++++++++++++++++++- js/functions.js | 38 +++++--------------------------------- 3 files changed, 52 insertions(+), 34 deletions(-) (limited to 'js/functions.js') diff --git a/include/functions.php b/include/functions.php index 4cc8f134d..8ac5753c9 100644 --- a/include/functions.php +++ b/include/functions.php @@ -1558,6 +1558,7 @@ * Here you should call extractfeedurls in rpc-backend * to get all possible feeds. * 5 - Couldn't download the URL content. + * 6 - Content is an invalid XML. */ function subscribe_to_feed($url, $cat_id = 0, $auth_login = '', $auth_pass = '') { @@ -1588,6 +1589,18 @@ $url = key($feedUrls); } + libxml_use_internal_errors(true); + $doc = new DOMDocument(); + $doc->loadXML(html_entity_decode($contents)); + $error = libxml_get_last_error(); + libxml_clear_errors(); + + if ($error) { + $error_message = format_libxml_error($error); + + return array("code" => 6, "message" => $error_message); + } + if ($cat_id == "0" || !$cat_id) { $cat_qpart = "NULL"; } else { @@ -4203,4 +4216,10 @@ return LABEL_BASE_INDEX - 1 + abs($feed); } + function format_libxml_error($error) { + return T_sprintf("LibXML error %s at line %d (column %d): %s", + $error->code, $error->line, $error->column, + $error->message); + } + ?> diff --git a/include/rssfuncs.php b/include/rssfuncs.php index 31d35bf8e..47d622169 100644 --- a/include/rssfuncs.php +++ b/include/rssfuncs.php @@ -316,6 +316,25 @@ _debug("update_rss_feed: fetch done."); } + $error = verify_feed_xml($feed_data); + + if ($error) { + if ($debug_enabled) { + _debug("update_rss_feed: error verifying XML, code: " . $error->code); + } + + if ($error->code == 26) { + if ($debug_enabled) { + _debug("update_rss_feed: got error 26, trying to decode entities..."); + } + + $feed_data = html_entity_decode($feed_data, ENT_COMPAT, 'UTF-8'); + + $error = verify_feed_xml($feed_data); + + if ($error) $feed_data = ''; + } + } } if (!$feed_data) { @@ -559,7 +578,7 @@ _debug("update_rss_feed: date $entry_timestamp [$entry_timestamp_fmt]"); } - $entry_title = html_entity_decode($item->get_title()); + $entry_title = html_entity_decode($item->get_title(), ENT_COMPAT, 'UTF-8'); $entry_link = rewrite_relative_url($site_url, $item->get_link()); @@ -1421,5 +1440,13 @@ mb_strtolower(strip_tags($title), 'utf-8')); } + function verify_feed_xml($feed_data) { + libxml_use_internal_errors(true); + $doc = new DOMDocument(); + $doc->loadXML($feed_data); + $error = libxml_get_last_error(); + libxml_clear_errors(); + return $error; + } ?> diff --git a/js/functions.js b/js/functions.js index e02767504..04be58bf7 100644 --- a/js/functions.js +++ b/js/functions.js @@ -816,39 +816,6 @@ function quickAddFeed() { alert(__("Specified URL doesn't seem to contain any feeds.")); break; case 4: - /* notify_progress("Searching for feed urls...", true); - - new Ajax.Request("backend.php", { - parameters: 'op=rpc&method=extractfeedurls&url=' + param_escape(feed_url), - onComplete: function(transport, dialog, feed_url) { - - notify(''); - - var reply = JSON.parse(transport.responseText); - - var feeds = reply['urls']; - - console.log(transport.responseText); - - var select = dijit.byId("feedDlg_feedContainerSelect"); - - while (select.getOptions().length > 0) - select.removeOption(0); - - var count = 0; - for (var feedUrl in feeds) { - select.addOption({value: feedUrl, label: feeds[feedUrl]}); - count++; - } - -// if (count > 5) count = 5; -// select.size = count; - - Effect.Appear('feedDlg_feedsContainer', {duration : 0.5}); - } - }); - break; */ - feeds = rc['feeds']; var select = dijit.byId("feedDlg_feedContainerSelect"); @@ -871,6 +838,11 @@ function quickAddFeed() { alert(__("Couldn't download the specified URL: %s"). replace("%s", rc['message'])); break; + case 6: + alert(__("XML validation failed: %s"). + replace("%s", rc['message'])); + break; + break; case 0: alert(__("You are already subscribed to this feed.")); break; -- cgit v1.2.3-54-g00ecf From f66492d357010a2e5ec11e07fd6db9825184d37d Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sat, 20 Apr 2013 10:43:21 +0400 Subject: better javascript error reporting, save error reports in tt-rss log --- classes/rpc.php | 11 +++++++++++ js/functions.js | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) (limited to 'js/functions.js') diff --git a/classes/rpc.php b/classes/rpc.php index 61c815b36..750aa2cb1 100644 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -634,5 +634,16 @@ class RPC extends Handler_Protected { } } + function log() { + $logmsg = $this->dbh->escape_string($_REQUEST['logmsg']); + + if ($logmsg) { + Logger::get()->log_error(E_USER_WARNING, + $logmsg, '[client-js]', 0, false); + } + + echo json_encode(array("message" => "HOST_ERROR_LOGGED")); + + } } ?> diff --git a/js/functions.js b/js/functions.js index 04be58bf7..8442e1c9f 100644 --- a/js/functions.js +++ b/js/functions.js @@ -50,6 +50,21 @@ function exception_error(location, e, ext_info) { } } + try { + new Ajax.Request("backend.php", { + parameters: {op: "rpc", method: "log", logmsg: msg}, + onComplete: function (transport) { + console.log(transport.responseText); + } }); + + } catch (eii) { + console.log("Exception while trying to log the error."); + console.log(eii); + } + + msg += "

"+ __("The error will be reported to the configured log destination.") + + "

"; + var content = "
" + "
" + msg + "
"; @@ -106,7 +121,28 @@ function exception_error(location, e, ext_info) { dialog.show(); - } catch (e) { + } catch (ei) { + console.log("Exception while trying to report an exception. Oh boy."); + console.log(ei); + console.log("Original exception:"); + console.log(e); + + msg += "\n\nAdditional exception caught while trying to show the error dialog.\n\n" + format_exception_error('exception_error', ei); + + try { + new Ajax.Request("backend.php", { + parameters: {op: "rpc", method: "log", logmsg: msg}, + onComplete: function (transport) { + console.log(transport.responseText); + } }); + + } catch (eii) { + console.log("Third exception while trying to log the error! Seriously?"); + console.log(eii); + } + + msg += "\n\nThe error will be reported to the configured log destination."; + alert(msg); } -- cgit v1.2.3-54-g00ecf From abbe9c1f555baa7ae14b9424ff995edb16122d1c Mon Sep 17 00:00:00 2001 From: supahgreg Date: Sat, 27 Apr 2013 09:45:02 -0500 Subject: minor: remove duplicate check for params --- js/functions.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'js/functions.js') diff --git a/js/functions.js b/js/functions.js index 8442e1c9f..87c52b709 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1269,13 +1269,11 @@ function backend_sanity_check_callback(transport) { if (params) { console.log('reading init-params...'); - if (params) { - for (k in params) { - var v = params[k]; - console.log("IP: " + k + " => " + v); + for (k in params) { + var v = params[k]; + console.log("IP: " + k + " => " + v); - if (k == "label_base_index") _label_base_index = parseInt(v); - } + if (k == "label_base_index") _label_base_index = parseInt(v); } init_params = params; -- cgit v1.2.3-54-g00ecf From 8ceea119a8287568439a2a9d167b333f74a47e21 Mon Sep 17 00:00:00 2001 From: supahgreg Date: Sat, 27 Apr 2013 11:01:54 -0500 Subject: Add JS PluginHost.HOOK_PARAMS_LOADED and PluginHost.HOOK_RUNTIME_INFO_LOADED to notify when interesting info has been created/updated. --- js/PluginHost.js | 2 ++ js/functions.js | 3 +++ js/tt-rss.js | 4 +++- 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'js/functions.js') diff --git a/js/PluginHost.js b/js/PluginHost.js index de4c57b60..668d215f9 100644 --- a/js/PluginHost.js +++ b/js/PluginHost.js @@ -8,6 +8,8 @@ var PluginHost = { HOOK_FEED_LOADED: 5, HOOK_ARTICLE_EXPANDED: 6, HOOK_ARTICLE_COLLAPSED: 7, + HOOK_PARAMS_LOADED: 8, + HOOK_RUNTIME_INFO_LOADED: 9, hooks: [], register: function (name, callback) { if (typeof(this.hooks[name]) == 'undefined') diff --git a/js/functions.js b/js/functions.js index 87c52b709..8691c1ee5 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1277,6 +1277,9 @@ function backend_sanity_check_callback(transport) { } init_params = params; + + // PluginHost might not be available on non-index pages + window.PluginHost && PluginHost.run(PluginHost.HOOK_PARAMS_LOADED, init_params); } sanity_check_done = true; diff --git a/js/tt-rss.js b/js/tt-rss.js index a7518959c..2a741ab2d 100644 --- a/js/tt-rss.js +++ b/js/tt-rss.js @@ -753,6 +753,8 @@ function parse_runtime_info(data) { init_params[k] = v; notify(''); } + + PluginHost.run(PluginHost.HOOK_RUNTIME_INFO_LOADED, data); } function collapse_feedlist() { @@ -992,7 +994,7 @@ function handle_rpc_json(transport, scheduled_call) { if (counters) parse_counters(counters, scheduled_call); - var runtime_info = reply['runtime-info'];; + var runtime_info = reply['runtime-info']; if (runtime_info) parse_runtime_info(runtime_info); -- cgit v1.2.3-54-g00ecf