Accurate status count when updating feeds
This commit is contained in:
@@ -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:* 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`
|
- *Adding feed:* Prefer favicons with size `32x32`
|
||||||
- *Settings, Feeds:* Actions `delete` and `edit` use clicked items instead of selected items
|
- *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)
|
- *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
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
@import Cocoa;
|
@import Cocoa;
|
||||||
|
|
||||||
@interface UpdateScheduler : NSObject
|
@interface UpdateScheduler : NSObject
|
||||||
|
@property (class, readonly) NSUInteger feedsInQueue;
|
||||||
@property (class, readonly) NSDate *dateScheduled;
|
@property (class, readonly) NSDate *dateScheduled;
|
||||||
@property (class, readonly) BOOL allowNetworkConnection;
|
@property (class, readonly) BOOL allowNetworkConnection;
|
||||||
@property (class, readonly) BOOL isUpdating;
|
@property (class, readonly) BOOL isUpdating;
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ static BOOL _nextUpdateIsForced = NO;
|
|||||||
|
|
||||||
#pragma mark - User Interaction
|
#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.
|
/// @return Date when background update will fire. If updates are paused, date is @c distantFuture.
|
||||||
+ (NSDate *)dateScheduled { return _timer.fireDate; }
|
+ (NSDate *)dateScheduled { return _timer.fireDate; }
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
@class Feed;
|
@class Feed;
|
||||||
|
|
||||||
@interface WebFeed : NSObject
|
@interface WebFeed : NSObject
|
||||||
|
@property (class, readonly) NSUInteger feedsInQueue;
|
||||||
|
|
||||||
+ (void)setRequestsAreUrgent:(BOOL)flag;
|
+ (void)setRequestsAreUrgent:(BOOL)flag;
|
||||||
// Downloading
|
// Downloading
|
||||||
+ (void)newFeed:(NSString *)urlStr askUser:(nonnull NSString*(^)(RSHTMLMetadata *meta))askUser block:(nonnull void(^)(RSParsedFeed *parsed, NSError *error, NSHTTPURLResponse *response))block;
|
+ (void)newFeed:(NSString *)urlStr askUser:(nonnull NSString*(^)(RSHTMLMetadata *meta))askUser block:(nonnull void(^)(RSParsedFeed *parsed, NSError *error, NSHTTPURLResponse *response))block;
|
||||||
|
|||||||
@@ -28,15 +28,19 @@
|
|||||||
#import "FeedMeta+Ext.h"
|
#import "FeedMeta+Ext.h"
|
||||||
#import "FeedGroup+Ext.h"
|
#import "FeedGroup+Ext.h"
|
||||||
#import "NSDate+Ext.h"
|
#import "NSDate+Ext.h"
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
static BOOL _requestsAreUrgent = NO;
|
static BOOL _requestsAreUrgent = NO;
|
||||||
|
static _Atomic(NSUInteger) _queueSize = 0;
|
||||||
|
|
||||||
@implementation WebFeed
|
@implementation WebFeed
|
||||||
|
|
||||||
/// Disables @c NSURLNetworkServiceTypeBackground (ideally only temporarily)
|
/// Disables @c NSURLNetworkServiceTypeBackground (ideally only temporarily)
|
||||||
+ (void)setRequestsAreUrgent:(BOOL)flag { _requestsAreUrgent = flag; }
|
+ (void)setRequestsAreUrgent:(BOOL)flag { _requestsAreUrgent = flag; }
|
||||||
|
|
||||||
|
/// @return Number of feeds being currently downloaded.
|
||||||
|
+ (NSUInteger)feedsInQueue { return _queueSize; }
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - Request Generator
|
#pragma mark - Request Generator
|
||||||
|
|
||||||
@@ -292,11 +296,14 @@ static BOOL _requestsAreUrgent = NO;
|
|||||||
*/
|
*/
|
||||||
+ (void)batchDownloadFeeds:(NSArray<Feed*> *)list favicons:(BOOL)fav showErrorAlert:(BOOL)alert finally:(nullable os_block_t)block {
|
+ (void)batchDownloadFeeds:(NSArray<Feed*> *)list favicons:(BOOL)fav showErrorAlert:(BOOL)alert finally:(nullable os_block_t)block {
|
||||||
[UpdateScheduler beginUpdate];
|
[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();
|
dispatch_group_t group = dispatch_group_create();
|
||||||
for (Feed *f in list) {
|
for (Feed *f in list) {
|
||||||
dispatch_group_enter(group);
|
dispatch_group_enter(group);
|
||||||
[self backgroundUpdateBoth:f favicon:fav alert:alert finally:^(BOOL success){
|
[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);
|
dispatch_group_leave(group);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>10349</string>
|
<string>10386</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>
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
self.timerStatusInfo = [NSTimer timerWithTimeInterval:NSTimeIntervalSince1970 target:self selector:@selector(keepTimerRunning) userInfo:nil repeats:YES];
|
self.timerStatusInfo = [NSTimer timerWithTimeInterval:NSTimeIntervalSince1970 target:self selector:@selector(keepTimerRunning) userInfo:nil repeats:YES];
|
||||||
[[NSRunLoop mainRunLoop] addTimer:self.timerStatusInfo forMode:NSRunLoopCommonModes];
|
[[NSRunLoop mainRunLoop] addTimer:self.timerStatusInfo forMode:NSRunLoopCommonModes];
|
||||||
// start spinner if update is in progress when preferences open
|
// start spinner if update is in progress when preferences open
|
||||||
[self activateSpinner:([UpdateScheduler isUpdating] ? -1 : 0)];
|
[self activateSpinner:[UpdateScheduler feedsInQueue]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Timer cleanup
|
/// 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.
|
/// 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) {
|
if (c == 0) {
|
||||||
[self.view.spinner stopAnimation:nil];
|
[self.view.spinner stopAnimation:nil];
|
||||||
self.view.status.stringValue = @"";
|
self.view.status.stringValue = @"";
|
||||||
@@ -200,8 +200,6 @@
|
|||||||
[self.view.spinner startAnimation:nil];
|
[self.view.spinner startAnimation:nil];
|
||||||
if (c == 1) { // exactly one feed
|
if (c == 1) { // exactly one feed
|
||||||
self.view.status.stringValue = NSLocalizedString(@"Updating 1 feed …", nil);
|
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 {
|
} else {
|
||||||
self.view.status.stringValue = [NSString stringWithFormat:NSLocalizedString(@"Updating %lu feeds …", nil), c];
|
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.
|
/// Callback method fired when background feed update begins and ends.
|
||||||
- (void)updateInProgress:(NSNotification*)notify {
|
- (void)updateInProgress:(NSNotification*)notify {
|
||||||
[self activateSpinner:[notify.object integerValue]];
|
[self activateSpinner:[notify.object unsignedIntegerValue]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user