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.
This commit is contained in:
parent
74d8d361ee
commit
8422e62abc
5
assets/js/all.min.js
vendored
5
assets/js/all.min.js
vendored
@ -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()}}}();
|
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;d<e;d++){var c=a[d].getAttribute("data-feed-id");c&&b.push(parseInt(c))}}var b=[],d=[];return{Update:function(b,a){e(b);var d=new XMLHttpRequest;d.onload=function(){var c=document.getElementById("loading-feed-"+b);c&&(c.innerHTML="");if(c=document.getElementById("last-checked-feed-"+
|
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;d<e;d++){var c=a[d].getAttribute("data-feed-id");c&&b.push(parseInt(c))}}var b=[],d=[];return{Update:function(b,a){e(b);var d=new XMLHttpRequest;d.onload=function(){var c;try{c=JSON.parse(this.responseText)}catch(h){}var m="(0/0)";!1!==c.result&&
|
||||||
b))c.innerHTML=c.getAttribute("data-after-update");try{a&&a(JSON.parse(this.responseText))}catch(h){}};d.open("POST","?action=refresh-feed&feed_id="+b,!0);d.send()},UpdateAll:function(){a();var e=setInterval(function(){for(;0<b.length&&5>d.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)}}}();
|
(m="("+String(c.result.items_unread)+"/"+String(c.result.items_total)+")");var d=document.getElementById("loading-feed-"+b);d&&(d.innerHTML=m);if(d=document.getElementById("last-checked-feed-"+b))d.innerHTML=d.getAttribute("data-after-update");a&&a(c)};d.open("POST","?action=refresh-feed&feed_id="+b,!0);d.send()},UpdateAll:function(){a();var e=setInterval(function(){for(;0<b.length&&5>d.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");
|
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=
|
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=
|
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=
|
||||||
|
@ -15,6 +15,7 @@ Miniflux.Feed = (function() {
|
|||||||
var container = document.getElementById("loading-feed-" + feed_id);
|
var container = document.getElementById("loading-feed-" + feed_id);
|
||||||
|
|
||||||
if (container) {
|
if (container) {
|
||||||
|
container.innerHTML = "";
|
||||||
var img = document.createElement("img");
|
var img = document.createElement("img");
|
||||||
img.src = "assets/img/refresh.gif";
|
img.src = "assets/img/refresh.gif";
|
||||||
container.appendChild(img);
|
container.appendChild(img);
|
||||||
@ -22,10 +23,10 @@ Miniflux.Feed = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hide the refresh icon after update
|
// Hide the refresh icon after update
|
||||||
function hideRefreshIcon(feed_id)
|
function hideRefreshIcon(feed_id, replace_text)
|
||||||
{
|
{
|
||||||
var container = document.getElementById("loading-feed-" + feed_id);
|
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);
|
var container = document.getElementById("last-checked-feed-" + feed_id);
|
||||||
if (container) container.innerHTML = container.getAttribute("data-after-update");
|
if (container) container.innerHTML = container.getAttribute("data-after-update");
|
||||||
@ -51,14 +52,24 @@ Miniflux.Feed = (function() {
|
|||||||
|
|
||||||
request.onload = function() {
|
request.onload = function() {
|
||||||
|
|
||||||
hideRefreshIcon(feed_id);
|
var response;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (callback) {
|
response = JSON.parse(this.responseText);
|
||||||
callback(JSON.parse(this.responseText));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (e) {}
|
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);
|
request.open("POST", "?action=refresh-feed&feed_id=" + feed_id, true);
|
||||||
|
@ -194,7 +194,7 @@ Router\get_action('feeds', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Response\html(Template\layout('feeds', array(
|
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'),
|
'nothing_to_read' => Request\int_param('nothing_to_read'),
|
||||||
'menu' => 'feeds',
|
'menu' => 'feeds',
|
||||||
'title' => t('Subscriptions')
|
'title' => t('Subscriptions')
|
||||||
|
@ -161,7 +161,7 @@ function refresh($feed_id)
|
|||||||
if (! $resource->isModified()) {
|
if (! $resource->isModified()) {
|
||||||
update_parsing_error($feed_id, 0);
|
update_parsing_error($feed_id, 0);
|
||||||
\Model\Config\write_debug();
|
\Model\Config\write_debug();
|
||||||
return true;
|
return get_feed_unread_counts($feed_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$parser = $reader->getParser();
|
$parser = $reader->getParser();
|
||||||
@ -190,7 +190,7 @@ function refresh($feed_id)
|
|||||||
\Model\Item\update_all($feed_id, $result->items, $parser->grabber);
|
\Model\Item\update_all($feed_id, $result->items, $parser->grabber);
|
||||||
\Model\Config\write_debug();
|
\Model\Config\write_debug();
|
||||||
|
|
||||||
return true;
|
return get_feed_unread_counts($feed_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +244,58 @@ function get_all()
|
|||||||
->findAll();
|
->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
|
// Get one feed
|
||||||
function get($feed_id)
|
function get($feed_id)
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
<?php if (! $feed['enabled']): ?>
|
<?php if (! $feed['enabled']): ?>
|
||||||
<span title="<?= t('Subscription disabled') ?>">✖</a>
|
<span title="<?= t('Subscription disabled') ?>">✖</a>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<span id="loading-feed-<?= $feed['id'] ?>"></span>
|
<span id="loading-feed-<?= $feed['id'] ?>">(<?= $feed['items_unread'] .'/' . $feed['items_total'] ?>)</span>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<a href="?action=feed-items&feed_id=<?= $feed['id'] ?>" title="<?= t('Show only this subscription') ?>"><?= Helper\escape($feed['title']) ?></a>
|
<a href="?action=feed-items&feed_id=<?= $feed['id'] ?>" title="<?= t('Show only this subscription') ?>"><?= Helper\escape($feed['title']) ?></a>
|
||||||
|
Loading…
Reference in New Issue
Block a user