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