diff --git a/VHGithubNotifier.xcodeproj/project.pbxproj b/VHGithubNotifier.xcodeproj/project.pbxproj index b75a13b..6372c99 100644 --- a/VHGithubNotifier.xcodeproj/project.pbxproj +++ b/VHGithubNotifier.xcodeproj/project.pbxproj @@ -1529,7 +1529,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 6967F9654F27A5A529E7AF2F /* [CP] Embed Pods Frameworks */ = { diff --git a/VHGithubNotifier/Info.plist b/VHGithubNotifier/Info.plist index e0bb665..8fc4433 100644 --- a/VHGithubNotifier/Info.plist +++ b/VHGithubNotifier/Info.plist @@ -19,9 +19,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.2.6 + 1.0.2.7 CFBundleVersion - 1026 + 1027 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) LSUIElement diff --git a/VHGithubNotifier/Model/Manager/VHGithubNotifierManager+UserNotification.m b/VHGithubNotifier/Model/Manager/VHGithubNotifierManager+UserNotification.m index f7df4fa..abc5199 100644 --- a/VHGithubNotifier/Model/Manager/VHGithubNotifierManager+UserNotification.m +++ b/VHGithubNotifier/Model/Manager/VHGithubNotifierManager+UserNotification.m @@ -16,6 +16,7 @@ #import "VHGithubNotifierManager+Notification.h" static NSMutableArray *userNotifications; +static NSMutableSet *cacheNotifications; @implementation VHGithubNotifierManager (UserNotification) @@ -28,8 +29,7 @@ - (void)innerInitializePropertiesForUserNotification - (void)addNotifications:(NSArray *)notifications { - @synchronized (userNotifications) - { + IN_MAIN_THREAD({ for (VHNotification *notification in notifications) { CNUserNotification *userNotification = [[CNUserNotification alloc] init]; @@ -38,17 +38,15 @@ - (void)addNotifications:(NSArray *)notifications userNotification.informativeText = [notification toNowTimeString]; NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:4]; [userInfo setObject:@(VHGithubUserNotificationTypeNotification) forKey:@"type"]; - if (notification) - { - [userInfo setObject:notification forKey:@"notification"]; - } + [userInfo setObject:@(notification.notificationId) forKey:@"notificationID"]; userNotification.hasActionButton = NO; userNotification.feature.bannerImage = [VHUtils imageFromNotificationType:notification.type]; userNotification.userInfo = userInfo; [[self userNotifications] push:userNotification]; } - } - [self notify]; + [[self cacheNotifications] addObjectsFromArray:notifications]; + [self notify]; + }); } #pragma mark - Private Methods @@ -74,6 +72,44 @@ - (void)notify return userNotifications; } +- (NSMutableSet *)cacheNotifications +{ + if (cacheNotifications == nil) + { + cacheNotifications = [NSMutableSet set]; + } + return cacheNotifications; +} + +- (VHNotification *)cacheNotificationWithID:(long long)notificationID +{ + __block VHNotification *cacheNotification = nil; + [[self cacheNotifications] enumerateObjectsUsingBlock:^(VHNotification * _Nonnull obj, BOOL * _Nonnull stop) { + if (obj.notificationId == notificationID) + { + cacheNotification = obj; + *stop = YES; + } + }]; + return cacheNotification; +} + +- (void)removeCacheNotificationWithID:(long long)notificationID +{ + __block VHNotification *cacheNotification = nil; + [[self cacheNotifications] enumerateObjectsUsingBlock:^(VHNotification * _Nonnull obj, BOOL * _Nonnull stop) { + if (obj.notificationId == notificationID) + { + cacheNotification = obj; + *stop = YES; + } + }]; + if (cacheNotification) + { + [[self cacheNotifications] removeObject:cacheNotification]; + } +} + - (void)storeRecordOfNotification:(CNUserNotification *)userNotification { dispatch_async(GLOBAL_QUEUE, ^{ @@ -81,14 +117,17 @@ - (void)storeRecordOfNotification:(CNUserNotification *)userNotification { RLMRealm *realm = [self realm]; VHNotificationRecord *record = [[VHNotificationRecord alloc] init]; - VHNotification *notification = [userNotification.userInfo objectForKey:@"notification"]; - record.notificationId = notification.notificationId; - record.latestUpdateTime = notification.updateDate; - if (record.notificationId != 0 && record.latestUpdateTime) + VHNotification *notification = [self cacheNotificationWithID:[[userNotification.userInfo objectForKey:@"notificationID"] longLongValue]]; + if (notification) { - [realm beginWriteTransaction]; - [realm addOrUpdateObject:record]; - [realm commitWriteTransaction]; + record.notificationId = notification.notificationId; + record.latestUpdateTime = notification.updateDate; + if (record.notificationId != 0 && record.latestUpdateTime) + { + [realm beginWriteTransaction]; + [realm addOrUpdateObject:record]; + [realm commitWriteTransaction]; + } } } }); @@ -96,31 +135,32 @@ - (void)storeRecordOfNotification:(CNUserNotification *)userNotification #pragma mark - NSUserNotificationCenterDelegate -- (void)userNotificationCenter:(NSUserNotificationCenter *)center didDeliverNotification:(NSUserNotification *)notification +- (void)userNotificationCenter:(NSUserNotificationCenter *)center didDeliverNotification:(NSUserNotification *)userNotification { } -- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification +- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)userNotification { - NSDictionary *userInfo = notification.userInfo; + NSDictionary *userInfo = userNotification.userInfo; if (userInfo) { if ([[userInfo objectForKey:@"type"] integerValue] == VHGithubUserNotificationTypeNotification) { - VHNotification *notification = [userInfo objectForKey:@"notification"]; + VHNotification *notification = [self cacheNotificationWithID:[[userInfo objectForKey:@"notificationID"] longLongValue]]; [self openNotificationURLAndMarkAsReadBySettings:notification]; } } } -- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification +- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)userNotification { return YES; } -- (void)userNotificationCenter:(CNUserNotificationCenter *)center didRemoveNotification:(CNUserNotification *)notification +- (void)userNotificationCenter:(CNUserNotificationCenter *)center didRemoveNotification:(CNUserNotification *)userNotification { + [self removeCacheNotificationWithID:[[userNotification.userInfo objectForKey:@"notificationID"] longLongValue]]; [self notify]; } diff --git a/VHGithubNotifier/Model/VHNotification.h b/VHGithubNotifier/Model/VHNotification.h index 6d99909..05be233 100644 --- a/VHGithubNotifier/Model/VHNotification.h +++ b/VHGithubNotifier/Model/VHNotification.h @@ -29,7 +29,7 @@ typedef NS_ENUM(NSUInteger, VHNotificationType) VHNotificationTypePullRequest = 2, }; -@interface VHNotification : NSObject +@interface VHNotification : NSObject @property (nonatomic, assign) long long notificationId; @property (nonatomic, strong) NSDate *lastReadDate; diff --git a/VHGithubNotifier/Model/VHNotification.m b/VHGithubNotifier/Model/VHNotification.m index 1d33418..e1cf9c8 100644 --- a/VHGithubNotifier/Model/VHNotification.m +++ b/VHGithubNotifier/Model/VHNotification.m @@ -98,4 +98,39 @@ - (NSString *)description self.htmlUrl]; } +- (void)encodeWithCoder:(NSCoder *)aCoder +{ + [aCoder encodeInt64:self.notificationId forKey:@"notificationId"]; + [aCoder encodeObject:self.lastReadDate forKey:@"lastReadDate"]; + [aCoder encodeInteger:self.reason forKey:@"reason"]; + [aCoder encodeObject:self.repository forKey:@"repository"]; + [aCoder encodeObject:self.lastCommentUrl forKey:@"lastCommentUrl"]; + [aCoder encodeObject:self.title forKey:@"title"]; + [aCoder encodeObject:self.url forKey:@"url"]; + [aCoder encodeBool:self.unread forKey:@"unread"]; + [aCoder encodeObject:self.updateDate forKey:@"updateDate"]; + [aCoder encodeObject:self.htmlUrl forKey:@"htmlUrl"]; + [aCoder encodeInteger:self.type forKey:@"type"]; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder +{ + self = [super init]; + if (self) + { + _notificationId = [aDecoder decodeInt64ForKey:@"notificationId"]; + _lastReadDate = [aDecoder decodeObjectForKey:@"lastReadDate"]; + _reason = [aDecoder decodeIntegerForKey:@"reason"]; + _repository = [aDecoder decodeObjectForKey:@"repository"]; + _lastCommentUrl = [aDecoder decodeObjectForKey:@"lastCommentUrl"]; + _title = [aDecoder decodeObjectForKey:@"title"]; + _url = [aDecoder decodeObjectForKey:@"url"]; + _unread = [aDecoder decodeBoolForKey:@"unread"]; + _updateDate = [aDecoder decodeObjectForKey:@"updateDate"]; + _htmlUrl = [aDecoder decodeObjectForKey:@"htmlUrl"]; + _type = [aDecoder decodeIntegerForKey:@"type"]; + } + return self; +} + @end diff --git a/VHGithubNotifier/Model/VHSimpleRepository.h b/VHGithubNotifier/Model/VHSimpleRepository.h index a8d7e7b..123b2ac 100644 --- a/VHGithubNotifier/Model/VHSimpleRepository.h +++ b/VHGithubNotifier/Model/VHSimpleRepository.h @@ -6,7 +6,7 @@ // Copyright © 2017年 黄伟平. All rights reserved. // -@interface VHSimpleRepository : NSObject +@interface VHSimpleRepository : NSObject @property (nonatomic, assign) long long repositoryId; @property (nonatomic, strong) NSString *fullName; diff --git a/VHGithubNotifier/Model/VHSimpleRepository.m b/VHGithubNotifier/Model/VHSimpleRepository.m index 1918e54..eb81f04 100644 --- a/VHGithubNotifier/Model/VHSimpleRepository.m +++ b/VHGithubNotifier/Model/VHSimpleRepository.m @@ -71,4 +71,27 @@ - (NSUInteger)hash return self.repositoryId; } +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder +{ + [aCoder encodeInt64:self.repositoryId forKey:@"repositoryId"]; + [aCoder encodeObject:self.fullName forKey:@"fullName"]; + [aCoder encodeObject:self.htmlUrl forKey:@"htmlUrl"]; + [aCoder encodeObject:self.ownerName forKey:@"ownerName"]; + [aCoder encodeObject:self.name forKey:@"name"]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder +{ + self = [super init]; + if (self) + { + _repositoryId = [aDecoder decodeInt64ForKey:@"repositoryId"]; + _fullName = [aDecoder decodeObjectForKey:@"fullName"]; + _htmlUrl = [aDecoder decodeObjectForKey:@"htmlUrl"]; + _ownerName = [aDecoder decodeObjectForKey:@"ownerName"]; + _name = [aDecoder decodeObjectForKey:@"name"]; + } + return self; +} + @end