From 8422e62abc749ddefff0ac55eef29188fa49ea05 Mon Sep 17 00:00:00 2001 From: Philip Walden Date: Sat, 22 Feb 2014 11:00:49 -0800 Subject: [PATCH] Fulfills enhnacement request fguillot/miniflux #155 Inserts a (unread/total)" items count in front of each subcription on the feeds page. models/feed.php adds two functions: get_feed_unread_counts(), get_all_w_counts(). get_feed_unread_counts - returns either an array of (unread/total) counts indexed by feed id or a singl (unread/total) for a specific id. get_all_w_counts() returns the same as get_all() but appends items_unread and items_total columns. controller/feed.php modifies Router\post_action('refresh-feed',function() to retrun the (unread/total) count in the retruned ajax json array. Router\get_action('feeds',function() was modified to call get_all_w_counts(). templates/feeds.php was modified to insert the (unread/total) count into the span id="loading-feed-" such that is can be updated after a refresh. assets/js/feed.js was modified to to have the Update and hideRefreshIcon update the returned (unread/total) amounts in the "loading-feed" span. --- assets/js/all.min.js | 5 ++-- assets/js/feed.js | 23 ++++++++++++----- controllers/feed.php | 2 +- models/feed.php | 60 +++++++++++++++++++++++++++++++++++++++++--- templates/feeds.php | 2 +- 5 files changed, 78 insertions(+), 14 deletions(-) diff --git a/assets/js/all.min.js b/assets/js/all.min.js index b80cc5f..da80452 100644 --- a/assets/js/all.min.js +++ b/assets/js/all.min.js @@ -1,6 +1,7 @@ var Miniflux={};Miniflux.App=function(){return{Run:function(){Miniflux.Event.ListenKeyboardEvents();Miniflux.Event.ListenMouseEvents()},MozillaAuth:function(e){navigator.id.watch({onlogin:function(a){var b=new XMLHttpRequest;b.open("POST","?action="+e+"&token="+a,!0);b.setRequestHeader("Connection","close");b.onload=function(){window.location.href=this.responseText};b.send("token="+a)},onlogout:function(){}});navigator.id.request()}}}(); -Miniflux.Feed=function(){function e(b){if(b=document.getElementById("loading-feed-"+b)){var a=document.createElement("img");a.src="assets/img/refresh.gif";b.appendChild(a)}}function a(){for(var a=document.getElementsByTagName("a"),d=0,e=a.length;dd.length;){var a=b.shift();d.push(a);Miniflux.Feed.Update(a,function(a){a=d.indexOf(a.feed_id);0<=a&&d.splice(a,1);0==b.length&&0==d.length&&(clearInterval(e),window.location.href="?action=unread")})}},100)}}}(); +Miniflux.Feed=function(){function e(b){if(b=document.getElementById("loading-feed-"+b)){b.innerHTML="";var a=document.createElement("img");a.src="assets/img/refresh.gif";b.appendChild(a)}}function a(){for(var a=document.getElementsByTagName("a"),d=0,e=a.length;dd.length;){var a=b.shift();d.push(a);Miniflux.Feed.Update(a,function(a){a=d.indexOf(a.feed_id);0<=a&&d.splice(a,1); +0==b.length&&0==d.length&&(clearInterval(e),window.location.href="?action=unread")})}},100)}}}(); Miniflux.Item=function(){function e(c){var b=document.getElementById("item-"+c);b||(b=document.getElementById("current-item"),b.getAttribute("data-item-id")!=c&&(b=!1));return b}function a(c){if((c=document.getElementById("bookmark-"+c))&&c.getAttribute("data-reverse-label")){var b=c.innerHTML;c.innerHTML=c.getAttribute("data-reverse-label");c.setAttribute("data-reverse-label",b)}}function b(c){if(c=document.getElementById("status-"+c)){var b=c.innerHTML;c.innerHTML=c.getAttribute("data-reverse-label"); c.setAttribute("data-reverse-label",b)}}function d(c){"mouse"!=Miniflux.Event.lastEventType&&Miniflux.Nav.SelectNextItem();c.parentNode.removeChild(c);if(c=document.getElementById("page-counter"))counter=parseInt(c.textContent.trim(),10)-1,0==counter?window.location="?action=unread":(c.textContent=counter+" ",document.title="miniflux ("+counter+")",document.getElementById("nav-counter").textContent="("+counter+")")}function f(c){var a=new XMLHttpRequest;a.onload=function(){if(Miniflux.Nav.IsListing()){var a= e(c);if(a)if(a.getAttribute("data-hide"))d(a);else{a.setAttribute("data-item-status","read");b(c);if(a=document.getElementById("show-"+c)){a.className="read";var h=document.createElement("span");h.id="read-icon-"+c;h.appendChild(document.createTextNode("\u2611 "));a.parentNode.insertBefore(h,a)}(a=document.getElementById("status-"+c))&&a.setAttribute("data-action","mark-unread")}}};a.open("POST","?action=mark-item-read&id="+c,!0);a.send()}function k(c){var a=new XMLHttpRequest;a.onload=function(){if(Miniflux.Nav.IsListing()){var a= diff --git a/assets/js/feed.js b/assets/js/feed.js index 3be193e..a228ce3 100644 --- a/assets/js/feed.js +++ b/assets/js/feed.js @@ -15,6 +15,7 @@ Miniflux.Feed = (function() { var container = document.getElementById("loading-feed-" + feed_id); if (container) { + container.innerHTML = ""; var img = document.createElement("img"); img.src = "assets/img/refresh.gif"; container.appendChild(img); @@ -22,10 +23,10 @@ Miniflux.Feed = (function() { } // Hide the refresh icon after update - function hideRefreshIcon(feed_id) + function hideRefreshIcon(feed_id, replace_text) { var container = document.getElementById("loading-feed-" + feed_id); - if (container) container.innerHTML = ""; + if (container) container.innerHTML = replace_text; var container = document.getElementById("last-checked-feed-" + feed_id); if (container) container.innerHTML = container.getAttribute("data-after-update"); @@ -51,14 +52,24 @@ Miniflux.Feed = (function() { request.onload = function() { - hideRefreshIcon(feed_id); + var response; try { - if (callback) { - callback(JSON.parse(this.responseText)); - } + response = JSON.parse(this.responseText); } catch (e) {} + + var unread_ratio = String("(0/0)"); + if (response.result !== false) { + unread_ratio = "(" + String(response.result.items_unread) + "/" + String(response.result.items_total) + ")"; + // document.getElementById("xmlhttpresp").innerHTML=this.responseText + " " + unread_ratio; + } + + hideRefreshIcon(feed_id, unread_ratio); + + if (callback) { + callback(response); + } }; request.open("POST", "?action=refresh-feed&feed_id=" + feed_id, true); diff --git a/controllers/feed.php b/controllers/feed.php index 5d1955f..a2099f4 100644 --- a/controllers/feed.php +++ b/controllers/feed.php @@ -194,7 +194,7 @@ Router\get_action('feeds', function() { } Response\html(Template\layout('feeds', array( - 'feeds' => Model\Feed\get_all(), + 'feeds' => Model\Feed\get_all_w_counts(), 'nothing_to_read' => Request\int_param('nothing_to_read'), 'menu' => 'feeds', 'title' => t('Subscriptions') diff --git a/models/feed.php b/models/feed.php index 10ca05b..ae48475 100644 --- a/models/feed.php +++ b/models/feed.php @@ -157,11 +157,11 @@ function refresh($feed_id) // Update the `last_checked` column each time, HTTP cache or not update_last_checked($feed_id); - + if (! $resource->isModified()) { update_parsing_error($feed_id, 0); \Model\Config\write_debug(); - return true; + return get_feed_unread_counts($feed_id); } $parser = $reader->getParser(); @@ -182,7 +182,7 @@ function refresh($feed_id) } $result = $parser->execute(); - + if ($result !== false) { update_parsing_error($feed_id, 0); @@ -190,7 +190,7 @@ function refresh($feed_id) \Model\Item\update_all($feed_id, $result->items, $parser->grabber); \Model\Config\write_debug(); - return true; + return get_feed_unread_counts($feed_id); } } @@ -244,6 +244,58 @@ function get_all() ->findAll(); } +// Returns item unread and total counts, indexed by feed_id +// setting $feed_id returns counts for just that feed +function get_feed_unread_counts($feed_id = 0) +{ + $query = Database::get('db') + ->table('items') + ->columns('feed_id', 'status', 'count(status) AS item_count') + ->in('status', array('read', 'unread')) + ->groupBy('feed_id', 'status'); + if ($feed_id) $query->eq('feed_id', $feed_id); + $rq = $query->findAll(); + + $itemcnts = array(); + foreach($rq as $rec) { + if (!array_key_exists($rec['feed_id'], $itemcnts)) + $itemcnts[$rec['feed_id']] = array('items_unread' => 0, 'items_total' => 0); + if ($rec['status'] == 'unread') + $itemcnts[$rec['feed_id']]['items_unread'] = $rec['item_count']; + $itemcnts[$rec['feed_id']]['items_total'] += $rec['item_count']; + } + if ($feed_id) + // return the counts for the singe feed requested + if(! array_key_exists($feed_id, $itemcnts)) + return array('items_unread' => 0, 'items_total' => 0); + else + return $itemcnts[$feed_id]; + else + // return the counts for all feeds + return $itemcnts; +} + +// Get all feeds with counts of items_unread and items_total for each feed +function get_all_w_counts() +{ + // get unread and total item counts by feed id + $cnts = get_feed_unread_counts(); + // get all feeds + $rq = get_all(); + // for loop re-processes return array by appending items_unread and items_total fields + foreach ($rq as $rec_no => $rec) { + // determine if there are item counts for this feed + if (array_key_exists($rec['id'], $cnts)) { + // yes, append unread and total counts to the feed record + $rq[$rec_no] = array_merge($rec, $cnts[$rec['id']]); + } else { + // no this is an empty feed, so append unread and total counts = 0 + $rq[$rec_no] = array_merge($rec, array('items_unread' => 0, 'items_total' => 0)); + } + } + return $rq; +} + // Get one feed function get($feed_id) { diff --git a/templates/feeds.php b/templates/feeds.php index ece49b5..02a33df 100644 --- a/templates/feeds.php +++ b/templates/feeds.php @@ -25,7 +25,7 @@ - + ()