Skip to content

Instantly share code, notes, and snippets.

@ericlewis
Created April 13, 2019 17:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericlewis/1c3912289e66d109b250231f1709953d to your computer and use it in GitHub Desktop.
Save ericlewis/1c3912289e66d109b250231f1709953d to your computer and use it in GitHub Desktop.
react-native NativeModule for interacting with gmail objc google rest apis
//
// RNGmailAPI.m
// astroboy
//
// Created by Eric Lewis on 4/9/19.
// Copyright © 2019 Eric Lewis. All rights reserved.
//
#import "RNGmailAPI.h"
#import "RNPromiseWrapper.h"
#import <GTLRGmail.h>
@interface RNGmailAPI ()
@property (nonatomic) RNPromiseWrapper *promiseWrapper;
@property (nonatomic) GTLRGmailService *gmail;
@property (nonatomic) GTLRBatchQuery *batchQuery;
@property (nonatomic) GIDSignIn *signIn;
@end
@implementation RNGmailAPI
RCT_EXPORT_MODULE();
- (instancetype)init
{
self = [super init];
if (self) {
self.promiseWrapper = [[RNPromiseWrapper alloc] init];
self.gmail = [[GTLRGmailService alloc] init];
self.signIn = [GIDSignIn sharedInstance];
self.signIn.delegate = self;
}
return self;
}
- (NSDictionary *)constantsToExport
{
return @{ @"initialIsLoggedIn": @(self.signIn.hasAuthInKeychain) };
}
+ (BOOL)requiresMainQueueSetup
{
return NO;
}
RCT_EXPORT_METHOD(initialize:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
if (self.signIn.currentUser == nil) {
NSString *methodName = @"initialize";
[self.promiseWrapper setPromiseWithInProgressCheck:resolve rejecter:nil fromCallSite:methodName];
dispatch_async(dispatch_get_main_queue(), ^{
[[GIDSignIn sharedInstance] signInSilently];
});
} else {
resolve(self.signIn.currentUser);
}
}
RCT_EXPORT_METHOD(executeQueries:(NSArray<NSDictionary *> *)queries
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
[self execute:[self createBatchQuery:queries] resolver:resolve rejecter:reject];
}
- (void)execute:(GTLRBatchQuery *)query
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject
{
[self.gmail executeQuery:query
completionHandler:^(GTLRServiceTicket *ticket, GTLRBatchResult *batchResult, NSError *error) {
if (error == nil) {
// reset the global batcher (maybe there is a better way?) also, maybe we don't want to on error?
NSDictionary *successes = batchResult.successes;
NSMutableArray *successResponse = [[NSMutableArray alloc] initWithCapacity:successes.count];
for (NSString *requestID in successes) {
GTLRObject *list = [successes objectForKey:requestID];
[successResponse addObject:list.JSON];
}
NSDictionary *failures = batchResult.failures;
NSMutableArray *failuresResponse = [[NSMutableArray alloc] initWithCapacity:failures.count];
for (NSString *requestID in failures) {
GTLRErrorObject *errorObj = [failures objectForKey:requestID];
[failuresResponse addObject:errorObj.JSON];
}
resolve(@{ @"results": successResponse, @"errors": failuresResponse });
} else {
reject(@"gmail_error", @"Something went wrong, yo.", error);
}
}];
}
- (GTLRBatchQuery *)createBatchQuery:(NSArray<NSDictionary *> *)queries
{
__block GTLRBatchQuery *batch = [GTLRBatchQuery batchQuery];
[queries enumerateObjectsUsingBlock:^(NSDictionary *query, NSUInteger idx, BOOL * _Nonnull stop) {
[batch addQuery:[self createQueryFromDictionary:query]];
}];
return batch;
}
- (id)createQueryFromDictionary:(NSDictionary*)queryDict
{
NSString *type = queryDict[@"type"];
Class theClass = NSClassFromString([NSString stringWithFormat:@"GTLRGmailQuery_%@", type]);
id query = ( [type containsString:@"Trash"]
|| [type containsString:@"Untrash"]
|| [type containsString:@"Delete"]
|| [type containsString:@"Get"])
? [theClass queryWithUserId:self.signIn.currentUser.userID identifier:queryDict[@"id"]]
: [theClass queryWithUserId:self.signIn.currentUser.userID];
NSMutableDictionary *queryDictCopy = [queryDict mutableCopy];
// clean off some things we don't wanna attach
[queryDictCopy removeObjectForKey:@"type"];
[queryDictCopy removeObjectForKey:@"id"];
[query setValuesForKeysWithDictionary:queryDictCopy];
return query;
}
- (void)signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user
withError:(NSError *)error
{
if (error) {
[self.promiseWrapper reject:@"Error when revoking access." withError:error];
return;
}
self.gmail.authorizer = [[user authentication] fetcherAuthorizer];
[self.promiseWrapper resolve:(user)];
}
- (void)signIn:(GIDSignIn *)signIn didDisconnectWithUser:(GIDGoogleUser *)user
withError:(NSError *)error
{
if (error) {
[self.promiseWrapper reject:@"Error when disconnecting user." withError:error];
return;
}
[self.promiseWrapper resolve:(user)];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment