11#import " ReactNativeShareExtension.h"
22#import " React/RCTRootView.h"
33
4- #define ITEM_IDENTIFIER @" public.url"
5- #define IMAGE_IDENTIFIER @" public.image"
4+ // public.url
5+ // public.image
6+ // public.movie
7+ // public.plain-text
8+ // #define URL_IDENTIFIER @"public.url"
9+ // #define IMAGE_IDENTIFIER @"public.image"
10+
611
712NSExtensionContext * extensionContext;
813
@@ -34,16 +39,18 @@ - (void)viewDidLoad {
3439}
3540
3641
37- RCT_EXPORT_METHOD (close) {
38- [extensionContext completeRequestReturningItems: nil
39- completionHandler: nil ];
42+ RCT_EXPORT_METHOD (close:(NSString *)appGroupId) {
43+ [self cleanUpTempFiles: appGroupId];
44+ [extensionContext completeRequestReturningItems: nil
45+ completionHandler: nil ];
4046}
4147
4248RCT_REMAP_METHOD (data,
43- resolver:(RCTPromiseResolveBlock)resolve
44- rejecter:(RCTPromiseRejectBlock)reject)
49+ appGroupId: (NSString *)appGroupId
50+ resolver:(RCTPromiseResolveBlock)resolve
51+ rejecter:(RCTPromiseRejectBlock)reject)
4552{
46- [self extractDataFromContext: extensionContext withCallback : ^(NSArray * items ,NSException * err) {
53+ [self extractDataFromContext: extensionContext withAppGroup: appGroupId andCallback : ^(NSArray * items ,NSException * err) {
4754 if (items == nil ) {
4855 resolve (nil );
4956 return ;
@@ -53,80 +60,173 @@ - (void)viewDidLoad {
5360}
5461
5562RCT_REMAP_METHOD (dataMulti,
63+ appGroupId: (NSString *)appGroupId
5664 resolverMulti:(RCTPromiseResolveBlock)resolve
5765 rejecterMulti:(RCTPromiseRejectBlock)reject)
5866{
59- [self extractDataFromContext: extensionContext withCallback : ^(NSArray * items ,NSException * err) {
67+ [self extractDataFromContext: extensionContext withAppGroup: appGroupId andCallback : ^(NSArray * items ,NSException * err) {
6068 resolve (items);
6169 }];
6270}
6371
64- typedef void (^ProviderCallback)(NSURL *url , NSString *contentType, NSException *exception);
72+ typedef void (^ProviderCallback)(NSString *content , NSString *contentType, BOOL owner , NSException *exception);
6573
66- - (void )extractDataFromContext : (NSExtensionContext *)context withCallback : (void (^)(NSArray *items ,NSException *exception))callback {
74+ - (void )extractDataFromContext : (NSExtensionContext *)context withAppGroup : ( NSString *) appGroupId andCallback : (void (^)(NSArray *items ,NSException *exception))callback {
6775 @try {
6876 NSExtensionItem *item = [context.inputItems firstObject ];
6977 NSArray *attachments = item.attachments ;
7078 NSMutableArray *items = [[NSMutableArray alloc ] init ];
71-
79+
7280 __block int attachmentIdx = 0 ;
7381 __block ProviderCallback providerCb = nil ;
74- providerCb = ^ void (NSURL *url , NSString *contentType, NSException *exception) {
82+ providerCb = ^ void (NSString *content , NSString *contentType, BOOL owner , NSException *exception) {
7583 if (exception) {
7684 callback (nil , exception);
7785 return ;
7886 }
79-
80- [items addObject: @{
81- @" type" : contentType,
82- @" value" : [url absoluteString ]
83- }];
87+
88+ if (content != nil ) {
89+ [items addObject: @{
90+ @" type" : contentType,
91+ @" value" : content,
92+ @" owner" : [NSNumber numberWithBool: owner],
93+ }];
94+ }
8495
8596 ++attachmentIdx;
8697 if (attachmentIdx == [attachments count ]) {
8798 callback (items, nil );
8899 } else {
89- [self extractDataFromProvider: attachments[attachmentIdx] withCallback : providerCb];
100+ [self extractDataFromProvider: attachments[attachmentIdx] withAppGroup: appGroupId andCallback : providerCb];
90101 }
91102 };
92- [self extractDataFromProvider: attachments[0 ] withCallback : providerCb];
103+ [self extractDataFromProvider: attachments[0 ] withAppGroup: appGroupId andCallback : providerCb];
93104 }
94105 @catch (NSException *exception) {
95106 callback (nil ,exception);
96107 }
97108}
98109
99- - (void )extractDataFromProvider : (NSItemProvider *)provider withCallback : (void (^)(NSURL * url, NSString * contentType ,NSException *exception))callback {
100- NSItemProvider *urlProvider = nil ;
101- NSItemProvider *imageProvider = nil ;
102-
103- if ([provider hasItemConformingToTypeIdentifier: ITEM_IDENTIFIER]) {
104- urlProvider = provider;
105- }else if ([provider hasItemConformingToTypeIdentifier: IMAGE_IDENTIFIER]){
106- imageProvider = provider;
107- }
108-
109- if (urlProvider) {
110- [urlProvider loadItemForTypeIdentifier: ITEM_IDENTIFIER options: nil completionHandler: ^(id <NSSecureCoding > item, NSError *error) {
111- NSURL *url = (NSURL *)item;
110+ - (void )extractDataFromProvider : (NSItemProvider *)provider withAppGroup : (NSString *) appGroupId andCallback : (void (^)(NSString * content, NSString * contentType, BOOL owner, NSException *exception))callback {
111+
112+ if ([provider hasItemConformingToTypeIdentifier: @" public.image" ]) {
113+ [provider loadItemForTypeIdentifier: @" public.image" options: nil completionHandler: ^(id <NSSecureCoding , NSObject > item, NSError *error) {
114+ if (error) {
115+ callback (nil , nil , NO , error);
116+ return ;
117+ }
118+
119+ if ([item isKindOfClass: NSURL .class]) {
120+ NSURL *url = (NSURL *)item;
121+ return callback ([url absoluteString ], @" public.image" , NO , nil );
122+ } else if ([item isKindOfClass: UIImage.class]) {
123+ UIImage *image = (UIImage *)item;
124+ NSString *fileName = [NSString stringWithFormat: @" %@ .jpg" , [[NSUUID UUID ] UUIDString ]];
125+ NSURL *tempContainerURL = [ReactNativeShareExtension tempContainerURL: appGroupId];
126+ if (tempContainerURL == nil ){
127+ return callback (nil , nil , NO , nil );
128+ }
112129
113- if (callback) {
114- callback (url,@" text/plain" ,nil );
130+ NSURL *tempFileURL = [tempContainerURL URLByAppendingPathComponent: fileName];
131+ BOOL created = [UIImageJPEGRepresentation (image, 0.95 ) writeToFile: [tempFileURL path ] atomically: YES ];
132+ if (created) {
133+ return callback ([tempFileURL absoluteString ], @" public.image" , YES , nil );
134+ } else {
135+ return callback (nil , nil , NO , nil );
136+ }
137+ } else if ([item isKindOfClass: NSData .class]) {
138+ NSString *fileName = [NSString stringWithFormat: @" %@ .jpg" , [[NSUUID UUID ] UUIDString ]];
139+ NSData *data = (NSData *)item;
140+ UIImage *image = [UIImage imageWithData: data];
141+ NSURL *tempContainerURL = [ReactNativeShareExtension tempContainerURL: appGroupId];
142+ if (tempContainerURL == nil ){
143+ return callback (nil , nil , NO , nil );
144+ }
145+ NSURL *tempFileURL = [tempContainerURL URLByAppendingPathComponent: fileName];
146+ BOOL created = [UIImageJPEGRepresentation (image, 0.95 ) writeToFile: [tempFileURL path ] atomically: YES ];
147+ if (created) {
148+ return callback ([tempFileURL absoluteString ], @" public.image" , YES , nil );
149+ } else {
150+ return callback (nil , nil , NO , nil );
151+ }
152+ } else {
153+ // Do nothing, some type we don't support.
154+ return callback (nil , nil , NO , nil );
115155 }
116156 }];
117- }else if (imageProvider){
118- [imageProvider loadItemForTypeIdentifier: IMAGE_IDENTIFIER options: nil completionHandler: ^(id <NSSecureCoding > item, NSError *error) {
119- NSURL *url = (NSURL *)item;
120-
121- if (callback) {
122- callback (url,[[[url absoluteString ] pathExtension ] lowercaseString ] ,nil );
157+ return ;
158+ }
159+
160+ if ([provider hasItemConformingToTypeIdentifier: @" public.url" ]) {
161+ [provider loadItemForTypeIdentifier: @" public.url" options: nil completionHandler: ^(id <NSSecureCoding , NSObject > item, NSError *error) {
162+ if (error) {
163+ callback (nil , nil , NO , error);
164+ return ;
165+ }
166+ callback ([(NSURL *)item absoluteString ], @" public.url" , NO , nil );
167+ }];
168+ return ;
169+ }
170+
171+ if ([provider hasItemConformingToTypeIdentifier: @" public.text" ]) {
172+ [provider loadItemForTypeIdentifier: @" public.text" options: nil completionHandler: ^(id <NSSecureCoding , NSObject > item, NSError *error) {
173+ if (error) {
174+ callback (nil , nil , NO , error);
175+ return ;
176+ }
177+
178+ if ([item isKindOfClass: NSString .class]) {
179+ return callback ((NSString *)item, @" public.text" , NO , nil );
180+ } else if ([item isKindOfClass: NSData .class]) {
181+ NSString *str = [[NSString alloc ] initWithData: (NSData *)item encoding: NSUTF8StringEncoding];
182+ if (str) {
183+ return callback (str, @" public.text" , NO , nil );
184+ } else {
185+ return callback (nil , nil , NO , nil );
186+ }
187+ } else {
188+ return callback (nil , nil , NO , nil );
123189 }
124190 }];
125- } else {
126- if (callback) {
127- callback (nil , nil ,[NSException exceptionWithName: @" Error" reason: @" couldn't find provider" userInfo: nil ]);
191+ return ;
192+ }
193+
194+ callback (nil , nil , NO , nil );
195+ }
196+
197+ + (NSURL *) tempContainerURL : (NSString *)appGroupId {
198+ NSFileManager *manager = [NSFileManager defaultManager ];
199+ NSURL *containerURL = [manager containerURLForSecurityApplicationGroupIdentifier: appGroupId];
200+ NSURL *tempDirectoryURL = [containerURL URLByAppendingPathComponent: @" shareTempItems" ];
201+ if (![manager fileExistsAtPath: [tempDirectoryURL path ]]) {
202+ NSError *err;
203+ [manager createDirectoryAtURL: tempDirectoryURL withIntermediateDirectories: YES attributes: nil error: &err];
204+ if (err) {
205+ return nil ;
128206 }
129207 }
208+
209+ return tempDirectoryURL;
210+ }
211+
212+ - (void ) cleanUpTempFiles : (NSString *)appGroupId {
213+ NSURL *tmpDirectoryURL = [ReactNativeShareExtension tempContainerURL: appGroupId];
214+ if (tmpDirectoryURL == nil ) {
215+ return ;
216+ }
217+
218+ NSFileManager *fileManager = [NSFileManager defaultManager ];
219+ NSError *error;
220+ NSArray *tmpFiles = [fileManager contentsOfDirectoryAtPath: [tmpDirectoryURL path ] error: &error];
221+ if (error) {
222+ return ;
223+ }
224+
225+ for (NSString *file in tmpFiles)
226+ {
227+ error = nil ;
228+ [fileManager removeItemAtPath: [[tmpDirectoryURL URLByAppendingPathComponent: file] path ] error: &error];
229+ }
130230}
131231
132232@end
0 commit comments