mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
infinite-scrolling
This commit is contained in:
@@ -39,21 +39,39 @@ public class FeedEntryService extends GenericDAO<FeedEntry, Long> {
|
||||
em.merge(feed);
|
||||
}
|
||||
|
||||
public List<FeedEntry> getUnreadEntries(Feed feed, User user) {
|
||||
private TypedQuery<FeedEntry> unreadQuery(Feed feed, User user) {
|
||||
String query = "select e from FeedEntry e where e.feed=:feed and not exists (select s from FeedEntryStatus s where s.entry = e and s.user =:user and s.read = true)";
|
||||
TypedQuery<FeedEntry> typedQuery = em.createQuery(query,
|
||||
FeedEntry.class);
|
||||
typedQuery.setParameter("feed", feed);
|
||||
typedQuery.setParameter("user", user);
|
||||
return typedQuery.getResultList();
|
||||
return typedQuery;
|
||||
}
|
||||
|
||||
public List<FeedEntry> getAllEntries(Feed feed) {
|
||||
public List<FeedEntry> getUnreadEntries(Feed feed, User user) {
|
||||
return unreadQuery(feed, user).getResultList();
|
||||
}
|
||||
|
||||
public List<FeedEntry> getUnreadEntries(Feed feed, User user, int offset,
|
||||
int limit) {
|
||||
return unreadQuery(feed, user).setFirstResult(offset)
|
||||
.setMaxResults(limit).getResultList();
|
||||
}
|
||||
|
||||
private TypedQuery<FeedEntry> allQuery(Feed feed) {
|
||||
String query = "select e from FeedEntry e where e.feed=:feed";
|
||||
TypedQuery<FeedEntry> typedQuery = em.createQuery(query,
|
||||
FeedEntry.class);
|
||||
typedQuery.setParameter("feed", feed);
|
||||
return typedQuery.getResultList();
|
||||
return typedQuery;
|
||||
}
|
||||
|
||||
public List<FeedEntry> getAllEntries(Feed feed) {
|
||||
return allQuery(feed).getResultList();
|
||||
}
|
||||
|
||||
public List<FeedEntry> getAllEntries(Feed feed, int offset, int limit) {
|
||||
return allQuery(feed).setFirstResult(offset).setMaxResults(limit)
|
||||
.getResultList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,9 +50,8 @@ public class FeedTimer {
|
||||
feedEntryService
|
||||
.updateEntries(feed.getUrl(), feed.getEntries());
|
||||
} catch (Exception e) {
|
||||
log.info(
|
||||
"Unable to refresh feed " + key + " : "
|
||||
+ e.getMessage(), e);
|
||||
log.info("Unable to refresh feed " + key + " : "
|
||||
+ e.getMessage());
|
||||
|
||||
Feed feed = feeds.get(key);
|
||||
feed.setLastUpdated(Calendar.getInstance().getTime());
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
<script src="vendor/angular/angular-resource.min.js"></script>
|
||||
<script src="vendor/angular/angular-sanitize.min.js"></script>
|
||||
<script src="vendor/angular-upload/ng-upload.min.js"></script>
|
||||
<script src="vendor/angular-infinite-scroll/ng-infinite-scroll.min.js"></script>
|
||||
<script src="vendor/angular-ui/angular-ui.min.js"></script>
|
||||
<script src="vendor/angular-ui-bootstrap/ui-bootstrap-tpls-0.2.0.min.js"></script>
|
||||
<script src="js/main.js"></script>
|
||||
|
||||
@@ -5,9 +5,11 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.QueryParam;
|
||||
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
|
||||
@@ -27,7 +29,9 @@ public class EntriesREST extends AbstractREST {
|
||||
@Path("get/{type}/{id}/{readType}")
|
||||
@GET
|
||||
public Entries getEntries(@PathParam("type") String type,
|
||||
@PathParam("id") String id, @PathParam("readType") String readType) {
|
||||
@PathParam("id") String id, @PathParam("readType") String readType,
|
||||
@DefaultValue("0") @QueryParam("offset") int offset,
|
||||
@DefaultValue("-1") @QueryParam("limit") int limit) {
|
||||
|
||||
Entries entries = new Entries();
|
||||
boolean unreadOnly = "unread".equals(readType);
|
||||
@@ -36,7 +40,8 @@ public class EntriesREST extends AbstractREST {
|
||||
FeedSubscription subscription = feedSubscriptionService.findById(
|
||||
getUser(), Long.valueOf(id));
|
||||
entries.setName(subscription.getTitle());
|
||||
entries.getEntries().addAll(buildEntries(subscription, unreadOnly));
|
||||
entries.getEntries().addAll(
|
||||
buildEntries(subscription, offset, limit, unreadOnly));
|
||||
|
||||
} else {
|
||||
FeedCategory feedCategory = "all".equals(id) ? null
|
||||
@@ -48,7 +53,7 @@ public class EntriesREST extends AbstractREST {
|
||||
entries.setName("all".equals(id) ? "All" : feedCategory.getName());
|
||||
for (FeedSubscription subscription : subscriptions) {
|
||||
entries.getEntries().addAll(
|
||||
buildEntries(subscription, unreadOnly));
|
||||
buildEntries(subscription, offset, limit, unreadOnly));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,19 +64,27 @@ public class EntriesREST extends AbstractREST {
|
||||
return ObjectUtils.compare(e2.getDate(), e1.getDate());
|
||||
}
|
||||
});
|
||||
|
||||
int lastIndex = entries.getEntries().size()
|
||||
- (entries.getEntries().isEmpty() ? 0 : 1);
|
||||
int from = Math.min(lastIndex, offset);
|
||||
int to = limit == -1 ? lastIndex : Math.min(lastIndex, offset + limit);
|
||||
|
||||
List<Entry> subList = entries.getEntries().subList(from, to);
|
||||
entries.setEntries(Lists.newArrayList(subList));
|
||||
return entries;
|
||||
}
|
||||
|
||||
private List<Entry> buildEntries(FeedSubscription subscription,
|
||||
boolean unreadOnly) {
|
||||
private List<Entry> buildEntries(FeedSubscription subscription, int offset,
|
||||
int limit, boolean unreadOnly) {
|
||||
List<FeedEntry> feedEntries = null;
|
||||
|
||||
if (unreadOnly) {
|
||||
feedEntries = feedEntryService.getUnreadEntries(
|
||||
subscription.getFeed(), getUser());
|
||||
subscription.getFeed(), getUser(), offset, limit);
|
||||
} else {
|
||||
feedEntries = feedEntryService
|
||||
.getAllEntries(subscription.getFeed());
|
||||
feedEntries = feedEntryService.getAllEntries(
|
||||
subscription.getFeed(), offset, limit);
|
||||
}
|
||||
|
||||
List<Entry> entries = Lists.newArrayList();
|
||||
|
||||
@@ -102,15 +102,45 @@ module.controller('FeedListCtrl', function($scope, $routeParams, $http,
|
||||
$scope.refreshList();
|
||||
});
|
||||
|
||||
|
||||
$scope.offset = 0;
|
||||
$scope.limit = 10;
|
||||
$scope.busy = false;
|
||||
$scope.hasMore = true;
|
||||
|
||||
$scope.refreshList = function() {
|
||||
if ($scope.settings.readingMode) {
|
||||
$scope.entryList = EntryService.get({
|
||||
_type : $scope.selectedType,
|
||||
_id : $scope.selectedId,
|
||||
_readtype : $scope.settings.readingMode
|
||||
_readtype : $scope.settings.readingMode,
|
||||
offset : $scope.offset,
|
||||
limit : 30
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.loadMoreEntries = function() {
|
||||
if ($scope.busy || !$scope.hasMore)
|
||||
return;
|
||||
if (!$scope.settings.readingMode)
|
||||
return;
|
||||
$scope.busy = true;
|
||||
EntryService.get({
|
||||
_type : $scope.selectedType,
|
||||
_id : $scope.selectedId,
|
||||
_readtype : $scope.settings.readingMode,
|
||||
offset : $scope.offset,
|
||||
limit : $scope.limit
|
||||
}, function(data) {
|
||||
for ( var i = 0; i < data.entries.length; i++) {
|
||||
$scope.entryList.entries.push(data.entries[i]);
|
||||
}
|
||||
$scope.offset = $scope.offset + data.entries.length;
|
||||
$scope.busy = false;
|
||||
$scope.hasMore = data.entries.length == $scope.limit;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.mark = function(entry, read) {
|
||||
if (entry.read != read) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var app = angular.module('commafeed', [ 'ui', 'ui.bootstrap',
|
||||
'commafeed.directives', 'commafeed.controllers', 'commafeed.services',
|
||||
'ngSanitize', 'ngUpload' ]);
|
||||
'ngSanitize', 'ngUpload', 'infinite-scroll' ]);
|
||||
|
||||
app.config([ '$routeProvider', function($routeProvider) {
|
||||
$routeProvider.when('/feeds/view/:_type/:_id', {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{{readType}}
|
||||
<span>{{entryList.name}}</span><span
|
||||
ng-show="selectedType == 'category'"> »</span>
|
||||
<div class="accordion" id="feed-accordion">
|
||||
<div class="accordion" id="feed-accordion" infinite-scroll="loadMoreEntries()" infinite-scroll-disabled="busy" infinite-scroll-distance="1">
|
||||
<div class="accordion-group" ng-repeat="entry in entryList.entries">
|
||||
<div class="accordion-heading">
|
||||
<a class="accordion-toggle" data-toggle="collapse"
|
||||
@@ -17,5 +17,6 @@
|
||||
<div class="accordion-inner" ng-bind-html="entry.content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="busy">Loading data...</div>
|
||||
</div>
|
||||
</div>
|
||||
2
src/main/webapp/vendor/angular-infinite-scroll/ng-infinite-scroll.min.js
vendored
Normal file
2
src/main/webapp/vendor/angular-infinite-scroll/ng-infinite-scroll.min.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/* ng-infinite-scroll - v1.0.0 - 2013-02-23 */
|
||||
var mod;mod=angular.module("infinite-scroll",[]),mod.directive("infiniteScroll",["$rootScope","$window","$timeout",function(i,n,e){return{link:function(t,l,o){var r,c,f,a;return n=angular.element(n),f=0,null!=o.infiniteScrollDistance&&t.$watch(o.infiniteScrollDistance,function(i){return f=parseInt(i,10)}),a=!0,r=!1,null!=o.infiniteScrollDisabled&&t.$watch(o.infiniteScrollDisabled,function(i){return a=!i,a&&r?(r=!1,c()):void 0}),c=function(){var e,c,u,d;return d=n.height()+n.scrollTop(),e=l.offset().top+l.height(),c=e-d,u=n.height()*f>=c,u&&a?i.$$phase?t.$eval(o.infiniteScroll):t.$apply(o.infiniteScroll):u?r=!0:void 0},n.on("scroll",c),t.$on("$destroy",function(){return n.off("scroll",c)}),e(function(){return o.infiniteScrollImmediateCheck?t.$eval(o.infiniteScrollImmediateCheck)?c():void 0:c()},0)}}}]);
|
||||
Reference in New Issue
Block a user