From 202005eb0d8591913b0f49b0df6a2831fb034756 Mon Sep 17 00:00:00 2001 From: relikd Date: Mon, 12 Aug 2019 01:52:42 +0200 Subject: [PATCH] Accurate status count when updating feeds --- CHANGELOG.md | 1 + baRSS/Feed Import/UpdateScheduler.h | 1 + baRSS/Feed Import/UpdateScheduler.m | 3 +++ baRSS/Feed Import/WebFeed.h | 2 ++ baRSS/Feed Import/WebFeed.m | 11 +++++++++-- baRSS/Info.plist | 2 +- baRSS/Preferences/Feeds Tab/SettingsFeeds.m | 8 +++----- 7 files changed, 20 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0499618..ab20b5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2 - *Adding feed:* If URLs can't be resolved in the first run (5xx error), try a second time. E.g., `Done` click (issue: #5) - *Adding feed:* Prefer favicons with size `32x32` - *Settings, Feeds:* Actions `delete` and `edit` use clicked items instead of selected items +- *Settings, Feeds:* Accurate download count instead of `Updating feeds …` - *UI:* If an error occurs, show document URL (path to file or web url) - Comparison of existing articles with nonexistent guid and link - Don't mark articles read if opening URLs failed diff --git a/baRSS/Feed Import/UpdateScheduler.h b/baRSS/Feed Import/UpdateScheduler.h index 202df93..e5029a0 100644 --- a/baRSS/Feed Import/UpdateScheduler.h +++ b/baRSS/Feed Import/UpdateScheduler.h @@ -23,6 +23,7 @@ @import Cocoa; @interface UpdateScheduler : NSObject +@property (class, readonly) NSUInteger feedsInQueue; @property (class, readonly) NSDate *dateScheduled; @property (class, readonly) BOOL allowNetworkConnection; @property (class, readonly) BOOL isUpdating; diff --git a/baRSS/Feed Import/UpdateScheduler.m b/baRSS/Feed Import/UpdateScheduler.m index 7154e9a..2aee2c8 100644 --- a/baRSS/Feed Import/UpdateScheduler.m +++ b/baRSS/Feed Import/UpdateScheduler.m @@ -38,6 +38,9 @@ static BOOL _nextUpdateIsForced = NO; #pragma mark - User Interaction +/// @return Number of feeds being currently downloaded. ++ (NSUInteger)feedsInQueue { return [WebFeed feedsInQueue]; } + /// @return Date when background update will fire. If updates are paused, date is @c distantFuture. + (NSDate *)dateScheduled { return _timer.fireDate; } diff --git a/baRSS/Feed Import/WebFeed.h b/baRSS/Feed Import/WebFeed.h index a9ee7a9..7dd560e 100644 --- a/baRSS/Feed Import/WebFeed.h +++ b/baRSS/Feed Import/WebFeed.h @@ -25,6 +25,8 @@ @class Feed; @interface WebFeed : NSObject +@property (class, readonly) NSUInteger feedsInQueue; + + (void)setRequestsAreUrgent:(BOOL)flag; // Downloading + (void)newFeed:(NSString *)urlStr askUser:(nonnull NSString*(^)(RSHTMLMetadata *meta))askUser block:(nonnull void(^)(RSParsedFeed *parsed, NSError *error, NSHTTPURLResponse *response))block; diff --git a/baRSS/Feed Import/WebFeed.m b/baRSS/Feed Import/WebFeed.m index 7e4059d..3df6e9b 100644 --- a/baRSS/Feed Import/WebFeed.m +++ b/baRSS/Feed Import/WebFeed.m @@ -28,15 +28,19 @@ #import "FeedMeta+Ext.h" #import "FeedGroup+Ext.h" #import "NSDate+Ext.h" +#include static BOOL _requestsAreUrgent = NO; - +static _Atomic(NSUInteger) _queueSize = 0; @implementation WebFeed /// Disables @c NSURLNetworkServiceTypeBackground (ideally only temporarily) + (void)setRequestsAreUrgent:(BOOL)flag { _requestsAreUrgent = flag; } +/// @return Number of feeds being currently downloaded. ++ (NSUInteger)feedsInQueue { return _queueSize; } + #pragma mark - Request Generator @@ -292,11 +296,14 @@ static BOOL _requestsAreUrgent = NO; */ + (void)batchDownloadFeeds:(NSArray *)list favicons:(BOOL)fav showErrorAlert:(BOOL)alert finally:(nullable os_block_t)block { [UpdateScheduler beginUpdate]; - PostNotification(kNotificationBackgroundUpdateInProgress, @(list.count)); + atomic_fetch_add_explicit(&_queueSize, list.count, memory_order_relaxed); + PostNotification(kNotificationBackgroundUpdateInProgress, @(_queueSize)); dispatch_group_t group = dispatch_group_create(); for (Feed *f in list) { dispatch_group_enter(group); [self backgroundUpdateBoth:f favicon:fav alert:alert finally:^(BOOL success){ + atomic_fetch_sub_explicit(&_queueSize, 1, memory_order_relaxed); + PostNotification(kNotificationBackgroundUpdateInProgress, @(_queueSize)); dispatch_group_leave(group); }]; } diff --git a/baRSS/Info.plist b/baRSS/Info.plist index 7fadbbd..e5103d6 100644 --- a/baRSS/Info.plist +++ b/baRSS/Info.plist @@ -60,7 +60,7 @@ CFBundleVersion - 10349 + 10386 LSApplicationCategoryType public.app-category.news LSMinimumSystemVersion diff --git a/baRSS/Preferences/Feeds Tab/SettingsFeeds.m b/baRSS/Preferences/Feeds Tab/SettingsFeeds.m index 4411827..f2afa58 100644 --- a/baRSS/Preferences/Feeds Tab/SettingsFeeds.m +++ b/baRSS/Preferences/Feeds Tab/SettingsFeeds.m @@ -65,7 +65,7 @@ self.timerStatusInfo = [NSTimer timerWithTimeInterval:NSTimeIntervalSince1970 target:self selector:@selector(keepTimerRunning) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop] addTimer:self.timerStatusInfo forMode:NSRunLoopCommonModes]; // start spinner if update is in progress when preferences open - [self activateSpinner:([UpdateScheduler isUpdating] ? -1 : 0)]; + [self activateSpinner:[UpdateScheduler feedsInQueue]]; } /// Timer cleanup @@ -190,7 +190,7 @@ } /// Start ( @c c @c > @c 0 ) or stop ( @c c @c = @c 0 ) activity spinner. Also, sets status info. -- (void)activateSpinner:(NSInteger)c { +- (void)activateSpinner:(NSUInteger)c { if (c == 0) { [self.view.spinner stopAnimation:nil]; self.view.status.stringValue = @""; @@ -200,8 +200,6 @@ [self.view.spinner startAnimation:nil]; if (c == 1) { // exactly one feed self.view.status.stringValue = NSLocalizedString(@"Updating 1 feed …", nil); - } else if (c < 0) { // unknown number of feeds - self.view.status.stringValue = NSLocalizedString(@"Updating feeds …", nil); } else { self.view.status.stringValue = [NSString stringWithFormat:NSLocalizedString(@"Updating %lu feeds …", nil), c]; } @@ -210,7 +208,7 @@ /// Callback method fired when background feed update begins and ends. - (void)updateInProgress:(NSNotification*)notify { - [self activateSpinner:[notify.object integerValue]]; + [self activateSpinner:[notify.object unsignedIntegerValue]]; }