2 Commits

Author SHA1 Message Date
relikd
4c4a133fe2 chore: bump version 2025-10-29 15:12:43 +01:00
relikd
ccca329630 feat: notification open options 2025-10-29 15:10:06 +01:00
4 changed files with 34 additions and 9 deletions

View File

@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.5.2] 2025-10-29
### Added
- *Notifications:* Reply with "Open in background", "Mark read & dismiss", or "Open but keep unread"
## [1.5.1] 2025-10-27
### Fixed
- *Status Bar Menu:* Simplified options for "Show only unread"
@@ -220,6 +225,7 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
Initial release
[1.5.2]: https://github.com/relikd/baRSS/compare/v1.5.1...v1.5.2
[1.5.1]: https://github.com/relikd/baRSS/compare/v1.5.0...v1.5.1
[1.5.0]: https://github.com/relikd/baRSS/compare/v1.4.1...v1.5.0
[1.4.1]: https://github.com/relikd/baRSS/compare/v1.4.0...v1.4.1

View File

@@ -805,7 +805,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 16720;
CURRENT_PROJECT_VERSION = 16777;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = UY657LKNHJ;
@@ -823,7 +823,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 1.5.1;
MARKETING_VERSION = 1.5.2;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
@@ -866,7 +866,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 16720;
CURRENT_PROJECT_VERSION = 16777;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = UY657LKNHJ;
@@ -881,7 +881,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 1.5.1;
MARKETING_VERSION = 1.5.2;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};

View File

@@ -225,9 +225,11 @@
return nil; // if success == NO, do not modify unread state & exit
}
NSInteger countChange = 0;
for (FeedArticle *fa in list) {
if (fa.unread == markRead) { // only if differs
fa.unread = !markRead;
countChange += markRead ? -1 : +1;
}
}
[self saveContext:moc andParent:YES];
@@ -242,8 +244,7 @@
}
[moc reset];
NSNumber *num = [NSNumber numberWithInteger: (markRead ? -1 : +1) * (NSInteger)list.count ];
PostNotification(kNotificationTotalUnreadCountChanged, num);
PostNotification(kNotificationTotalUnreadCountChanged, @(countChange));
return dbRefs;
}

View File

@@ -9,6 +9,11 @@
*/
static NSString* const kNotifyIdGlobal = @"global";
static NSString* const kCategoryDismissable = @"DISMISSIBLE";
static NSString* const kActionOpenBackground = @"OPEN_IN_BACKGROUND";
static NSString* const kActionMarkRead = @"MARK_READ_DONT_OPEN";
static NSString* const kActionOpenOnly = @"OPEN_ONLY_DONT_MARK_READ";
@implementation NotifyEndpoint
@@ -18,20 +23,27 @@ static NotificationType notifyType;
/// Ask user for permission to send notifications @b AND register delegate to respond to alert banner clicks.
/// @note Called every time user changes notification settings
+ (void)activate {
UNUserNotificationCenter *center = UNUserNotificationCenter.currentNotificationCenter;
notifyType = UserPrefsNotificationType();
// even if disabled, register delegate. This allows to open previously sent notifications
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [NotifyEndpoint new];
UNUserNotificationCenter.currentNotificationCenter.delegate = singleton;
center.delegate = singleton;
});
if (notifyType == NotificationTypeDisabled) {
return;
}
// register action types (allow mark read without opening notification)
UNNotificationAction *openBackgroundAction = [UNNotificationAction actionWithIdentifier:kActionOpenBackground title:NSLocalizedString(@"Open in background", nil) options:UNNotificationActionOptionNone];
UNNotificationAction *dontOpenAction = [UNNotificationAction actionWithIdentifier:kActionMarkRead title:NSLocalizedString(@"Mark read & dismiss", nil) options:UNNotificationActionOptionNone];
UNNotificationAction *dontReadAction = [UNNotificationAction actionWithIdentifier:kActionOpenOnly title:NSLocalizedString(@"Open but keep unread", nil) options:UNNotificationActionOptionNone];
UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:kCategoryDismissable actions:@[openBackgroundAction, dontOpenAction, dontReadAction] intentIdentifiers:@[] options:UNNotificationCategoryOptionNone];
[center setNotificationCategories:[NSSet setWithObject:category]];
[UNUserNotificationCenter.currentNotificationCenter requestAuthorizationWithOptions:UNAuthorizationOptionAlert | UNAuthorizationOptionSound completionHandler:^(BOOL granted, NSError * _Nullable error) {
[center requestAuthorizationWithOptions:UNAuthorizationOptionAlert | UNAuthorizationOptionSound completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSAlert *alert = [[NSAlert alloc] init];
@@ -105,6 +117,7 @@ static NotificationType notifyType;
if (title != nil) msg.title = title;
if (body != nil) msg.body = body;
// common settings:
msg.categoryIdentifier = kCategoryDismissable;
// TODO: make sound configurable?
msg.sound = [UNNotificationSound defaultSound];
[self send:identifier content: msg];
@@ -167,7 +180,12 @@ static NotificationType notifyType;
return;
}
}
[StoreCoordinator updateArticles:articles markRead:YES andOpen:YES inContext:moc];
// open-in-background performs the same operation as a normal click
// the "background" part is triggered by _NOT_ having the UNNotificationActionOptionForeground option
BOOL dontOpen = [response.actionIdentifier isEqualToString:kActionMarkRead];
BOOL dontMarkRead = [response.actionIdentifier isEqualToString:kActionOpenOnly];
[StoreCoordinator updateArticles:articles markRead:!dontMarkRead andOpen:!dontOpen inContext:moc];
}
@end