diff --git a/CHANGELOG b/CHANGELOG index 45936ac03..fe856fe4a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,8 @@ (voir réorganisation ci-dessous) * Pour les versions suivantes, juste garder “./data/config.php” et “./data/*_user.php”, éventuellement “./data/persona/*” +* Rafraîchissement automatique du nombre d’articles non lus toutes les minutes (utilise le cache HTTP à bon escient) + * Permet aussi de conserver la session valide, surtout dans le cas de Persona * Importation OPML instantanée et plus tolérante * Nouvelle gestion des favicons avec téléchargement en parallèle * Nouvelles options diff --git a/app/Controllers/javascriptController.php b/app/Controllers/javascriptController.php index e7e25f656..2d0ff4984 100755 --- a/app/Controllers/javascriptController.php +++ b/app/Controllers/javascriptController.php @@ -3,11 +3,17 @@ class FreshRSS_javascript_Controller extends Minz_ActionController { public function firstAction () { $this->view->_useLayout (false); - header('Content-type: text/javascript'); } public function actualizeAction () { + header('Content-Type: text/javascript; charset=UTF-8'); $feedDAO = new FreshRSS_FeedDAO (); $this->view->feeds = $feedDAO->listFeeds (); } + + public function nbUnreadsPerFeedAction() { + header('Content-Type: application/json; charset=UTF-8'); + $catDAO = new FreshRSS_CategoryDAO(); + $this->view->categories = $catDAO->listCategories(true, false); + } } diff --git a/app/views/javascript/nbUnreadsPerFeed.phtml b/app/views/javascript/nbUnreadsPerFeed.phtml new file mode 100644 index 000000000..68f98ce9e --- /dev/null +++ b/app/views/javascript/nbUnreadsPerFeed.phtml @@ -0,0 +1,8 @@ +categories as $cat) { + foreach ($cat->feeds() as $feed) { + $result[$feed->id()] = $feed->nbNotRead(); + } +} +echo json_encode($result); diff --git a/p/i/index.php b/p/i/index.php index 3dcf659c9..187bbabe8 100755 --- a/p/i/index.php +++ b/p/i/index.php @@ -26,6 +26,7 @@ if (file_exists ('install.php')) { session_cache_limiter(''); Minz_Session::init('FreshRSS'); + Minz_Session::_param('keepAlive', 1); //For Persona if (!file_exists(DATA_PATH . '/no-cache.txt')) { require(LIB_PATH . '/http-conditional.php'); diff --git a/p/scripts/main.js b/p/scripts/main.js index 8646d9b72..24fdfd3f3 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -25,6 +25,46 @@ function incLabel(p, inc) { return i > 0 ? ' (' + i + ')' : ''; } +function incUnreadsFeed(article, feed_id, nb) { + //Update unread: feed + var elem = $('#' + feed_id + '>.feed').get(0), + feed_unreads = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0, + feed_priority = elem ? (parseInt(elem.getAttribute('data-priority'), 10) || 0) : 0; + if (elem) { + elem.setAttribute('data-unread', Math.max(0, feed_unreads + nb)); + } + + //Update unread: category + elem = $('#' + feed_id).parent().prevAll('.category').children(':first').get(0); + feed_unreads = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0; + if (elem) { + elem.setAttribute('data-unread', Math.max(0, feed_unreads + nb)); + } + + //Update unread: all + if (feed_priority > 0) { + elem = $('#aside_flux .all').children(':first').get(0); + if (elem) { + feed_unreads = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0; + elem.setAttribute('data-unread', Math.max(0, feed_unreads + nb)); + } + } + + //Update unread: favourites + if (article && article.closest('div').hasClass('favorite')) { + elem = $('#aside_flux .favorites').children(':first').get(0); + if (elem) { + feed_unreads = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0; + elem.setAttribute('data-unread', Math.max(0, feed_unreads + nb)); + } + } + + //Update unread: title + document.title = document.title.replace(/((?: \(\d+\))?)( · .*?)((?: \(\d+\))?)$/, function (m, p1, p2, p3) { + return incLabel(p1, nb) + p2 + incLabel(p3, feed_priority > 0 ? nb : 0); + }); +} + function mark_read(active, only_not_read) { if (active[0] === undefined || (only_not_read === true && !active.hasClass("not_read"))) { return false; @@ -51,45 +91,9 @@ function mark_read(active, only_not_read) { } $r.find('.icon').replaceWith(data.icon); - //Update unread: feed var feed_url = active.find(".website>a").attr("href"), - feed_id = feed_url.substr(feed_url.lastIndexOf('f_')), - elem = $('#' + feed_id + ' .feed').get(0), - feed_unread = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0, - feed_priority = elem ? (parseInt(elem.getAttribute('data-priority'), 10) || 0) : 0; - if (elem) { - elem.setAttribute('data-unread', Math.max(0, feed_unread + inc)); - } - - //Update unread: category - elem = $('#' + feed_id).parent().prevAll('.category').children(':first').get(0); - feed_unread = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0; - if (elem) { - elem.setAttribute('data-unread', Math.max(0, feed_unread + inc)); - } - - //Update unread: all - if (feed_priority > 0) { - elem = $('#aside_flux .all').children(':first').get(0); - if (elem) { - feed_unread = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0; - elem.setAttribute('data-unread', Math.max(0, feed_unread + inc)); - } - } - - //Update unread: favourites - if (active.closest('div').hasClass('favorite')) { - elem = $('#aside_flux .favorites').children(':first').get(0); - if (elem) { - feed_unread = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0; - elem.setAttribute('data-unread', Math.max(0, feed_unread + inc)); - } - } - - //Update unread: title - document.title = document.title.replace(/((?: \(\d+\))?)( · .*?)((?: \(\d+\))?)$/, function (m, p1, p2, p3) { - return incLabel(p1, inc) + p2 + incLabel(p3, feed_priority > 0 ? inc : 0); - }); + feed_id = feed_url.substr(feed_url.lastIndexOf('f_')); + incUnreadsFeed(active, feed_id, inc); }); } @@ -128,8 +132,8 @@ function mark_favorite(active) { if (active.closest('div').hasClass('not_read')) { var elem = $('#aside_flux .favorites').children(':first').get(0), - feed_unread = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0; - elem.setAttribute('data-unread', Math.max(0, feed_unread + inc)); + feed_unreads = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0; + elem.setAttribute('data-unread', Math.max(0, feed_unreads + inc)); } }); } @@ -514,6 +518,17 @@ function init_notifications() { } } +function refreshUnreads() { + $.getJSON('./?c=javascript&a=nbUnreadsPerFeed').done(function (data) { + $.each(data, function(feed_id, nbUnreads) { + feed_id = 'f_' + feed_id; + var elem = $('#' + feed_id + '>.feed').get(0), + feed_unreads = elem ? (parseInt(elem.getAttribute('data-unread'), 10) || 0) : 0; + incUnreadsFeed(null, feed_id, nbUnreads - feed_unreads); + }); + }); +} + // var url_load_more = "", load_more = false, @@ -685,6 +700,7 @@ function init_all() { } init_confirm_action(); init_print_action(); + window.setInterval(refreshUnreads, 60000); if (window.console) { console.log('FreshRSS init done.'); }