From 6192f76605ba130d2ba9ae1012dbaf0b7b91088f Mon Sep 17 00:00:00 2001 From: relikd Date: Fri, 15 Mar 2019 00:09:00 +0100 Subject: [PATCH] Fix update for feeds where all articles have the same URL. Closes #3 --- CHANGELOG.md | 8 ++++- baRSS/Core Data/Feed+Ext.m | 60 +++++++++++++++++++------------------- baRSS/Info.plist | 4 +-- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3236d47..bf481b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,16 +6,21 @@ and this project does NOT adhere to [Semantic Versioning](https://semver.org/spe ## [Unreleased] + + +## [0.9.3] - 2019-03-14 ### Added - Changelog +- UI: Show body tag in article tooltip if abstract tag is empty ### Fixed - 'Update all feeds' will shows unread items count properly during update +- Fixed update for feeds where all article URLs point to the same resource (issue: #3) ## [0.9.2] - 2019-03-07 ### Added -- Limit number of articles that are displayed in feed menu +- Limit number of articles that are displayed in feed menu (issue: #2) ### Fixed - Cmd+Q in preferences will close the window instead of quitting the application @@ -46,6 +51,7 @@ Initial release [Unreleased]: https://github.com/relikd/baRSS/compare/v0.9.2...HEAD +[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.1]: https://github.com/relikd/baRSS/compare/v0.9...v0.9.1 [0.9]: https://github.com/relikd/baRSS/compare/e1f36514a8aa2d5fb9a575b6eb19adc2ce4a04d9...v0.9 diff --git a/baRSS/Core Data/Feed+Ext.m b/baRSS/Core Data/Feed+Ext.m index 24f7df7..3f41c09 100644 --- a/baRSS/Core Data/Feed+Ext.m +++ b/baRSS/Core Data/Feed+Ext.m @@ -92,9 +92,9 @@ self.group.name = obj.title; // Add and remove articles - NSMutableSet *urls = [[self.articles valueForKeyPath:@"link"] mutableCopy]; - NSInteger diff = [self addMissingArticles:obj updateLinks:urls]; // will remove links in 'urls' that should be kept - diff -= [self deleteArticlesWithLink:urls]; // remove old, outdated articles + NSMutableSet *oldSet = [self.articles mutableCopy]; + NSInteger diff = [self addMissingArticles:obj withOldSet:oldSet]; // will remove items that should be kept + diff -= [self deleteArticlesWithOldSet:oldSet]; // remove old, outdated articles // Get new total article count and post unread-count-change notification if (flag && diff != 0) { [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationTotalUnreadCountChanged object:@(diff)]; @@ -108,9 +108,10 @@ 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. - @param urls Input will be used to identify new articles. Output will contain URLs that aren't present in the feed anymore. + @param oldSet Input will be used to identify new articles. + Output contains articles that aren't present in the feed anymore and should be deleted. */ -- (NSInteger)addMissingArticles:(RSParsedFeed*)obj updateLinks:(NSMutableSet*)urls { +- (NSInteger)addMissingArticles:(RSParsedFeed*)obj withOldSet:(NSMutableSet*)oldSet { NSInteger newOnes = 0; int32_t currentIndex = [[self.articles valueForKeyPath:@"@min.sortIndex"] intValue]; FeedArticle *lastInserted = nil; @@ -118,10 +119,10 @@ for (RSParsedArticle *article in [obj.articles reverseObjectEnumerator]) { // reverse enumeration ensures correct article order - if ([urls containsObject:article.link]) { - [urls removeObject:article.link]; - FeedArticle *storedArticle = [self findArticleWithLink:article.link]; // TODO: use two synced arrays? - if (storedArticle && storedArticle.sortIndex != currentIndex) { + FeedArticle *storedArticle = [self findArticle:article inSet:oldSet]; + if (storedArticle) { + [oldSet removeObject:storedArticle]; + if (storedArticle.sortIndex != currentIndex) { storedArticle.sortIndex = currentIndex; } hasGapBetweenNewArticles = YES; @@ -146,26 +147,19 @@ } /** - Delete all items where @c link matches one of the URLs in the @c NSSet. + Delete all articles from core data, that are still in the oldSet. */ -- (NSUInteger)deleteArticlesWithLink:(NSMutableSet*)urls { - if (!urls || urls.count == 0) +- (NSUInteger)deleteArticlesWithOldSet:(NSMutableSet*)oldSet { + if (!oldSet || oldSet.count == 0) return 0; NSUInteger c = 0; - for (FeedArticle *fa in self.articles) { - if ([urls containsObject:fa.link]) { - [urls removeObject:fa.link]; - if (fa.unread) ++c; - // TODO: keep unread articles? - [self.managedObjectContext deleteObject:fa]; - if (urls.count == 0) - break; - } - } - NSSet *delArticles = [self.managedObjectContext deletedObjects]; - if (delArticles.count > 0) { - [self removeArticles:delArticles]; + for (FeedArticle *fa in oldSet) { + if (fa.unread) ++c; + // TODO: keep unread articles? + [self.managedObjectContext deleteObject:fa]; } + if (oldSet.count > 0) + [self removeArticles:oldSet]; return c; } @@ -183,12 +177,18 @@ } /** - Iterate over all Articles and return the one where @c .link matches. Or @c nil if no matching article found. + Iterate over oldSet and return the one where @c link and @c guid matches. Or @c nil if no matching article found. */ -- (FeedArticle*)findArticleWithLink:(NSString*)url { - for (FeedArticle *a in self.articles) { - if ([a.link isEqualToString:url]) - return a; +- (FeedArticle*)findArticle:(RSParsedArticle*)article inSet:(NSSet*)oldSet { + NSString *searchLink = article.link; + NSString *searchGuid = article.guid; + BOOL linkIsNil = (searchLink == nil); + BOOL guidIsNil = (searchGuid == nil); + for (FeedArticle *old in oldSet) { + if ((linkIsNil && old.link == nil) || [old.link isEqualToString:searchLink]) { + if ((guidIsNil && old.guid == nil) || [old.guid isEqualToString:searchGuid]) + return old; + } } return nil; } diff --git a/baRSS/Info.plist b/baRSS/Info.plist index daa9430..1a85c4f 100644 --- a/baRSS/Info.plist +++ b/baRSS/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.9.2 + 0.9.3 CFBundleURLTypes @@ -32,7 +32,7 @@ CFBundleVersion - 1146 + 1153 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) LSUIElement