summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controller/itemcontroller.php10
-rw-r--r--css/feeds.css2
-rw-r--r--db/itemmapper.php6
-rw-r--r--js/app/app.coffee4
-rw-r--r--js/app/controllers/itemcontroller.coffee10
-rw-r--r--js/app/directives/newsitemscroll.coffee8
-rw-r--r--js/app/services/businesslayer/itembusinesslayer.coffee7
-rw-r--r--js/app/services/models/itemmodel.coffee11
-rw-r--r--js/public/app.js45
-rw-r--r--js/tests/services/businesslayer/itembusinesslayerSpec.coffee15
-rw-r--r--js/tests/services/models/itemmodelSpec.coffee9
-rw-r--r--templates/part.feed.unread.php3
-rw-r--r--templates/part.listfeed.php2
-rw-r--r--templates/part.listfolder.php3
-rw-r--r--tests/unit/controller/ItemControllerTest.php5
-rw-r--r--tests/unit/db/ItemMapperTest.php6
16 files changed, 116 insertions, 30 deletions
diff --git a/controller/itemcontroller.php b/controller/itemcontroller.php
index cfdfc4156..5387f40a2 100644
--- a/controller/itemcontroller.php
+++ b/controller/itemcontroller.php
@@ -50,7 +50,7 @@ class ItemController extends Controller {
*/
public function items(){
$userId = $this->api->getUserId();
- $showAll = $this->api->getUserValue($userId, 'showAll') === 'true';
+ $showAll = $this->api->getUserValue('showAll') === '1';
$limit = $this->params('limit');
$type = (int) $this->params('type');
@@ -61,12 +61,12 @@ class ItemController extends Controller {
if($limit !== null){
$offset = (int) $this->params('offset', 0);
- $items = $this->itemBusinessLayer->findAll($id, $type, (int) $limit, $offset,
- $showAll, $userId);
+ $items = $this->itemBusinessLayer->findAll($id, $type, (int) $limit,
+ $offset, $showAll, $userId);
} else {
$updatedSince = (int) $this->params('updatedSince');
- $items = $this->itemBusinessLayer->findAllNew($id, $type, $updatedSince,
- $showAll, $userId);
+ $items = $this->itemBusinessLayer->findAllNew($id, $type,
+ $updatedSince, $showAll, $userId);
}
$params = array(
diff --git a/css/feeds.css b/css/feeds.css
index 441b77720..13da15bf8 100644
--- a/css/feeds.css
+++ b/css/feeds.css
@@ -28,7 +28,7 @@
background-image: url('%appswebroot%/news/img/rss.svg');
}
-.unread {
+.unread > a {
font-weight: bold;
}
diff --git a/db/itemmapper.php b/db/itemmapper.php
index 077614695..bffab6348 100644
--- a/db/itemmapper.php
+++ b/db/itemmapper.php
@@ -158,7 +158,7 @@ class ItemMapper extends Mapper implements IMapper {
$params = array($userId, $id);
$sql = 'AND `items`.`feed_id` = ? ';
if($offset !== 0){
- $sql .= 'AND `items`.`id` > ? ';
+ $sql .= 'AND `items`.`id` < ? ';
array_push($params, $offset);
}
$sql .= 'ORDER BY `items`.`id` DESC ';
@@ -171,7 +171,7 @@ class ItemMapper extends Mapper implements IMapper {
$params = array($userId, $id);
$sql = 'AND `feeds`.`folder_id` = ? ';
if($offset !== 0){
- $sql .= 'AND `items`.`id` > ? ';
+ $sql .= 'AND `items`.`id` < ? ';
array_push($params, $offset);
}
$sql .= 'ORDER BY `items`.`id` DESC ';
@@ -184,7 +184,7 @@ class ItemMapper extends Mapper implements IMapper {
$params = array($userId);
$sql = '';
if($offset !== 0){
- $sql .= 'AND `items`.`id` > ? ';
+ $sql .= 'AND `items`.`id` < ? ';
array_push($params, $offset);
}
$sql .= 'ORDER BY `items`.`id` DESC ';
diff --git a/js/app/app.coffee b/js/app/app.coffee
index 2042a9ebf..264078b57 100644
--- a/js/app/app.coffee
+++ b/js/app/app.coffee
@@ -28,6 +28,10 @@ angular.module('News', ['OC', 'ui']).config ($provide) ->
scrollTimeout: 500
feedUpdateInterval: 600000
itemBatchSize: 20
+ # the autoPageFactor defines how many heights of the box must be left
+ # before it starts autopaging e.g. if it was 2, then it will start
+ # to fetch new items if less than the height*2 px is left to scroll
+ autoPageFactor: 6
angular.module('News').run ['Persistence', 'Config', 'FeedBusinessLayer',
diff --git a/js/app/controllers/itemcontroller.coffee b/js/app/controllers/itemcontroller.coffee
index 4fd00ec59..0d912b507 100644
--- a/js/app/controllers/itemcontroller.coffee
+++ b/js/app/controllers/itemcontroller.coffee
@@ -31,6 +31,8 @@ Language) ->
constructor: (@_$scope, @_itemBusinessLayer, @_feedModel, @_feedLoading,
@_feedBusinessLayer, @_language) ->
+ @_autoPaging = true
+
@_$scope.itemBusinessLayer = @_itemBusinessLayer
@_$scope.feedBusinessLayer = @_feedBusinessLayer
@@ -54,10 +56,14 @@ Language) ->
@_$scope.$on 'readItem', (scope, data) =>
- console.log data
@_itemBusinessLayer.setRead(data)
-
+ @_$scope.$on 'autoPage', =>
+ if @_autoPaging
+ # prevent multiple autopaging requests
+ @_autoPaging = false
+ @_itemBusinessLayer.loadNext =>
+ @_autoPaging = true
return new ItemController($scope, ItemBusinessLayer, FeedModel, FeedLoading,
diff --git a/js/app/directives/newsitemscroll.coffee b/js/app/directives/newsitemscroll.coffee
index 5e7e42a3e..619710bf3 100644
--- a/js/app/directives/newsitemscroll.coffee
+++ b/js/app/directives/newsitemscroll.coffee
@@ -49,14 +49,18 @@ angular.module('News').directive 'newsItemScroll', ['$rootScope', 'Config',
offset = $(feedItem).position().top
if offset <= -50
id = parseInt($(feedItem).data('id'), 10)
- #$rootScope.$broadcast 'readItem', id
+ $rootScope.$broadcast 'readItem', id
else
break
, Config.MarkReadTimeout
- scope.$apply attr.newsItemScroll
+ # autopaging
+ tolerance = elm.height() * Config.autoPageFactor
+ remaining = elm[0].scrollHeight - elm.scrollTop() - tolerance
+ if remaining <= 0
+ $rootScope.$broadcast 'autoPage'
]
diff --git a/js/app/services/businesslayer/itembusinesslayer.coffee b/js/app/services/businesslayer/itembusinesslayer.coffee
index b93f9035d..0b79cd638 100644
--- a/js/app/services/businesslayer/itembusinesslayer.coffee
+++ b/js/app/services/businesslayer/itembusinesslayer.coffee
@@ -105,7 +105,12 @@ StarredBusinessLayer) ->
return feed.title
- loadNext: ->
+ loadNext: (callback) ->
+ lowestItemId = @_itemModel.getLowestId()
+ if angular.isDefined(lowestItemId)
+ @_persistence.getItems @_activeFeed.getType(),
+ @_activeFeed.getId(), lowestItemId,
+ callback
diff --git a/js/app/services/models/itemmodel.coffee b/js/app/services/models/itemmodel.coffee
index 70b3a9f5c..1b03d65f8 100644
--- a/js/app/services/models/itemmodel.coffee
+++ b/js/app/services/models/itemmodel.coffee
@@ -109,5 +109,16 @@ angular.module('News').factory 'ItemModel',
return 0
+ getLowestId: ->
+ query = new _MinimumQuery('id')
+ lowestId = @get(query)
+
+ if angular.isDefined(lowestId)
+ return lowestId.id
+ else
+ return 0
+
+
+
return new ItemModel()
] \ No newline at end of file
diff --git a/js/public/app.js b/js/public/app.js
index ab3c73783..406007894 100644
--- a/js/public/app.js
+++ b/js/public/app.js
@@ -42,7 +42,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
markReadTimeout: 500,
scrollTimeout: 500,
feedUpdateInterval: 600000,
- itemBatchSize: 20
+ itemBatchSize: 20,
+ autoPageFactor: 6
});
});
@@ -247,6 +248,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
'$rootScope', 'Config', function($rootScope, Config) {
return function(scope, elm, attr) {
return elm.bind('scroll', function() {
+ var remaining, tolerance;
+
if (scrolling) {
scrolling = false;
setTimeout(function() {
@@ -264,7 +267,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
feedItem = $elems[_i];
offset = $(feedItem).position().top;
if (offset <= -50) {
- _results.push(id = parseInt($(feedItem).data('id'), 10));
+ id = parseInt($(feedItem).data('id'), 10);
+ _results.push($rootScope.$broadcast('readItem', id));
} else {
break;
}
@@ -272,7 +276,11 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
return _results;
}, Config.MarkReadTimeout);
}
- return scope.$apply(attr.newsItemScroll);
+ tolerance = elm.height() * Config.autoPageFactor;
+ remaining = elm[0].scrollHeight - elm.scrollTop() - tolerance;
+ if (remaining <= 0) {
+ return $rootScope.$broadcast('autoPage');
+ }
}
});
};
@@ -444,6 +452,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
this._feedLoading = _feedLoading;
this._feedBusinessLayer = _feedBusinessLayer;
this._language = _language;
+ this._autoPaging = true;
this._$scope.itemBusinessLayer = this._itemBusinessLayer;
this._$scope.feedBusinessLayer = this._feedBusinessLayer;
this._$scope.isLoading = function() {
@@ -467,9 +476,16 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
}
};
this._$scope.$on('readItem', function(scope, data) {
- console.log(data);
return _this._itemBusinessLayer.setRead(data);
});
+ this._$scope.$on('autoPage', function() {
+ if (_this._autoPaging) {
+ _this._autoPaging = false;
+ return _this._itemBusinessLayer.loadNext(function() {
+ return _this._autoPaging = true;
+ });
+ }
+ });
}
return ItemController;
@@ -1223,7 +1239,14 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
}
};
- ItemBusinessLayer.prototype.loadNext = function() {};
+ ItemBusinessLayer.prototype.loadNext = function(callback) {
+ var lowestItemId;
+
+ lowestItemId = this._itemModel.getLowestId();
+ if (angular.isDefined(lowestItemId)) {
+ return this._persistence.getItems(this._activeFeed.getType(), this._activeFeed.getId(), lowestItemId, callback);
+ }
+ };
ItemBusinessLayer.prototype.loadNew = function() {};
@@ -2015,6 +2038,18 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
}
};
+ ItemModel.prototype.getLowestId = function() {
+ var lowestId, query;
+
+ query = new _MinimumQuery('id');
+ lowestId = this.get(query);
+ if (angular.isDefined(lowestId)) {
+ return lowestId.id;
+ } else {
+ return 0;
+ }
+ };
+
return ItemModel;
})(_Model);
diff --git a/js/tests/services/businesslayer/itembusinesslayerSpec.coffee b/js/tests/services/businesslayer/itembusinesslayerSpec.coffee
index d5333c1f4..5f4744ffa 100644
--- a/js/tests/services/businesslayer/itembusinesslayerSpec.coffee
+++ b/js/tests/services/businesslayer/itembusinesslayerSpec.coffee
@@ -35,9 +35,9 @@ describe 'ItemBusinessLayer', ->
@FeedType, @FeedModel, @StarredBusinessLayer) =>
@item1 = {id: 5, title: 'hi', unreadCount:134, urlHash: 'a3', folderId: 3}
@FeedModel.add(@item1)
+ @ActiveFeed.handle({type: @FeedType.Feed, id: 3})
-
it 'should return all items', =>
item1 = {id: 6, feedId: 5, guidHash: 'a1'}
item2 = {id: 3, feedId: 5, guidHash: 'a2'}
@@ -233,3 +233,16 @@ describe 'ItemBusinessLayer', ->
expect(@item1.unreadCount).toBe(135)
+ it 'should load the next items', =>
+ @persistence.getItems = jasmine.createSpy('autopage')
+ callback = ->
+
+ @ItemModel.add({id: 2, guidHash: 'abc', feedId: 2, status: 16})
+ @ItemModel.add({id: 3, guidHash: 'abcd', feedId: 2, status: 16})
+ @ItemModel.add({id: 1, guidHash: 'abce', feedId: 2, status: 16})
+ @ItemModel.add({id: 6, guidHash: 'abcf', feedId: 2, status: 16})
+
+ @ItemBusinessLayer.loadNext(callback)
+
+ expect(@persistence.getItems).toHaveBeenCalledWith(
+ @FeedType.Feed, 3, 1, jasmine.any(Function))
diff --git a/js/tests/services/models/itemmodelSpec.coffee b/js/tests/services/models/itemmodelSpec.coffee
index ef6b535c4..4e93609ea 100644
--- a/js/tests/services/models/itemmodelSpec.coffee
+++ b/js/tests/services/models/itemmodelSpec.coffee
@@ -103,4 +103,11 @@ describe 'ItemModel', ->
expect(@ItemModel.getById(3).isStarred()).toBe(false)
- \ No newline at end of file
+
+ it 'should return the lowest id', =>
+ @ItemModel.add({id: 2, guidHash: 'abc', feedId: 2, status: 16})
+ @ItemModel.add({id: 3, guidHash: 'abcd', feedId: 2, status: 16})
+ @ItemModel.add({id: 1, guidHash: 'abce', feedId: 2, status: 16})
+ @ItemModel.add({id: 6, guidHash: 'abcf', feedId: 2, status: 16})
+
+ expect(@ItemModel.getLowestId()).toBe(1) \ No newline at end of file
diff --git a/templates/part.feed.unread.php b/templates/part.feed.unread.php
index 03ec2754d..0c6527af3 100644
--- a/templates/part.feed.unread.php
+++ b/templates/part.feed.unread.php
@@ -16,7 +16,8 @@
<?php p($l->t('All articles'))?>
</a>
<span class="utils">
- <span class="unread-counter">
+ <span class="unread-counter"
+ ng-show="subscriptionsBusinessLayer.getUnreadCount() > 0">
{{ subscriptionsBusinessLayer.getUnreadCount() }}
</span>
<button class="svg action mark-read-icon"
diff --git a/templates/part.listfeed.php b/templates/part.listfeed.php
index 6ab8751ad..1a56febf2 100644
--- a/templates/part.listfeed.php
+++ b/templates/part.listfeed.php
@@ -29,7 +29,7 @@
<span class="utils">
<span class="unread-counter"
- ng-show="feed.id">
+ ng-show="feed.id && feedBusinessLayer.getUnreadCount(feed.id) > 0">
{{ feedBusinessLayer.getUnreadCount(feed.id) }}
</span>
diff --git a/templates/part.listfolder.php b/templates/part.listfolder.php
index 63752521d..4266b4814 100644
--- a/templates/part.listfolder.php
+++ b/templates/part.listfolder.php
@@ -30,7 +30,8 @@
class="svg action delete-icon"
title="<?php p($l->t('Delete folder')); ?>"></button>
- <span class="unread-counter">
+ <span class="unread-counter"
+ ng-show="folderBusinessLayer.getUnreadCount(folder.id) > 0">
{{ folderBusinessLayer.getUnreadCount(folder.id) }}
</span>
diff --git a/tests/unit/controller/ItemControllerTest.php b/tests/unit/controller/ItemControllerTest.php
index ca72ee330..953330855 100644
--- a/tests/unit/controller/ItemControllerTest.php
+++ b/tests/unit/controller/ItemControllerTest.php
@@ -232,9 +232,8 @@ class ItemControllerTest extends ControllerTestUtility {
private function itemsApiExpects($id, $type){
$this->api->expects($this->once())
->method('getUserValue')
- ->with($this->equalTo($this->user),
- $this->equalTo('showAll'))
- ->will($this->returnValue('true'));
+ ->with($this->equalTo('showAll'))
+ ->will($this->returnValue('1'));
$this->api->expects($this->once())
->method('getUserId')
->will($this->returnValue($this->user));
diff --git a/tests/unit/db/ItemMapperTest.php b/tests/unit/db/ItemMapperTest.php
index 56cfe62ab..a7fead8f0 100644
--- a/tests/unit/db/ItemMapperTest.php
+++ b/tests/unit/db/ItemMapperTest.php
@@ -175,7 +175,7 @@ class ItemMapperTest extends \OCA\AppFramework\Utility\MapperTestUtility {
public function testFindAllFeed(){
$sql = 'AND `items`.`feed_id` = ? ' .
- 'AND `items`.`id` > ? ' .
+ 'AND `items`.`id` < ? ' .
'ORDER BY `items`.`id` DESC ';
$sql = $this->makeSelectQueryStatus($sql, $this->status);
$params = array($this->user, $this->id, $this->offset);
@@ -202,7 +202,7 @@ class ItemMapperTest extends \OCA\AppFramework\Utility\MapperTestUtility {
public function testFindAllFolder(){
$sql = 'AND `feeds`.`folder_id` = ? ' .
- 'AND `items`.`id` > ? ' .
+ 'AND `items`.`id` < ? ' .
'ORDER BY `items`.`id` DESC ';
$sql = $this->makeSelectQueryStatus($sql, $this->status);
$params = array($this->user, $this->id,
@@ -229,7 +229,7 @@ class ItemMapperTest extends \OCA\AppFramework\Utility\MapperTestUtility {
public function testFindAll(){
- $sql = 'AND `items`.`id` > ? ' .
+ $sql = 'AND `items`.`id` < ? ' .
'ORDER BY `items`.`id` DESC ';
$sql = $this->makeSelectQueryStatus($sql, $this->status);
$params = array($this->user, $this->offset);