The wicked ghost must vanish! Items emerge from the dead.
This commit is contained in:
@@ -42,6 +42,7 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
|
|||||||
- *UI:* If an error occurs, show document URL (path to file or web url)
|
- *UI:* If an error occurs, show document URL (path to file or web url)
|
||||||
- Comparison of existing articles with nonexistent guid and link
|
- Comparison of existing articles with nonexistent guid and link
|
||||||
- Don't mark articles read if opening URLs failed
|
- Don't mark articles read if opening URLs failed
|
||||||
|
- Don't mark articles read that appear in the middle of a feed (ghost items)
|
||||||
- HTML tag removal keeps structure intact
|
- HTML tag removal keeps structure intact
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
@@ -90,52 +90,36 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Append new articles and increment their sortIndex. Update unread counter on the way.
|
Append new articles and increment @c sortIndex and unread count.
|
||||||
|
New articles are in ascending order without any gaps in between.
|
||||||
|
|
||||||
@note
|
@param localSet Use result set of @c deleteArticles:withRemoteSet:
|
||||||
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 localSet Use result set @c localSet of method call @c deleteArticles:withRemoteSet:.
|
|
||||||
@param remoteSet Readonly copy of @c RSParsedFeed.articles.
|
|
||||||
*/
|
*/
|
||||||
- (NSUInteger)insertArticles:(NSMutableSet<FeedArticle*>*)localSet withRemoteSet:(NSArray<RSParsedArticle*>*)remoteSet {
|
- (NSUInteger)insertArticles:(NSMutableSet<FeedArticle*>*)localSet withRemoteSet:(NSArray<RSParsedArticle*>*)remoteSet {
|
||||||
int32_t currentIndex = [[localSet valueForKeyPath:@"@min.sortIndex"] intValue];
|
int32_t currentIndex = [[localSet valueForKeyPath:@"@min.sortIndex"] intValue];
|
||||||
NSMutableArray<FeedArticle*>* newlyInserted = [NSMutableArray arrayWithCapacity:remoteSet.count];
|
NSUInteger c = 0;
|
||||||
|
|
||||||
for (RSParsedArticle *article in [remoteSet reverseObjectEnumerator]) {
|
for (RSParsedArticle *article in [remoteSet reverseObjectEnumerator]) {
|
||||||
// reverse enumeration ensures correct article order
|
// Reverse enumeration ensures correct article order
|
||||||
FeedArticle *storedArticle = [self findRemoteArticle:article inLocalSet:localSet];
|
FeedArticle *stored = [self findRemoteArticle:article inLocalSet:localSet];
|
||||||
if (storedArticle) {
|
if (stored) {
|
||||||
// TODO: stop bullshitting with ghost articles
|
[localSet removeObject:stored];
|
||||||
[localSet removeObject:storedArticle];
|
if (stored.sortIndex != currentIndex)
|
||||||
// If we encounter an already existing item, assume newly inserted are "ghost" items and mark read.
|
stored.sortIndex = currentIndex; // Ensures block of ascending indices
|
||||||
if (newlyInserted.count > 0) {
|
|
||||||
for (FeedArticle *ghostItem in newlyInserted) {
|
|
||||||
ghostItem.unread = NO;
|
|
||||||
}
|
|
||||||
[newlyInserted removeAllObjects];
|
|
||||||
}
|
|
||||||
// Ensures consecutive block of incrementing numbers on sortIndex
|
|
||||||
if (storedArticle.sortIndex != currentIndex) {
|
|
||||||
storedArticle.sortIndex = currentIndex;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
FeedArticle *newArticle = [FeedArticle newArticle:article inContext:self.managedObjectContext];
|
FeedArticle *newArticle = [FeedArticle newArticle:article inContext:self.managedObjectContext];
|
||||||
newArticle.sortIndex = currentIndex;
|
newArticle.sortIndex = currentIndex;
|
||||||
[self addArticlesObject:newArticle];
|
[self addArticlesObject:newArticle];
|
||||||
[newlyInserted addObject:newArticle];
|
c += 1;
|
||||||
}
|
}
|
||||||
currentIndex += 1;
|
currentIndex += 1;
|
||||||
}
|
}
|
||||||
return newlyInserted.count; // all ghost items are removed already
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Delete all articles from core data, that aren't present anymore.
|
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 localSet Input a copy of @c self.articles . Output same set minus deleted articles.
|
||||||
@param remoteSet Readonly copy of @c RSParsedFeed.articles.
|
|
||||||
*/
|
*/
|
||||||
- (NSUInteger)deleteArticles:(NSMutableSet<FeedArticle*>*)localSet withRemoteSet:(NSArray<RSParsedArticle*>*)remoteSet {
|
- (NSUInteger)deleteArticles:(NSMutableSet<FeedArticle*>*)localSet withRemoteSet:(NSArray<RSParsedArticle*>*)remoteSet {
|
||||||
NSUInteger c = 0;
|
NSUInteger c = 0;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>13435</string>
|
<string>13460</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.news</string>
|
<string>public.app-category.news</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
|||||||
@@ -57,7 +57,10 @@
|
|||||||
|
|
||||||
/// Delete file or folder at URL. If item does not exist, this method does nothing.
|
/// Delete file or folder at URL. If item does not exist, this method does nothing.
|
||||||
- (void)remove {
|
- (void)remove {
|
||||||
BOOL success = [[NSFileManager defaultManager] removeItemAtURL:self error:nil];
|
#ifdef DEBUG
|
||||||
|
BOOL success =
|
||||||
|
#endif
|
||||||
|
[[NSFileManager defaultManager] removeItemAtURL:self error:nil];
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (success) printf("DEL %s\n", self.absoluteString.UTF8String);
|
if (success) printf("DEL %s\n", self.absoluteString.UTF8String);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user