Skip to content

Commit 015baa5

Browse files
feat: setup android for onSnapshotInSync
1 parent 0cbfb7c commit 015baa5

6 files changed

Lines changed: 125 additions & 56 deletions

File tree

packages/firestore/android/src/main/java/io/invertase/firebase/firestore/UniversalFirebaseFirestoreModule.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,17 @@
2222
import static io.invertase.firebase.firestore.UniversalFirebaseFirestoreCommon.instanceCache;
2323

2424
import android.content.Context;
25+
import android.util.SparseArray;
26+
27+
import com.facebook.react.bridge.Arguments;
28+
import com.facebook.react.bridge.WritableMap;
2529
import com.google.android.gms.tasks.Task;
2630
import com.google.android.gms.tasks.Tasks;
2731
import com.google.firebase.firestore.FirebaseFirestore;
32+
import com.google.firebase.firestore.ListenerRegistration;
2833
import com.google.firebase.firestore.LoadBundleTask;
34+
35+
import io.invertase.firebase.common.ReactNativeFirebaseEventEmitter;
2936
import io.invertase.firebase.common.UniversalFirebaseModule;
3037
import io.invertase.firebase.common.UniversalFirebasePreferences;
3138
import java.nio.charset.StandardCharsets;
@@ -34,13 +41,52 @@
3441
import java.util.Objects;
3542

3643
public class UniversalFirebaseFirestoreModule extends UniversalFirebaseModule {
44+
private static SparseArray<ListenerRegistration> onSnapshotInSyncListeners =
45+
new SparseArray<>();
3746

3847
private static HashMap<String, String> emulatorConfigs = new HashMap<>();
3948

4049
UniversalFirebaseFirestoreModule(Context context, String serviceName) {
4150
super(context, serviceName);
4251
}
4352

53+
void addSnapshotsInSync(
54+
String appName,
55+
String databaseId,
56+
int listenerId
57+
) {
58+
59+
FirebaseFirestore firebaseFirestore = getFirestoreForApp(appName, databaseId);
60+
ListenerRegistration listenerRegistration = firebaseFirestore
61+
.addSnapshotsInSyncListener(() -> {
62+
ReactNativeFirebaseEventEmitter emitter =
63+
ReactNativeFirebaseEventEmitter.getSharedInstance();
64+
WritableMap body = Arguments.createMap();
65+
emitter.sendEvent(
66+
new ReactNativeFirebaseFirestoreEvent(
67+
ReactNativeFirebaseFirestoreEvent.SNAPSHOT_IN_SYNC_EVENT_SYNC,
68+
body,
69+
appName,
70+
databaseId,
71+
listenerId));
72+
});
73+
74+
75+
onSnapshotInSyncListeners.put(listenerId, listenerRegistration);
76+
}
77+
78+
void removeSnapshotsInSync(
79+
String appName,
80+
String databaseId,
81+
int listenerId
82+
) {
83+
ListenerRegistration listenerRegistration = onSnapshotInSyncListeners.get(listenerId);
84+
if (listenerRegistration != null) {
85+
listenerRegistration.remove();
86+
onSnapshotInSyncListeners.remove(listenerId);
87+
}
88+
}
89+
4490
Task<Void> disableNetwork(String appName, String databaseId) {
4591
return getFirestoreForApp(appName, databaseId).disableNetwork();
4692
}

packages/firestore/android/src/reactnative/java/io/invertase/firebase/firestore/ReactNativeFirebaseFirestoreEvent.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class ReactNativeFirebaseFirestoreEvent implements NativeEvent {
2626
static final String COLLECTION_EVENT_SYNC = "firestore_collection_sync_event";
2727
static final String DOCUMENT_EVENT_SYNC = "firestore_document_sync_event";
2828
static final String TRANSACTION_EVENT_SYNC = "firestore_transaction_event";
29+
static final String SNAPSHOT_IN_SYNC_EVENT_SYNC = "firestore_snapshots_in_sync_event";
2930
private static final String KEY_ID = "listenerId";
3031
private static final String KEY_BODY = "body";
3132
private static final String KEY_APP_NAME = "appName";

packages/firestore/android/src/reactnative/java/io/invertase/firebase/firestore/ReactNativeFirebaseFirestoreModule.java

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import static io.invertase.firebase.firestore.ReactNativeFirebaseFirestoreCommon.rejectPromiseFirestoreException;
2222
import static io.invertase.firebase.firestore.UniversalFirebaseFirestoreCommon.createFirestoreKey;
2323
import static io.invertase.firebase.firestore.UniversalFirebaseFirestoreCommon.getFirestoreForApp;
24-
import static io.invertase.firebase.firestore.UniversalFirebaseFirestoreCommon.getQueryForFirestore;
2524

2625
import com.facebook.react.bridge.Arguments;
2726
import com.facebook.react.bridge.Promise;
@@ -30,8 +29,10 @@
3029
import com.facebook.react.bridge.ReadableMap;
3130
import com.facebook.react.bridge.WritableMap;
3231
import com.google.firebase.firestore.FirebaseFirestore;
32+
import com.google.firebase.firestore.ListenerRegistration;
3333
import com.google.firebase.firestore.LoadBundleTaskProgress;
3434
import com.google.firebase.firestore.PersistentCacheIndexManager;
35+
3536
import io.invertase.firebase.common.ReactNativeFirebaseModule;
3637

3738
public class ReactNativeFirebaseFirestoreModule extends ReactNativeFirebaseModule {
@@ -195,62 +196,25 @@ public void persistenceCacheIndexManager(
195196
}
196197

197198
@ReactMethod
198-
public void snapshotsInSyncListener(
199+
public void addSnapshotsInSync(
199200
String appName,
200201
String databaseId,
201-
int listenerId
202+
int listenerId,
203+
Promise promise
202204
) {
203-
FirebaseFirestore firebaseFirestore = getFirestoreForApp(appName, databaseId);
204-
ReactNativeFirebaseFirestoreQuery firestoreQuery =
205-
new ReactNativeFirebaseFirestoreQuery(
206-
appName,
207-
databaseId,
208-
getQueryForFirestore(firebaseFirestore)
209-
);
210-
211-
handleSnapshotsInSync(appName, databaseId);
205+
module.addSnapshotsInSync(appName, databaseId, listenerId);
206+
promise.resolve(null);
212207
}
213208

214209
@ReactMethod
215-
public void onSnapshotsInSync(String appName, String databaseId, Promise promise) {
216-
ListenerRegistration registration = FirebaseFirestore.getInstance()
217-
.addSnapshotsInSyncListener(() -> {
218-
WritableMap result = Arguments.createMap();
219-
getReactApplicationContext()
220-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
221-
.emit("firestore_onSnapshotsInSync", result);
222-
});
223-
210+
public void removeSnapshotsInSync(String appName,
211+
String databaseId,
212+
int listenerId,
213+
Promise promise){
214+
module.removeSnapshotsInSync(appName, databaseId, listenerId);
224215
promise.resolve(null);
225216
}
226217

227-
private void handleSnapshotsInSync(
228-
ReactNativeFirebaseFirestoreQuery firestoreQuery,
229-
String appName,
230-
String databaseId,
231-
int listenerId
232-
) {
233-
234-
final EventListener<QuerySnapshot> listener =
235-
(querySnapshot, exception) -> {
236-
if (exception != null) {
237-
ListenerRegistration listenerRegistration = collectionSnapshotListeners.get(listenerId);
238-
if (listenerRegistration != null) {
239-
listenerRegistration.remove();
240-
collectionSnapshotListeners.remove(listenerId);
241-
}
242-
sendOnSnapshotError(appName, databaseId, listenerId, exception);
243-
} else {
244-
sendOnSnapshotEvent(appName, databaseId, listenerId, querySnapshot, metadataChanges);
245-
}
246-
};
247-
248-
ListenerRegistration listenerRegistration =
249-
firestoreQuery.query.addSnapshotListener(metadataChanges, listener);
250-
251-
collectionSnapshotListeners.put(listenerId, listenerRegistration);
252-
}
253-
254218
private WritableMap taskProgressToWritableMap(LoadBundleTaskProgress progress) {
255219
WritableMap writableMap = Arguments.createMap();
256220
writableMap.putDouble("bytesLoaded", progress.getBytesLoaded());

packages/firestore/lib/index.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,17 +190,9 @@ class FirebaseFirestoreModule extends FirebaseModule {
190190
};
191191

192192
this.firestore.native.snapshotsInSyncListener(listenerId);
193-
194193
return unsubscribe;
195194
}
196195

197-
async onSnapshotsInSync(firestore, callback) {
198-
this.native.onSnapshotsInSync(firestore, callback, MODULAR_DEPRECATION_ARG);
199-
return () => {
200-
firestoreEmitter.removeListener('onSnapshotsInSync', callback);
201-
};
202-
}
203-
204196
useEmulator(host, port) {
205197
if (!host || !isString(host) || !port || !isNumber(port)) {
206198
throw new Error('firebase.firestore().useEmulator() takes a non-empty host and port');

packages/firestore/lib/modular/index.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,24 @@ export function collectionGroup(firestore, collectionId) {
8989
return firestore.collectionGroup.call(firestore, collectionId, MODULAR_DEPRECATION_ARG);
9090
}
9191

92+
let _id_SnapshotInSync = 0;
93+
94+
export function onSnapshotsInSync(firestore, callback) {
95+
const listenerId = _id_SnapshotInSync++;
96+
firestore.native.addSnapshotsInSync(listenerId);
97+
const onSnapshotsInSyncSubscription = firestore.emitter.addListener(
98+
firestore.eventNameForApp(`firestore_snapshots_in_sync_event:${listenerId}`),
99+
() => {
100+
callback();
101+
},
102+
);
103+
104+
return () => {
105+
onSnapshotsInSyncSubscription.remove();
106+
firestore.native.removeSnapshotsInSync(listenerId);
107+
};
108+
}
109+
92110
/**
93111
* @param {DocumentReference} reference
94112
* @param {import('.').PartialWithFieldValue} data
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React, { useEffect } from 'react';
2+
import { AppRegistry, Button, Text, View } from 'react-native';
3+
4+
import '@react-native-firebase/app';
5+
import firestore, { onSnapshotsInSync } from '@react-native-firebase/firestore';
6+
7+
const fire = firestore();
8+
function App() {
9+
let unsubscribe;
10+
useEffect(() => {
11+
unsubscribe = onSnapshotsInSync(fire, () => {
12+
console.log('onSnapshotsInSync');
13+
});
14+
}, []);
15+
16+
async function addDocument() {
17+
await firestore().collection('flutter-tests').doc('one').set({ foo: 'bar' });
18+
}
19+
20+
return (
21+
<View>
22+
<Text>React Native Firebase</Text>
23+
<Text>onSnapshotsInSync API</Text>
24+
<Button
25+
title="add document"
26+
onPress={async () => {
27+
try {
28+
addDocument();
29+
} catch (e) {
30+
console.log('EEEE', e);
31+
}
32+
}}
33+
/>
34+
<Button
35+
title="unsubscribe to snapshot in sync"
36+
onPress={async () => {
37+
try {
38+
unsubscribe();
39+
} catch (e) {
40+
console.log('EEEE', e);
41+
}
42+
}}
43+
/>
44+
</View>
45+
);
46+
}
47+
48+
AppRegistry.registerComponent('testing', () => App);

0 commit comments

Comments
 (0)