@@ -364,6 +364,7 @@ - (id) init
364364 self = [super init ];
365365 if (self != nil ) {
366366 _dbReferences = [[NSMutableDictionary alloc ] init ];
367+ _transactions = [[NSMutableDictionary alloc ] init ];
367368 }
368369 return self;
369370}
@@ -455,7 +456,58 @@ - (id) init
455456 }
456457}
457458
459+ RCT_EXPORT_METHOD (beginTransaction:(NSString *) path
460+ withIdentifier:(NSString *) identifier
461+ applyLocally:(BOOL ) applyLocally
462+ onComplete:(RCTResponseSenderBlock) onComplete)
463+ {
464+ NSMutableDictionary *transactionState = [NSMutableDictionary new ];
465+ [_transactions setValue: transactionState forKey: identifier];
466+ dispatch_semaphore_t sema = dispatch_semaphore_create (0 );
467+ [transactionState setObject: sema forKey: @" semaphore" ];
468+
469+ FIRDatabaseReference *ref = [self getPathRef: path];
470+ dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
471+ [ref runTransactionBlock: ^FIRTransactionResult * _Nonnull (FIRMutableData * _Nonnull currentData) {
472+ [self sendEventWithName: DATABASE_TRANSACTION_EVENT
473+ body: @{
474+ @" id" : identifier,
475+ @" originalValue" : currentData.value
476+ }];
477+ // Wait for the event handler to call tryCommitTransaction
478+ dispatch_semaphore_wait (sema, DISPATCH_TIME_FOREVER);
479+ BOOL abort = [transactionState valueForKey: @" abort" ];
480+ id value = [transactionState valueForKey: @" value" ];
481+ [_transactions removeObjectForKey: identifier];
482+ if (abort) {
483+ return [FIRTransactionResult abort ];
484+ } else {
485+ currentData.value = value;
486+ return [FIRTransactionResult successWithValue: currentData];
487+ }
488+ } andCompletionBlock: ^(NSError * _Nullable error, BOOL committed, FIRDataSnapshot * _Nullable snapshot) {
489+ [self handleCallback: @" transaction" callback: onComplete databaseError: error];
490+ } withLocalEvents: applyLocally];
491+ });
492+ }
458493
494+ RCT_EXPORT_METHOD (tryCommitTransaction:(NSString *) identifier
495+ withData:(NSDictionary *) data
496+ orAbort:(BOOL ) abort)
497+ {
498+ NSMutableDictionary *transactionState = [_transactions valueForKey: identifier];
499+ if (!transactionState) {
500+ NSLog (@" tryCommitTransaction for unknown ID %@ " , identifier);
501+ }
502+ dispatch_semaphore_t sema = [transactionState valueForKey: @" semaphore" ];
503+ if (abort) {
504+ [transactionState setValue: @true forKey: @" abort" ];
505+ } else {
506+ id newValue = [data valueForKey: @" value" ];
507+ [transactionState setValue: newValue forKey: @" value" ];
508+ }
509+ dispatch_semaphore_signal (sema);
510+ }
459511
460512RCT_EXPORT_METHOD (on:(NSString *) path
461513 modifiersString:(NSString *) modifiersString
@@ -610,7 +662,7 @@ - (NSString *) getDBListenerKey:(NSString *) path
610662
611663// Not sure how to get away from this... yet
612664- (NSArray <NSString *> *)supportedEvents {
613- return @[DATABASE_DATA_EVENT, DATABASE_ERROR_EVENT];
665+ return @[DATABASE_DATA_EVENT, DATABASE_ERROR_EVENT, DATABASE_TRANSACTION_EVENT ];
614666}
615667
616668
0 commit comments