summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2011-08-31 15:25:42 +0400
committerAndrew Dolgov <[email protected]>2011-08-31 16:15:01 +0400
commit37c03d3a420853b61348de87150a69a567c00146 (patch)
treede39fcfc127af3a7b7a9492bae9689628471e299
parent165c88ff3166825dcccfa2d30a9c3574e64c8549 (diff)
implement automatic precaching for next normal and unread feeds
allow opening cached next_unread_feed on f-q if available tweak getRelativeArticles() to scan forward only reenable prefetch_old server requests
-rw-r--r--backend.php2
-rw-r--r--feedlist.js148
-rw-r--r--functions.php4
-rw-r--r--modules/backend-rpc.php5
-rw-r--r--tt-rss.js4
-rw-r--r--viewfeed.js84
6 files changed, 149 insertions, 98 deletions
diff --git a/backend.php b/backend.php
index d039740b3..e3260739f 100644
--- a/backend.php
+++ b/backend.php
@@ -257,7 +257,7 @@
$subop = db_escape_string($_REQUEST["subop"]);
$view_mode = db_escape_string($_REQUEST["view_mode"]);
$limit = (int) get_pref($link, "DEFAULT_ARTICLE_LIMIT");
- @$cat_view = db_escape_string($_REQUEST["cat"]);
+ @$cat_view = db_escape_string($_REQUEST["cat"]) == "true";
@$next_unread_feed = db_escape_string($_REQUEST["nuf"]);
@$offset = db_escape_string($_REQUEST["skip"]);
@$vgroup_last_feed = db_escape_string($_REQUEST["vgrlf"]);
diff --git a/feedlist.js b/feedlist.js
index ab21a30fb..fc3bcd9c7 100644
--- a/feedlist.js
+++ b/feedlist.js
@@ -48,7 +48,7 @@ function loadMoreHeadlines() {
}
-function viewfeed(feed, subop, is_cat, offset) {
+function viewfeed(feed, subop, is_cat, offset, background) {
try {
if (is_cat == undefined)
is_cat = false;
@@ -57,6 +57,7 @@ function viewfeed(feed, subop, is_cat, offset) {
if (subop == undefined) subop = '';
if (offset == undefined) offset = 0;
+ if (background == undefined) background = false;
last_requested_article = 0;
@@ -72,101 +73,112 @@ function viewfeed(feed, subop, is_cat, offset) {
var force_nocache = false;
- if (getActiveFeedId() != feed || offset == 0) {
- active_post_id = 0;
- _infscroll_disable = 0;
- }
+ if (!background) {
+ if (getActiveFeedId() != feed || offset == 0) {
+ active_post_id = 0;
+ _infscroll_disable = 0;
+ }
- if (!offset && !subop && cached_headlines) {
- try {
- render_local_headlines(feed, is_cat, JSON.parse(cached_headlines));
- return;
- } catch (e) {
- console.warn("render_local_headlines failed: " + e);
+ if (!offset && !subop && cached_headlines && !background) {
+ try {
+ render_local_headlines(feed, is_cat, JSON.parse(cached_headlines));
+ return;
+ } catch (e) {
+ console.warn("render_local_headlines failed: " + e);
+ }
}
- }
- if (offset != 0 && !subop) {
- var date = new Date();
- var timestamp = Math.round(date.getTime() / 1000);
+ if (offset != 0 && !subop) {
+ var date = new Date();
+ var timestamp = Math.round(date.getTime() / 1000);
- if (_infscroll_request_sent && _infscroll_request_sent + 30 > timestamp) {
- //console.log("infscroll request in progress, aborting");
- return;
+ if (_infscroll_request_sent && _infscroll_request_sent + 30 > timestamp) {
+ //console.log("infscroll request in progress, aborting");
+ return;
+ }
+
+ _infscroll_request_sent = timestamp;
}
- _infscroll_request_sent = timestamp;
+ hideAuxDlg();
}
- hideAuxDlg();
-
Form.enable("main_toolbar_form");
- var toolbar_form = document.forms["main_toolbar_form"];
var toolbar_query = Form.serialize("main_toolbar_form");
- if (toolbar_form.query) {
- if (toolbar_form.query.value != "") {
+ var query = "?op=viewfeed&feed=" + feed + "&" +
+ toolbar_query + "&subop=" + param_escape(subop);
+
+ if (!background) {
+ if (_search_query) {
force_nocache = true;
+ query = query + "&" + _search_query;
+ _search_query = false;
}
- toolbar_form.query.value = "";
- }
- var query = "?op=viewfeed&feed=" + feed + "&" +
- toolbar_query + "&subop=" + param_escape(subop);
+ if (subop == "MarkAllRead") {
- if (_search_query) {
- force_nocache = true;
- query = query + "&" + _search_query;
- _search_query = false;
- }
+ var show_next_feed = getInitParam("on_catchup_show_next_feed") == "1";
- if (subop == "MarkAllRead") {
+ if (show_next_feed) {
+ var nuf = getNextUnreadFeed(feed, is_cat);
- var show_next_feed = getInitParam("on_catchup_show_next_feed") == "1";
+ if (nuf) {
+ var cached_nuf = cache_get("feed:" + nuf + ":false");
- if (show_next_feed) {
- var tree = dijit.byId("feedTree");
- var nuf = tree.model.getNextUnreadFeed(feed, is_cat);
+ if (cached_nuf) {
- if (nuf) {
- var nuf_id = tree.model.store.getValue(nuf, 'bare_id');
+ render_local_headlines(nuf, false, JSON.parse(cached_nuf));
- query = query + "&nuf=" + param_escape(nuf_id);
+ var catchup_query = "?op=rpc&subop=catchupFeed&feed_id=" +
+ feed + "&is_cat=" + is_cat;
+
+ console.log(catchup_query);
+
+ new Ajax.Request("backend.php", {
+ parameters: catchup_query,
+ onComplete: function(transport) {
+ handle_rpc_json(transport);
+ } });
+
+ return;
+ } else {
+ query += "&nuf=" + param_escape(nuf);
+ }
+ }
}
}
- }
- if (is_cat) {
- query = query + "&cat=1";
- }
-
- if (offset != 0) {
- query = query + "&skip=" + offset;
+ if (offset != 0) {
+ query = query + "&skip=" + offset;
- // to prevent duplicate feed titles when showing grouped vfeeds
- if (vgroup_last_feed) {
- query = query + "&vgrlf=" + param_escape(vgroup_last_feed);
+ // to prevent duplicate feed titles when showing grouped vfeeds
+ if (vgroup_last_feed) {
+ query = query + "&vgrlf=" + param_escape(vgroup_last_feed);
+ }
}
+
+ Form.enable("main_toolbar_form");
+
+ if (!offset)
+ if (!is_cat) {
+ if (!setFeedExpandoIcon(feed, is_cat, 'images/indicator_white.gif'))
+ notify_progress("Loading, please wait...", true);
+ } else {
+ notify_progress("Loading, please wait...", true);
+ }
}
- Form.enable("main_toolbar_form");
+ query += "&cat=" + is_cat;
console.log(query);
- if (!offset)
- if (!is_cat) {
- if (!setFeedExpandoIcon(feed, is_cat, 'images/indicator_white.gif'))
- notify_progress("Loading, please wait...", true);
- } else {
- notify_progress("Loading, please wait...", true);
- }
-
new Ajax.Request("backend.php", {
parameters: query,
onComplete: function(transport) {
setFeedExpandoIcon(feed, is_cat, 'images/blank_icon.gif');
- headlines_callback2(transport, offset);
+ headlines_callback2(transport, offset, background);
} });
} catch (e) {
@@ -428,3 +440,17 @@ function setFeedExpandoIcon(feed, is_cat, src) {
}
return false;
}
+
+function getNextUnreadFeed(feed, is_cat) {
+ try {
+ var tree = dijit.byId("feedTree");
+ var nuf = tree.model.getNextUnreadFeed(feed, is_cat);
+
+ if (nuf)
+ return tree.model.store.getValue(nuf, 'bare_id');
+
+ } catch (e) {
+ exception_error("getNextUnreadFeed", e);
+ }
+}
+
diff --git a/functions.php b/functions.php
index bb6164d7b..f0691f209 100644
--- a/functions.php
+++ b/functions.php
@@ -2494,8 +2494,9 @@
if (!$owner_uid) $owner_uid = $_SESSION['uid'];
- if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
+ //if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
+ if (is_numeric($feed)) {
if ($cat_view) {
if ($feed >= 0) {
@@ -2519,7 +2520,6 @@
}
} else if ($feed == -2) {
-
db_query($link, "UPDATE ttrss_user_entries
SET unread = false,last_read = NOW() WHERE (SELECT COUNT(*)
FROM ttrss_user_labels2 WHERE article_id = ref_id) > 0
diff --git a/modules/backend-rpc.php b/modules/backend-rpc.php
index a89c5ee81..dff12aa5a 100644
--- a/modules/backend-rpc.php
+++ b/modules/backend-rpc.php
@@ -657,10 +657,11 @@
if ($subop == "catchupFeed") {
$feed_id = db_escape_string($_REQUEST['feed_id']);
- $is_cat = db_escape_string($_REQUEST['is_cat']);
+ $is_cat = db_escape_string($_REQUEST['is_cat']) == "true";
catchup_feed($link, $feed_id, $is_cat);
+ print json_encode(array("message" => "UPDATE_COUNTERS"));
return;
}
@@ -758,7 +759,7 @@
if ($subop == "regenFeedKey") {
$feed_id = db_escape_string($_REQUEST['id']);
- $is_cat = (bool) db_escape_string($_REQUEST['is_cat']);
+ $is_cat = db_escape_string($_REQUEST['is_cat']) == "true";
$new_key = update_feed_access_key($link, $feed_id, $is_cat);
diff --git a/tt-rss.js b/tt-rss.js
index c8f4ab83e..3e0e95919 100644
--- a/tt-rss.js
+++ b/tt-rss.js
@@ -330,7 +330,9 @@ function init_second_stage() {
loading_set_progress(30);
- cache_clear();
+ // can't use cache_clear() here because viewfeed might not have initialized yet
+ if ('sessionStorage' in window && window['sessionStorage'] !== null)
+ sessionStorage.clear();
console.log("second stage ok");
diff --git a/viewfeed.js b/viewfeed.js
index c41c49a96..b040dc155 100644
--- a/viewfeed.js
+++ b/viewfeed.js
@@ -11,16 +11,19 @@ var last_requested_article = false;
var catchup_id_batch = [];
var catchup_timeout_id = false;
+var feed_precache_timeout_id = false;
+
+var cids_requested = [];
var has_storage = 'sessionStorage' in window && window['sessionStorage'] !== null;
-function headlines_callback2(transport, offset) {
+function headlines_callback2(transport, offset, background) {
try {
handle_rpc_json(transport);
loading_set_progress(25);
- console.log("headlines_callback2 [offset=" + offset + "]");
+ console.log("headlines_callback2 [offset=" + offset + "] B:" + background);
var is_cat = false;
var feed_id = false;
@@ -38,11 +41,12 @@ function headlines_callback2(transport, offset) {
is_cat = reply['headlines']['is_cat'];
feed_id = reply['headlines']['id'];
- setActiveFeedId(feed_id, is_cat);
-
- var update_btn = document.forms["main_toolbar_form"].update;
+ if (background) {
+ cache_headlines(feed_id, is_cat, reply['headlines']['toolbar'], reply['headlines']['content']);
+ return;
+ }
- update_btn.disabled = !(feed_id >= 0 && !is_cat);
+ setActiveFeedId(feed_id, is_cat);
try {
if (offset == 0) {
@@ -74,10 +78,6 @@ function headlines_callback2(transport, offset) {
var hsp = $("headlines-spacer");
if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
-/* if (!_infscroll_disable)
- hsp.innerHTML = "<img src='images/indicator_tiny.gif'> " +
- __("Loading, please wait..."); */
-
dijit.byId('headlines-frame').domNode.appendChild(hsp);
initHeadlinesMenu();
@@ -103,10 +103,6 @@ function headlines_callback2(transport, offset) {
if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
-/* if (!_infscroll_disable)
- hsp.innerHTML = "<img src='images/indicator_tiny.gif'> " +
- __("Loading, please wait..."); */
-
fixHeadlinesOrder(getLoadedArticleIds());
c.domNode.appendChild(hsp);
@@ -134,7 +130,8 @@ function headlines_callback2(transport, offset) {
}
}
- cache_headlines(feed_id, is_cat, reply['headlines']['toolbar'], $("headlines-frame").innerHTML);
+ if (headlines_count > 0)
+ cache_headlines(feed_id, is_cat, reply['headlines']['toolbar'], $("headlines-frame").innerHTML);
if (articles) {
for (var i = 0; i < articles.length; i++) {
@@ -247,22 +244,25 @@ function article_callback2(transport, id) {
var reply = JSON.parse(transport.responseText);
if (reply) {
+
var upic = $('FUPDPIC-' + id);
if (upic) upic.src = 'images/blank_icon.gif';
- if (id != last_requested_article) {
- console.log("requested article id is out of sequence, aborting");
- return;
- }
-
reply.each(function(article) {
if (active_post_id == article['id']) {
render_article(article['content']);
}
+ cids_requested.remove(article['id']);
+
cache_set("article:" + article['id'], article['content']);
});
+// if (id != last_requested_article) {
+// console.log("requested article id is out of sequence, aborting");
+// return;
+// }
+
} else {
console.warn("article_callback: returned invalid data");
@@ -293,16 +293,18 @@ function view(id) {
var query = "?op=view&id=" + param_escape(id);
- var neighbor_ids = getRelativePostIds(active_post_id);
+ var neighbor_ids = getRelativePostIds(id);
/* only request uncached articles */
- var cids_to_request = Array();
+ var cids_to_request = [];
for (var i = 0; i < neighbor_ids.length; i++) {
- if (!cache_get("article:" + neighbor_ids[i])) {
- cids_to_request.push(neighbor_ids[i]);
- }
+ if (cids_requested.indexOf(neighbor_ids[i]) == -1)
+ if (!cache_get("article:" + neighbor_ids[i])) {
+ cids_to_request.push(neighbor_ids[i]);
+ cids_requested.push(neighbor_ids[i]);
+ }
}
console.log("additional ids: " + cids_to_request.toString());
@@ -315,6 +317,24 @@ function view(id) {
active_post_id = id;
showArticleInHeadlines(id);
+ if (!feed_precache_timeout_id) {
+ feed_precache_timeout_id = window.setTimeout(function() {
+ var nuf = getNextUnreadFeed(getActiveFeedId(), activeFeedIsCat());
+ var nf = dijit.byId("feedTree").getNextFeed(getActiveFeedId(), activeFeedIsCat());
+
+ if (nuf && !cache_get("feed:" + nuf + ":" + activeFeedIsCat()))
+ viewfeed(nuf, '', activeFeedIsCat(), 0, true);
+
+ if (nf && !cache_get("feed:" + nf[0] + ":" + nf[1]))
+ viewfeed(nf[0], '', nf[1], 0, true);
+
+ window.setTimeout(function() {
+ feed_precache_timeout_id = false;
+ }, 3000);
+
+ }, 1000);
+ }
+
if (!cached_article) {
var upic = $('FUPDPIC-' + id);
@@ -334,8 +354,10 @@ function view(id) {
query = query + "&mode=prefetch_old";
render_article(cached_article);
- return; // do not do prefetch_old request
-
+ // if we don't need to request any relative ids, we might as well skip
+ // the server roundtrip altogether
+ if (cids_to_request.length == 0)
+ return;
}
last_requested_article = id;
@@ -1083,7 +1105,7 @@ function headlines_scroll_handler(e) {
}
} catch (e) {
- exception_error("headlines_scroll_handler", e);
+ console.warn("headlines_scroll_handler: " + e);
}
}
@@ -1734,14 +1756,14 @@ function getRelativePostIds(id, limit) {
try {
- if (!limit) limit = 3;
+ if (!limit) limit = 6; //3
var ids = getVisibleArticleIds();
for (var i = 0; i < ids.length; i++) {
if (ids[i] == id) {
for (var k = 1; k <= limit; k++) {
- if (i > k-1) tmp.push(ids[i-k]);
+ //if (i > k-1) tmp.push(ids[i-k]);
if (i < ids.length-k) tmp.push(ids[i+k]);
}
break;
@@ -2029,7 +2051,7 @@ function player(elem) {
}
function cache_set(id, obj) {
- console.log("cache_set: " + id);
+ //console.log("cache_set: " + id);
if (has_storage)
try {
sessionStorage[id] = obj;