Skip to content

Commit ddf0695

Browse files
committed
Updates for off and storing handles
1 parent b732357 commit ddf0695

File tree

5 files changed

+152
-39
lines changed

5 files changed

+152
-39
lines changed

ios/Firestack/FirestackDatabase.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
}
1818

19+
@property (nonatomic) NSArray *_DBHandles;
1920
@property (nonatomic, weak) FIRDatabaseReference *ref;
2021

2122
@end

ios/Firestack/FirestackDatabase.m

Lines changed: 109 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ @implementation FirestackDatabase
1515

1616
RCT_EXPORT_MODULE(FirestackDatabase);
1717

18-
RCT_EXPORT_METHOD(onDBEvent:(NSString *) path
18+
RCT_EXPORT_METHOD(on:(NSString *) path
1919
name:(NSString *) name
2020
callback:(RCTResponseSenderBlock) callback)
2121
{
@@ -25,20 +25,38 @@ @implementation FirestackDatabase
2525

2626
FIRDatabaseReference *ref = [self getRefAtPath:path];
2727

28-
[ref observeEventType:eventType
29-
withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
30-
callback(@[[NSNull null], [self snapshotToDict:snapshot]]);
31-
}
32-
withCancelBlock:^(NSError * _Nonnull error) {
33-
NSLog(@"Error onDBEvent: %@", [error debugDescription]);
34-
callback(@[@{
35-
@"error": @"onceError",
36-
@"msg": [error debugDescription]
37-
}]);
38-
}];
28+
FIRDatabaseHandle handle = [ref observeEventType:eventType
29+
withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
30+
NSDictionary *props =
31+
[self snapshotToDict:snapshot];
32+
33+
NSLog(@"props: %@", props);
34+
[self
35+
sendJSEvent:name
36+
props: @{
37+
@"eventName": name,
38+
@"snapshot": props
39+
}];
40+
}
41+
withCancelBlock:^(NSError * _Nonnull error) {
42+
NSLog(@"Error onDBEvent: %@", [error debugDescription]);
43+
[self
44+
sendJSEvent:DATABASE_ERROR_EVENT
45+
props: @{
46+
@"eventName": DATABASE_ERROR_EVENT,
47+
@"msg": [error debugDescription]
48+
}];
49+
}];
50+
51+
int idx = [self storeDBHandle:handle];
52+
53+
callback(@[[NSNull null], @{
54+
@"result": @"success",
55+
@"handle": @(idx)
56+
}]);
3957
}
4058

41-
RCT_EXPORT_METHOD(onDBEventOnce:(NSString *) path
59+
RCT_EXPORT_METHOD(onOnce:(NSString *) path
4260
name:(NSString *) name
4361
callback:(RCTResponseSenderBlock) callback)
4462
{
@@ -58,6 +76,34 @@ @implementation FirestackDatabase
5876
}];
5977
}
6078

79+
RCT_EXPORT_METHOD(off:(NSString *)path
80+
handleNumber:(NSInteger) handleNumber
81+
callback:(RCTResponseSenderBlock) callback)
82+
{
83+
FIRDatabaseReference *ref = [self getRefAtPath:path];
84+
85+
if (handleNumber == -1) {
86+
[ref removeAllObservers];
87+
} else {
88+
FIRDatabaseHandle handle = [[self storedDBHandles] objectAtIndex:handleNumber];
89+
if (handle != nil) {
90+
[ref removeObserverWithHandle:handle];
91+
[self removeDBHandle:handleNumber];
92+
} else {
93+
[ref removeAllObservers];
94+
}
95+
}
96+
callback(@[[NSNull null], @(true)]);
97+
}
98+
99+
RCT_EXPORT_METHOD(removeListeners:(NSString *) path
100+
callback:(RCTResponseSenderBlock) callback)
101+
{
102+
FIRDatabaseReference *ref = [self getRefAtPath:path];
103+
[ref removeAllObservers];
104+
callback(@[[NSNull null], @(true)]);
105+
}
106+
61107
// Helpers
62108
- (FIRDatabaseReference *) getRef
63109
{
@@ -74,6 +120,38 @@ - (FIRDatabaseReference *) getRefAtPath:(NSString *) str
74120
return [rootRef child:str];
75121
}
76122

123+
// Handles
124+
- (NSArray *) storedDBHandles
125+
{
126+
if (self._DBHandles == nil) {
127+
self._DBHandles = [[NSMutableArray alloc] init];
128+
}
129+
return self._DBHandles;
130+
}
131+
132+
- (int) storeDBHandle:(FIRDatabaseHandle) handle
133+
{
134+
NSMutableArray *stored = [[self storedDBHandles] mutableCopy];
135+
136+
NSNumber *handleNum = [NSNumber numberWithUnsignedLong:handle];
137+
138+
[stored addObject:handleNum];
139+
self._DBHandles = stored;
140+
141+
int handleIdx = [stored indexOfObject:handleNum];
142+
return handleIdx;
143+
}
144+
145+
- (int) removeDBHandle:(int) idx
146+
{
147+
NSMutableArray *stored = [[self storedDBHandles] mutableCopy];
148+
if ([stored objectAtIndex:idx]) {
149+
[stored removeObjectAtIndex:idx];
150+
self._DBHandles = stored;
151+
}
152+
return idx;
153+
}
154+
77155
- (NSDictionary *) snapshotToDict:(FIRDataSnapshot *) snapshot
78156
{
79157
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
@@ -93,32 +171,42 @@ - (int) eventTypeFromName:(NSString *)name
93171
{
94172
int eventType = FIRDataEventTypeValue;
95173

96-
if ([name isEqualToString:@"value"]) {
174+
if ([name isEqualToString:DATABASE_VALUE_EVENT]) {
97175
eventType = FIRDataEventTypeValue;
98-
} else if ([name isEqualToString:@"child_added"]) {
176+
} else if ([name isEqualToString:DATABASE_CHILD_ADDED_EVENT]) {
99177
eventType = FIRDataEventTypeChildAdded;
100-
} else if ([name isEqualToString:@"child_changed"]) {
178+
} else if ([name isEqualToString:DATABASE_CHILD_MODIFIED_EVENT]) {
101179
eventType = FIRDataEventTypeChildChanged;
102-
} else if ([name isEqualToString:@"child_removed"]) {
180+
} else if ([name isEqualToString:DATABASE_CHILD_REMOVED_EVENT]) {
103181
eventType = FIRDataEventTypeChildRemoved;
104-
} else if ([name isEqualToString:@"child_moved"]) {
182+
} else if ([name isEqualToString:DATABASE_CHILD_MOVED_EVENT]) {
105183
eventType = FIRDataEventTypeChildMoved;
106184
}
107185
return eventType;
108186
}
109187

188+
// Not sure how to get away from this... yet
110189
// Not sure how to get away from this... yet
111190
- (NSArray<NSString *> *)supportedEvents {
112191
return @[
113-
DATABASE_VALUE_EVENT
192+
DATABASE_VALUE_EVENT,
193+
DATABASE_CHILD_ADDED_EVENT,
194+
DATABASE_CHILD_MODIFIED_EVENT,
195+
DATABASE_CHILD_MOVED_EVENT,
196+
DATABASE_CHILD_REMOVED_EVENT
114197
];
115198
}
116199

117200
- (void) sendJSEvent:(NSString *)title
118201
props:(NSDictionary *)props
119202
{
120-
[self sendEventWithName:title
121-
body:props];
203+
@try {
204+
[self sendEventWithName:title
205+
body:props];
206+
}
207+
@catch (NSException *err) {
208+
NSLog(@"An error occurred in sendJSEvent: %@", [err debugDescription]);
209+
}
122210
}
123211

124212
@end

ios/Firestack/FirestackEvents.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,9 @@ static NSString *const AUTH_CHANGED_EVENT = @"listenForAuth";
1010
static NSString *const DEBUG_EVENT = @"debug";
1111

1212
// Database
13-
static NSString *const DATABASE_VALUE_EVENT = @"value";
13+
static NSString *const DATABASE_VALUE_EVENT = @"value";
14+
static NSString *const DATABASE_CHILD_ADDED_EVENT = @"child_added";
15+
static NSString *const DATABASE_CHILD_MODIFIED_EVENT = @"child_changed";
16+
static NSString *const DATABASE_CHILD_REMOVED_EVENT = @"child_removed";
17+
static NSString *const DATABASE_CHILD_MOVED_EVENT = @"child_moved";
18+
static NSString *const DATABASE_ERROR_EVENT = @"database_error";

lib/firestackModule.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,16 @@ export class FirestackModule {
126126

127127
unlisten() {
128128
const T = this._types;
129+
const ref = this.makeRef();
130+
129131
return new Promise((resolve, reject) => {
130-
this.firestack.off(this._ref);
131-
this._handleUpdate(T.ACTION_UNLISTEN, null, (state) => {
132-
resolve(state)
133-
})
132+
ref.off()
133+
.then((success) => {
134+
this._handleUpdate(T.ACTION_UNLISTEN, null, (state) => {
135+
resolve(state)
136+
})
137+
});
134138
})
135-
return (dispatch, getState) => {
136-
const {firestack} = getState();
137-
firestack.off(this._ref);
138-
dispatch({type: this._types.ACTION_UNLISTEN})
139-
}
140139
}
141140

142141
// TODO: Untested

lib/modules/database.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/**
22
* Database representation wrapper
33
*/
4-
import {NativeModules} from 'react-native';
4+
import {NativeModules, NativeEventEmitter} from 'react-native';
55
const FirestackDatabase = NativeModules.FirestackDatabase;
6+
const FirestackDatabaseEvt = new NativeEventEmitter(FirestackDatabase);
67

78
import promisify from '../promisify'
89
import { Base } from './base'
@@ -29,33 +30,52 @@ class DataSnapshot {
2930
}
3031
// https://firebase.google.com/docs/reference/js/firebase.database.Reference
3132
class DatabaseRef {
32-
constructor(db, ...path) {
33+
constructor(db, path) {
3334
this.db = db;
34-
this.path = path.join('/');
35+
this.path = path;
36+
37+
this.handle = -1;
3538
}
3639

3740
on(evt, cb) {
38-
return promisify('onDBEventOnce', FirestackDatabase)(this.path, evt)
39-
.then(val => {
40-
const snap = new DataSnapshot(val);
41+
this.db.on(evt, (data) => {
42+
this.db.log.debug('Got a snapshot', data.eventName, 'at', this.path);
43+
const snap = new DataSnapshot(data.snapshot);
4144
if (cb && typeof(cb) === 'function') {
4245
cb(snap);
4346
}
44-
return snap;
47+
}, FirestackDatabaseEvt);
48+
49+
return promisify('on', FirestackDatabase)(this.path, evt)
50+
.then(handle => {
51+
this.handle = handle;
52+
return handle;
4553
});
4654
}
55+
56+
off(evt) {
57+
return promisify('off', FirestackDatabase)(this.path, this.handle)
58+
.then(val => {
59+
return val;
60+
})
61+
}
4762
}
4863

4964
export class Database extends Base {
5065

5166
constructor(firestack, options={}) {
5267
super(firestack, options);
68+
this.refs = {};
5369

5470
this.log.debug('Created new Database instance', this.options);
5571
}
5672

5773
ref(...path) {
58-
return new DatabaseRef(this, path);
74+
const name = path.join('/');
75+
if (!this.refs[name]) {
76+
this.refs[name] = new DatabaseRef(this, name);
77+
}
78+
return this.refs[name];
5979
}
6080

6181
get namespace() {

0 commit comments

Comments
 (0)