1// Copyright 2018-present 650 Industries. All rights reserved. 2 3#import <ExpoModulesCore/EXDefines.h> 4#import <EXNotifications/EXNotificationBuilder.h> 5#import <EXNotifications/NSDictionary+EXNotificationsVerifyingClass.h> 6 7@implementation EXNotificationBuilder 8 9EX_REGISTER_MODULE(); 10 11+ (const NSArray<Protocol *> *)exportedInterfaces 12{ 13 return @[@protocol(EXNotificationBuilder)]; 14} 15 16- (UNMutableNotificationContent *)notificationContentFromRequest:(NSDictionary *)request 17{ 18 UNMutableNotificationContent *content = [UNMutableNotificationContent new]; 19 [content setTitle:[request objectForKey:@"title" verifyingClass:[NSString class]]]; 20 [content setSubtitle:[request objectForKey:@"subtitle" verifyingClass:[NSString class]]]; 21 [content setBody:[request objectForKey:@"body" verifyingClass:[NSString class]]]; 22 [content setLaunchImageName:[request objectForKey:@"launchImageName" verifyingClass:[NSString class]]]; 23 [content setBadge:[request objectForKey:@"badge" verifyingClass:[NSNumber class]]]; 24 [content setUserInfo:[request objectForKey:@"data" verifyingClass:[NSDictionary class]]]; 25 [content setCategoryIdentifier:[request objectForKey:@"categoryIdentifier" verifyingClass:[NSString class]]]; 26 if ([request[@"sound"] isKindOfClass:[NSNumber class]]) { 27 [content setSound:[request[@"sound"] boolValue] ? [UNNotificationSound defaultSound] : nil]; 28 } else if ([request[@"sound"] isKindOfClass:[NSString class]]) { 29 NSString *soundName = request[@"sound"]; 30 if ([@"default" isEqualToString:soundName]) { 31 [content setSound:[UNNotificationSound defaultSound]]; 32 } else if ([@"defaultCritical" isEqualToString:soundName]) { 33 if (@available(iOS 12.0, *)) { 34 [content setSound:[UNNotificationSound defaultCriticalSound]]; 35 } else { 36 [content setSound:[UNNotificationSound defaultSound]]; 37 } 38 } else { 39 [content setSound:[UNNotificationSound soundNamed:soundName]]; 40 } 41 } 42 NSMutableArray<UNNotificationAttachment *> *attachments = [NSMutableArray new]; 43 [[request objectForKey:@"attachments" verifyingClass:[NSArray class]] enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 44 UNNotificationAttachment *attachment = [self attachmentFromRequest:obj]; 45 if (attachment) { 46 [attachments addObject:attachment]; 47 } 48 }]; 49 [content setAttachments:attachments]; 50 return content; 51} 52 53- (UNNotificationAttachment *)attachmentFromRequest:(NSDictionary *)request 54{ 55 NSString *identifier = [request objectForKey:@"identifier" verifyingClass:[NSString class]] ?: @""; 56 NSURL *uri = [NSURL URLWithString:[request objectForKey:@"uri" verifyingClass:[NSString class]]]; 57 NSError *error = nil; 58 UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:identifier URL:uri options:[self attachmentOptionsFromRequest:request] error:&error]; 59 if (error) { 60 EXLogWarn(@"[expo-notifications] Could not have created a notification attachment out of request: %@. Error: %@.", [request description], [error description]); 61 return nil; 62 } 63 return attachment; 64} 65 66- (NSDictionary *)attachmentOptionsFromRequest:(NSDictionary *)request 67{ 68 NSMutableDictionary *options = [NSMutableDictionary new]; 69 if ([request objectForKey:@"typeHint" verifyingClass:[NSString class]]) { 70 options[UNNotificationAttachmentOptionsTypeHintKey] = request[@"typeHint"]; 71 } 72 if ([request objectForKey:@"hideThumbnail" verifyingClass:[NSNumber class]]) { 73 options[UNNotificationAttachmentOptionsThumbnailHiddenKey] = request[@"hideThumbnail"]; 74 } 75 if ([request objectForKey:@"thumbnailClipArea" verifyingClass:[NSDictionary class]]) { 76 NSDictionary *area = request[@"thumbnailClipArea"]; 77 NSNumber *x = [area objectForKey:@"x" verifyingClass:[NSNumber class]]; 78 NSNumber *y = [area objectForKey:@"y" verifyingClass:[NSNumber class]]; 79 NSNumber *width = [area objectForKey:@"width" verifyingClass:[NSNumber class]]; 80 NSNumber *height = [area objectForKey:@"height" verifyingClass:[NSNumber class]]; 81 CGRect areaRect = CGRectMake([x doubleValue], [y doubleValue], [width doubleValue], [height doubleValue]); 82 options[UNNotificationAttachmentOptionsThumbnailClippingRectKey] = (__bridge id _Nullable)(CGRectCreateDictionaryRepresentation(areaRect)); 83 } 84 if ([request objectForKey:@"thumbnailTime" verifyingClass:[NSNumber class]]) { 85 options[UNNotificationAttachmentOptionsThumbnailTimeKey] = request[@"thumbnailTime"]; 86 } 87 return options; 88} 89 90@end 91 92