First, remove old articles, then add new ones. Closes #4
This commit is contained in:
@@ -6,6 +6,8 @@ and this project does NOT adhere to [Semantic Versioning](https://semver.org/spe
|
|||||||
|
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Fixed
|
||||||
|
- Article order got mixed up for some feeds (issue: #4)
|
||||||
|
|
||||||
|
|
||||||
## [0.9.3] - 2019-03-14
|
## [0.9.3] - 2019-03-14
|
||||||
@@ -50,7 +52,7 @@ and this project does NOT adhere to [Semantic Versioning](https://semver.org/spe
|
|||||||
Initial release
|
Initial release
|
||||||
|
|
||||||
|
|
||||||
[Unreleased]: https://github.com/relikd/baRSS/compare/v0.9.2...HEAD
|
[Unreleased]: https://github.com/relikd/baRSS/compare/v0.9.3...HEAD
|
||||||
[0.9.3]: https://github.com/relikd/baRSS/compare/v0.9.2...v0.9.3
|
[0.9.3]: https://github.com/relikd/baRSS/compare/v0.9.2...v0.9.3
|
||||||
[0.9.2]: https://github.com/relikd/baRSS/compare/v0.9.1...v0.9.2
|
[0.9.2]: https://github.com/relikd/baRSS/compare/v0.9.1...v0.9.2
|
||||||
[0.9.1]: https://github.com/relikd/baRSS/compare/v0.9...v0.9.1
|
[0.9.1]: https://github.com/relikd/baRSS/compare/v0.9...v0.9.1
|
||||||
|
|||||||
@@ -92,9 +92,10 @@
|
|||||||
self.group.name = obj.title;
|
self.group.name = obj.title;
|
||||||
|
|
||||||
// Add and remove articles
|
// Add and remove articles
|
||||||
NSMutableSet<FeedArticle*> *oldSet = [self.articles mutableCopy];
|
NSMutableSet<FeedArticle*> *localSet = [self.articles mutableCopy];
|
||||||
NSInteger diff = [self addMissingArticles:obj withOldSet:oldSet]; // will remove items that should be kept
|
NSInteger diff = 0;
|
||||||
diff -= [self deleteArticlesWithOldSet:oldSet]; // remove old, outdated articles
|
diff -= [self deleteArticles:localSet withRemoteSet:obj.articles]; // remove old, outdated articles
|
||||||
|
diff += [self insertArticles:localSet withRemoteSet:obj.articles]; // insert new in correct order
|
||||||
// Get new total article count and post unread-count-change notification
|
// Get new total article count and post unread-count-change notification
|
||||||
if (flag && diff != 0) {
|
if (flag && diff != 0) {
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationTotalUnreadCountChanged object:@(diff)];
|
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationTotalUnreadCountChanged object:@(diff)];
|
||||||
@@ -108,20 +109,20 @@
|
|||||||
New articles should be in ascending order without any gaps in between.
|
New articles should be in ascending order without any gaps in between.
|
||||||
If new article is disjunct from the article before, assume a deleted article re-appeared and mark it as read.
|
If new article is disjunct from the article before, assume a deleted article re-appeared and mark it as read.
|
||||||
|
|
||||||
@param oldSet Input will be used to identify new articles.
|
@param localSet Use result set @c localSet of method call @c deleteArticles:withRemoteSet:.
|
||||||
Output contains articles that aren't present in the feed anymore and should be deleted.
|
@param remoteSet Readonly copy of @c RSParsedFeed.articles.
|
||||||
*/
|
*/
|
||||||
- (NSInteger)addMissingArticles:(RSParsedFeed*)obj withOldSet:(NSMutableSet<FeedArticle*>*)oldSet {
|
- (NSUInteger)insertArticles:(NSMutableSet<FeedArticle*>*)localSet withRemoteSet:(NSArray<RSParsedArticle*>*)remoteSet {
|
||||||
NSInteger newOnes = 0;
|
NSUInteger newOnes = 0;
|
||||||
int32_t currentIndex = [[self.articles valueForKeyPath:@"@min.sortIndex"] intValue];
|
int32_t currentIndex = [[localSet valueForKeyPath:@"@min.sortIndex"] intValue];
|
||||||
FeedArticle *lastInserted = nil;
|
FeedArticle *lastInserted = nil;
|
||||||
BOOL hasGapBetweenNewArticles = NO;
|
BOOL hasGapBetweenNewArticles = NO;
|
||||||
|
|
||||||
for (RSParsedArticle *article in [obj.articles reverseObjectEnumerator]) {
|
for (RSParsedArticle *article in [remoteSet reverseObjectEnumerator]) {
|
||||||
// reverse enumeration ensures correct article order
|
// reverse enumeration ensures correct article order
|
||||||
FeedArticle *storedArticle = [self findArticle:article inSet:oldSet];
|
FeedArticle *storedArticle = [self findRemoteArticle:article inLocalSet:localSet];
|
||||||
if (storedArticle) {
|
if (storedArticle) {
|
||||||
[oldSet removeObject:storedArticle];
|
[localSet removeObject:storedArticle];
|
||||||
if (storedArticle.sortIndex != currentIndex) {
|
if (storedArticle.sortIndex != currentIndex) {
|
||||||
storedArticle.sortIndex = currentIndex;
|
storedArticle.sortIndex = currentIndex;
|
||||||
}
|
}
|
||||||
@@ -147,19 +148,26 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Delete all articles from core data, that are still in the oldSet.
|
Delete all articles from core data, that aren't present anymore.
|
||||||
|
|
||||||
|
@param localSet Input a copy of @c self.articles. Output the same set minus deleted articles.
|
||||||
|
@param remoteSet Readonly copy of @c RSParsedFeed.articles.
|
||||||
*/
|
*/
|
||||||
- (NSUInteger)deleteArticlesWithOldSet:(NSMutableSet<FeedArticle*>*)oldSet {
|
- (NSUInteger)deleteArticles:(NSMutableSet<FeedArticle*>*)localSet withRemoteSet:(NSArray<RSParsedArticle*>*)remoteSet {
|
||||||
if (!oldSet || oldSet.count == 0)
|
|
||||||
return 0;
|
|
||||||
NSUInteger c = 0;
|
NSUInteger c = 0;
|
||||||
for (FeedArticle *fa in oldSet) {
|
NSMutableSet<FeedArticle*> *deletingSet = [NSMutableSet setWithCapacity:localSet.count];
|
||||||
if (fa.unread) ++c;
|
for (FeedArticle *fa in localSet) {
|
||||||
// TODO: keep unread articles?
|
if (![self findLocalArticle:fa inRemoteSet:remoteSet]) {
|
||||||
[self.managedObjectContext deleteObject:fa];
|
if (fa.unread) ++c;
|
||||||
|
// TODO: keep unread articles?
|
||||||
|
[self.managedObjectContext deleteObject:fa];
|
||||||
|
[deletingSet addObject:fa];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deletingSet.count > 0) {
|
||||||
|
[localSet minusSet:deletingSet];
|
||||||
|
[self removeArticles:deletingSet];
|
||||||
}
|
}
|
||||||
if (oldSet.count > 0)
|
|
||||||
[self removeArticles:oldSet];
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,17 +185,34 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Iterate over oldSet and return the one where @c link and @c guid matches. Or @c nil if no matching article found.
|
Iterate over localSet and return the one where @c link and @c guid matches. Or @c nil if no matching article found.
|
||||||
*/
|
*/
|
||||||
- (FeedArticle*)findArticle:(RSParsedArticle*)article inSet:(NSSet<FeedArticle*>*)oldSet {
|
- (FeedArticle*)findRemoteArticle:(RSParsedArticle*)remote inLocalSet:(NSSet<FeedArticle*>*)localSet {
|
||||||
NSString *searchLink = article.link;
|
NSString *searchLink = remote.link;
|
||||||
NSString *searchGuid = article.guid;
|
NSString *searchGuid = remote.guid;
|
||||||
BOOL linkIsNil = (searchLink == nil);
|
BOOL linkIsNil = (searchLink == nil);
|
||||||
BOOL guidIsNil = (searchGuid == nil);
|
BOOL guidIsNil = (searchGuid == nil);
|
||||||
for (FeedArticle *old in oldSet) {
|
for (FeedArticle *art in localSet) {
|
||||||
if ((linkIsNil && old.link == nil) || [old.link isEqualToString:searchLink]) {
|
if ((linkIsNil && art.link == nil) || [art.link isEqualToString:searchLink]) {
|
||||||
if ((guidIsNil && old.guid == nil) || [old.guid isEqualToString:searchGuid])
|
if ((guidIsNil && art.guid == nil) || [art.guid isEqualToString:searchGuid])
|
||||||
return old;
|
return art;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterate over remoteSet and return the one where @c link and @c guid matches. Or @c nil if no matching article found.
|
||||||
|
*/
|
||||||
|
- (RSParsedArticle*)findLocalArticle:(FeedArticle*)local inRemoteSet:(NSArray<RSParsedArticle*>*)remoteSet {
|
||||||
|
NSString *searchLink = local.link;
|
||||||
|
NSString *searchGuid = local.guid;
|
||||||
|
BOOL linkIsNil = (searchLink == nil);
|
||||||
|
BOOL guidIsNil = (searchGuid == nil);
|
||||||
|
for (RSParsedArticle *art in remoteSet) {
|
||||||
|
if ((linkIsNil && art.link == nil) || [art.link isEqualToString:searchLink]) {
|
||||||
|
if ((guidIsNil && art.guid == nil) || [art.guid isEqualToString:searchGuid])
|
||||||
|
return art;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1153</string>
|
<string>1172</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||||
<key>LSUIElement</key>
|
<key>LSUIElement</key>
|
||||||
|
|||||||
Reference in New Issue
Block a user