add article prefetching, remove history tracking
This commit is contained in:
parent
465ff90b4a
commit
e097e8be75
45
backend.php
45
backend.php
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
$print_exec_time = false;
|
$print_exec_time = false;
|
||||||
|
|
||||||
if ((!$op || $op == "rpc" || $op == "rss" || $op == "digestSend" ||
|
if ((!$op || $op == "rpc" || $op == "rss" || $op == "view" || $op == "digestSend" ||
|
||||||
$op == "globalUpdateFeeds") && !$_REQUEST["noxml"]) {
|
$op == "globalUpdateFeeds") && !$_REQUEST["noxml"]) {
|
||||||
header("Content-Type: application/xml; charset=utf-8");
|
header("Content-Type: application/xml; charset=utf-8");
|
||||||
} else {
|
} else {
|
||||||
|
@ -141,10 +141,9 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($op == "view") {
|
function outputArticleXML($link, $id, $feed_id, $mark_as_read = true) {
|
||||||
|
|
||||||
$id = db_escape_string($_GET["id"]);
|
print "<article id='$id'><![CDATA[";
|
||||||
$feed_id = db_escape_string($_GET["feed"]);
|
|
||||||
|
|
||||||
$result = db_query($link, "SELECT rtl_content FROM ttrss_feeds
|
$result = db_query($link, "SELECT rtl_content FROM ttrss_feeds
|
||||||
WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]);
|
WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
@ -163,9 +162,11 @@
|
||||||
$rtl_class = "";
|
$rtl_class = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = db_query($link, "UPDATE ttrss_user_entries
|
if ($mark_as_read) {
|
||||||
SET unread = false,last_read = NOW()
|
$result = db_query($link, "UPDATE ttrss_user_entries
|
||||||
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
SET unread = false,last_read = NOW()
|
||||||
|
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
}
|
||||||
|
|
||||||
$result = db_query($link, "SELECT title,link,content,feed_id,comments,int_id,
|
$result = db_query($link, "SELECT title,link,content,feed_id,comments,int_id,
|
||||||
SUBSTRING(updated,1,16) as updated,
|
SUBSTRING(updated,1,16) as updated,
|
||||||
|
@ -289,6 +290,36 @@
|
||||||
print "</div>";
|
print "</div>";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print "]]></article>";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($op == "view") {
|
||||||
|
|
||||||
|
$id = db_escape_string($_GET["id"]);
|
||||||
|
$feed_id = db_escape_string($_GET["feed"]);
|
||||||
|
$cids = split(",", db_escape_string($_GET["cids"]));
|
||||||
|
$mode = db_escape_string($_GET["mode"]);
|
||||||
|
|
||||||
|
print "<reply>";
|
||||||
|
|
||||||
|
// in prefetch mode we only output requested cids, main article
|
||||||
|
// just gets marked as read (it already exists in client cache)
|
||||||
|
|
||||||
|
if ($mode != "prefetch") {
|
||||||
|
outputArticleXML($link, $id, $feed_id);
|
||||||
|
} else {
|
||||||
|
catchupArticleById($link, $id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($cids as $cid) {
|
||||||
|
if ($cid) {
|
||||||
|
outputArticleXML($link, $cid, $feed_id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print "</reply>";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($op == "viewfeed") {
|
if ($op == "viewfeed") {
|
||||||
|
|
|
@ -46,10 +46,10 @@ function viewfeed(feed, subop, is_cat, subop_param, skip_history, offset) {
|
||||||
|
|
||||||
enableHotkeys();
|
enableHotkeys();
|
||||||
|
|
||||||
if (!skip_history) {
|
/* if (!skip_history) {
|
||||||
history_push('FEED:' + feed + ':' + subop + ':' + is_cat +
|
history_push('FEED:' + feed + ':' + subop + ':' + is_cat +
|
||||||
':' + subop_param);
|
':' + subop_param);
|
||||||
}
|
} */
|
||||||
|
|
||||||
var toolbar_query = Form.serialize("main_toolbar_form");
|
var toolbar_query = Form.serialize("main_toolbar_form");
|
||||||
var toolbar_form = document.forms["main_toolbar_form"];
|
var toolbar_form = document.forms["main_toolbar_form"];
|
||||||
|
|
31
functions.js
31
functions.js
|
@ -1667,3 +1667,34 @@ function logoutUser() {
|
||||||
exception_error("logoutUser", e);
|
exception_error("logoutUser", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this only searches loaded headlines list, not in CDM
|
||||||
|
function getRelativePostIds(id) {
|
||||||
|
|
||||||
|
debug("getRelativePostIds: " + id);
|
||||||
|
|
||||||
|
var ids = new Array();
|
||||||
|
var container = document.getElementById("headlinesList");
|
||||||
|
|
||||||
|
if (container) {
|
||||||
|
var rows = container.rows;
|
||||||
|
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
var r_id = rows[i].id.replace("RROW-", "");
|
||||||
|
|
||||||
|
if (r_id == id) {
|
||||||
|
if (i > 0) ids.push(rows[i-1].id.replace("RROW-", ""));
|
||||||
|
if (i > 1) ids.push(rows[i-2].id.replace("RROW-", ""));
|
||||||
|
if (i > 2) ids.push(rows[i-3].id.replace("RROW-", ""));
|
||||||
|
|
||||||
|
if (i < rows.length) ids.push(rows[i+1].id.replace("RROW-", ""));
|
||||||
|
if (i < rows.length-1) ids.push(rows[i+2].id.replace("RROW-", ""));
|
||||||
|
if (i < rows.length-2) ids.push(rows[i+3].id.replace("RROW-", ""));
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -2811,6 +2811,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function catchupArticleById($link, $id, $cmode) {
|
||||||
|
|
||||||
|
if ($cmode == 0) {
|
||||||
|
db_query($link, "UPDATE ttrss_user_entries SET
|
||||||
|
unread = false,last_read = NOW()
|
||||||
|
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
} else if ($cmode == 1) {
|
||||||
|
db_query($link, "UPDATE ttrss_user_entries SET
|
||||||
|
unread = true
|
||||||
|
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
} else {
|
||||||
|
db_query($link, "UPDATE ttrss_user_entries SET
|
||||||
|
unread = NOT unread,last_read = NOW()
|
||||||
|
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function escape_for_form($s) {
|
function escape_for_form($s) {
|
||||||
return htmlspecialchars(db_unescape_string($s));
|
return htmlspecialchars(db_unescape_string($s));
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ var xmlhttp_ctr = Ajax.getTransport();
|
||||||
|
|
||||||
var init_params = new Object();
|
var init_params = new Object();
|
||||||
|
|
||||||
var op_history = new Array();
|
//var op_history = new Array();
|
||||||
|
|
||||||
function tagsAreDisplayed() {
|
function tagsAreDisplayed() {
|
||||||
return display_tags;
|
return display_tags;
|
||||||
|
@ -696,7 +696,7 @@ function feedEditSave() {
|
||||||
exception_error("feedEditSave (main)", e);
|
exception_error("feedEditSave (main)", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
function localHotkeyHandler(e) {
|
function localHotkeyHandler(e) {
|
||||||
|
|
||||||
var keycode;
|
var keycode;
|
||||||
|
@ -756,7 +756,7 @@ function localHotkeyHandler(e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
debug("LKP=" + keycode);
|
debug("LKP=" + keycode);
|
||||||
}
|
}
|
||||||
|
|
||||||
function history_push(op) {
|
function history_push(op) {
|
||||||
debug("history_push: " + op);
|
debug("history_push: " + op);
|
||||||
|
@ -776,4 +776,4 @@ function history_pop() {
|
||||||
function history_clear() {
|
function history_clear() {
|
||||||
debug("history_clear");
|
debug("history_clear");
|
||||||
op_history.clear();
|
op_history.clear();
|
||||||
}
|
} */
|
||||||
|
|
141
viewfeed.js
141
viewfeed.js
|
@ -16,6 +16,8 @@ var _reload_feedlist_after_view = false;
|
||||||
var _cdm_wd_timeout = false;
|
var _cdm_wd_timeout = false;
|
||||||
var _cdm_wd_vishist = new Array();
|
var _cdm_wd_vishist = new Array();
|
||||||
|
|
||||||
|
var article_cache = new Array();
|
||||||
|
|
||||||
function catchup_callback() {
|
function catchup_callback() {
|
||||||
if (xmlhttp_rpc.readyState == 4) {
|
if (xmlhttp_rpc.readyState == 4) {
|
||||||
try {
|
try {
|
||||||
|
@ -66,14 +68,49 @@ function headlines_callback() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function article_callback() {
|
function render_article(article) {
|
||||||
if (xmlhttp.readyState == 4) {
|
try {
|
||||||
debug("article_callback");
|
|
||||||
var f = document.getElementById("content-frame");
|
var f = document.getElementById("content-frame");
|
||||||
try {
|
try {
|
||||||
f.scrollTop = 0;
|
f.scrollTop = 0;
|
||||||
} catch (e) { };
|
} catch (e) { };
|
||||||
f.innerHTML = xmlhttp.responseText;
|
|
||||||
|
f.innerHTML = article;
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
exception_error("render_article", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function article_callback() {
|
||||||
|
if (xmlhttp.readyState == 4) {
|
||||||
|
debug("article_callback");
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (xmlhttp.responseXML) {
|
||||||
|
var reply = xmlhttp.responseXML.firstChild.firstChild;
|
||||||
|
|
||||||
|
var articles = xmlhttp.responseXML.getElementsByTagName("article");
|
||||||
|
|
||||||
|
for (var i = 0; i < articles.length; i++) {
|
||||||
|
var a_id = articles[i].getAttribute("id");
|
||||||
|
|
||||||
|
debug("found id: " + a_id);
|
||||||
|
|
||||||
|
if (a_id == active_post_id) {
|
||||||
|
debug("active article, rendering...");
|
||||||
|
render_article(articles[i].firstChild.nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_inject(a_id, articles[i].firstChild.nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
debug("article_callback: returned no XML object");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
exception_error("article_callback", e);
|
||||||
|
}
|
||||||
|
|
||||||
var date = new Date();
|
var date = new Date();
|
||||||
last_article_view = date.getTime() / 1000;
|
last_article_view = date.getTime() / 1000;
|
||||||
|
@ -100,9 +137,13 @@ function view(id, feed_id, skip_history) {
|
||||||
|
|
||||||
active_real_feed_id = feed_id;
|
active_real_feed_id = feed_id;
|
||||||
|
|
||||||
if (!skip_history) {
|
var cached_article = cache_find(id);
|
||||||
|
|
||||||
|
debug("cache check result: " + (cached_article != false));
|
||||||
|
|
||||||
|
/* if (!skip_history) {
|
||||||
history_push("ARTICLE:" + id + ":" + feed_id);
|
history_push("ARTICLE:" + id + ":" + feed_id);
|
||||||
}
|
} */
|
||||||
|
|
||||||
enableHotkeys();
|
enableHotkeys();
|
||||||
|
|
||||||
|
@ -119,11 +160,15 @@ function view(id, feed_id, skip_history) {
|
||||||
xmlhttp.abort();
|
xmlhttp.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlhttp_ready(xmlhttp)) {
|
if (cached_article || xmlhttp_ready(xmlhttp)) {
|
||||||
|
|
||||||
cleanSelected("headlinesList");
|
cleanSelected("headlinesList");
|
||||||
|
|
||||||
var crow = document.getElementById("RROW-" + active_post_id);
|
var crow = document.getElementById("RROW-" + active_post_id);
|
||||||
|
|
||||||
|
var article_is_unread = crow.className.match("Unread");
|
||||||
|
debug("article is unread: " + article_is_unread);
|
||||||
|
|
||||||
crow.className = crow.className.replace("Unread", "");
|
crow.className = crow.className.replace("Unread", "");
|
||||||
|
|
||||||
var upd_img_pic = document.getElementById("FUPDPIC-" + active_post_id);
|
var upd_img_pic = document.getElementById("FUPDPIC-" + active_post_id);
|
||||||
|
@ -135,15 +180,55 @@ function view(id, feed_id, skip_history) {
|
||||||
selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
|
selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false);
|
||||||
markHeadline(active_post_id);
|
markHeadline(active_post_id);
|
||||||
|
|
||||||
|
var neighbor_ids = getRelativePostIds(active_post_id);
|
||||||
|
|
||||||
|
/* only request uncached articles */
|
||||||
|
|
||||||
|
var cids_to_request = Array();
|
||||||
|
|
||||||
|
for (var i = 0; i < neighbor_ids.length; i++) {
|
||||||
|
if (!cache_check(neighbor_ids[i])) {
|
||||||
|
cids_to_request.push(neighbor_ids[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("additional ids: " + cids_to_request.toString());
|
||||||
|
|
||||||
var date = new Date();
|
var date = new Date();
|
||||||
var timestamp = Math.round(date.getTime() / 1000);
|
var timestamp = Math.round(date.getTime() / 1000);
|
||||||
query = query + "&ts=" + timestamp;
|
query = query + "&ts=" + timestamp;
|
||||||
|
|
||||||
notify_progress("Loading, please wait...");
|
query = query + "&cids=" + cids_to_request.toString();
|
||||||
|
|
||||||
|
if (!cached_article) {
|
||||||
|
|
||||||
|
notify_progress("Loading, please wait...");
|
||||||
|
|
||||||
|
debug(query);
|
||||||
|
|
||||||
|
xmlhttp.open("GET", query, true);
|
||||||
|
xmlhttp.onreadystatechange=article_callback;
|
||||||
|
xmlhttp.send(null);
|
||||||
|
} else if (cached_article && article_is_unread) {
|
||||||
|
|
||||||
|
query = query + "&mode=prefetch";
|
||||||
|
|
||||||
|
debug(query);
|
||||||
|
|
||||||
|
xmlhttp.open("GET", query, true);
|
||||||
|
xmlhttp.onreadystatechange=article_callback;
|
||||||
|
xmlhttp.send(null);
|
||||||
|
|
||||||
|
render_article(cached_article);
|
||||||
|
|
||||||
|
} else if (cached_article) {
|
||||||
|
|
||||||
|
render_article(cached_article);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_expire();
|
||||||
|
|
||||||
xmlhttp.open("GET", query, true);
|
|
||||||
xmlhttp.onreadystatechange=article_callback;
|
|
||||||
xmlhttp.send(null);
|
|
||||||
} else {
|
} else {
|
||||||
debug("xmlhttp busy (@view)");
|
debug("xmlhttp busy (@view)");
|
||||||
printLockingError();
|
printLockingError();
|
||||||
|
@ -650,3 +735,37 @@ function cdmWatchdog() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function cache_inject(id, article) {
|
||||||
|
if (!article_cache[id]) {
|
||||||
|
debug("cache_article: miss: " + id);
|
||||||
|
|
||||||
|
var cache_obj = new Array();
|
||||||
|
|
||||||
|
var d = new Date();
|
||||||
|
cache_obj["entered"] = d.getTime() / 1000;
|
||||||
|
cache_obj["data"] = article;
|
||||||
|
|
||||||
|
article_cache[id] = cache_obj;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
debug("cache_article: hit: " + id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cache_find(id) {
|
||||||
|
if (typeof article_cache[id] != 'undefined') {
|
||||||
|
return article_cache[id]["data"];
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cache_check(id) {
|
||||||
|
return typeof article_cache[id] != 'undefined';
|
||||||
|
}
|
||||||
|
|
||||||
|
function cache_expire() {
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue