1818#import < Firebase/Firebase.h>
1919#import < React/RCTUtils.h>
2020
21- #import " RNFBApp/RNFBSharedUtils.h"
2221#import " RNFBFunctionsModule.h"
22+
23+ #import " RNFBApp/RNFBSharedUtils.h"
2324#import < RNFBApp/RNFBRCTEventEmitter.h>
2425
2526@implementation RNFBFunctionsModule
@@ -117,8 +118,8 @@ @implementation RNFBFunctionsModule
117118 NSString *projectId = firebaseApp.options .projectID ?: @" " ;
118119 NSString *urlString;
119120 if (host != nil && port != nil ) {
120- urlString = [NSString stringWithFormat: @" http:// %@ : %@ / %@ / %@ / %@ " ,
121- host, port, projectId, customUrlOrRegion, name];
121+ urlString = [NSString
122+ stringWithFormat: @" http:// %@ : %@ / %@ / %@ / %@ " , host, port, projectId, customUrlOrRegion, name];
122123 } else {
123124 urlString = [NSString stringWithFormat: @" https://%@ -%@ .cloudfunctions.net/%@ " ,
124125 customUrlOrRegion, projectId, name];
@@ -150,60 +151,64 @@ @implementation RNFBFunctionsModule
150151 config.URLCache = nil ;
151152 NSURLSession *session = [NSURLSession sessionWithConfiguration: config];
152153
153- NSURLSessionDataTask *task =
154- [session dataTaskWithRequest: request
155- completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) {
156- if (error) {
157- NSMutableDictionary *body = [@{@" error" : error.localizedDescription ?: @" error" } mutableCopy];
158- [RNFBSharedUtils sendJSEventForApp: firebaseApp
159- name: RNFB_FUNCTIONS_STREAMING_EVENT
160- body: @{
161- @" listenerId" : listenerId,
162- @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
163- @" body" : body
164- }];
165- } else if ([response isKindOfClass: [NSHTTPURLResponse class ]] &&
166- [(NSHTTPURLResponse *)response statusCode ] >= 400 ) {
167- NSHTTPURLResponse *http = (NSHTTPURLResponse *)response;
168- NSString *msg = [NSString stringWithFormat: @" http_error_%ld _%@ " ,
169- (long )http.statusCode,
170- [NSHTTPURLResponse localizedStringForStatusCode: http.statusCode]];
171- NSMutableDictionary *body = [@{@" error" : msg} mutableCopy];
172- [RNFBSharedUtils sendJSEventForApp: firebaseApp
173- name: RNFB_FUNCTIONS_STREAMING_EVENT
174- body: @{
175- @" listenerId" : listenerId,
176- @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
177- @" body" : body
178- }];
179- } else if (data.length > 0 ) {
180- NSString *payload = [[NSString alloc ] initWithData: data encoding: NSUTF8StringEncoding];
181- // Split into lines (handles SSE or NDJSON)
182- [payload enumerateLinesUsingBlock: ^(NSString *line, BOOL *stop) {
183- if (line.length == 0 ) return ;
184- NSString *trimmed = [line hasPrefix: @" data: " ] ? [line substringFromIndex: 6 ] : line;
185- NSMutableDictionary *body = [@{@" text" : trimmed} mutableCopy];
186- [RNFBSharedUtils sendJSEventForApp: firebaseApp
187- name: RNFB_FUNCTIONS_STREAMING_EVENT
188- body: @{
189- @" listenerId" : listenerId,
190- @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
191- @" body" : body
192- }];
193- }];
194- }
195- // Always emit done at end
196- [RNFBSharedUtils sendJSEventForApp: firebaseApp
197- name: RNFB_FUNCTIONS_STREAMING_EVENT
198- body: @{
199- @" listenerId" : listenerId,
200- @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
201- @" body" : @{@" done" : @YES }
202- }];
203- @synchronized (httpsCallableStreamListeners) {
204- [httpsCallableStreamListeners removeObjectForKey: listenerId];
205- }
206- }];
154+ NSURLSessionDataTask *task = [session
155+ dataTaskWithRequest: request
156+ completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) {
157+ if (error) {
158+ NSMutableDictionary *body =
159+ [@{@" error" : error.localizedDescription ?: @" error" } mutableCopy];
160+ [RNFBSharedUtils
161+ sendJSEventForApp: firebaseApp
162+ name: RNFB_FUNCTIONS_STREAMING_EVENT
163+ body: @{
164+ @" listenerId" : listenerId,
165+ @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
166+ @" body" : body
167+ }];
168+ } else if ([response isKindOfClass: [NSHTTPURLResponse class ]] &&
169+ [(NSHTTPURLResponse *)response statusCode ] >= 400 ) {
170+ NSHTTPURLResponse *http = (NSHTTPURLResponse *)response;
171+ NSString *msg = [NSString
172+ stringWithFormat: @" http_error_%ld _%@ " , (long )http.statusCode,
173+ [NSHTTPURLResponse localizedStringForStatusCode: http.statusCode]];
174+ NSMutableDictionary *body = [@{@" error" : msg} mutableCopy];
175+ [RNFBSharedUtils
176+ sendJSEventForApp: firebaseApp
177+ name: RNFB_FUNCTIONS_STREAMING_EVENT
178+ body: @{
179+ @" listenerId" : listenerId,
180+ @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
181+ @" body" : body
182+ }];
183+ } else if (data.length > 0 ) {
184+ NSString *payload = [[NSString alloc ] initWithData: data encoding: NSUTF8StringEncoding];
185+ // Split into lines (handles SSE or NDJSON)
186+ [payload enumerateLinesUsingBlock: ^(NSString *line, BOOL *stop) {
187+ if (line.length == 0 )
188+ return ;
189+ NSString *trimmed = [line hasPrefix: @" data: " ] ? [line substringFromIndex: 6 ] : line;
190+ NSMutableDictionary *body = [@{@" text" : trimmed} mutableCopy];
191+ [RNFBSharedUtils sendJSEventForApp: firebaseApp
192+ name: RNFB_FUNCTIONS_STREAMING_EVENT
193+ body: @{
194+ @" listenerId" : listenerId,
195+ @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
196+ @" body" : body
197+ }];
198+ }];
199+ }
200+ // Always emit done at end
201+ [RNFBSharedUtils sendJSEventForApp: firebaseApp
202+ name: RNFB_FUNCTIONS_STREAMING_EVENT
203+ body: @{
204+ @" listenerId" : listenerId,
205+ @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
206+ @" body" : @{@" done" : @YES }
207+ }];
208+ @synchronized (httpsCallableStreamListeners) {
209+ [httpsCallableStreamListeners removeObjectForKey: listenerId];
210+ }
211+ }];
207212
208213 @synchronized (httpsCallableStreamListeners) {
209214 httpsCallableStreamListeners[listenerId] = task;
@@ -229,7 +234,7 @@ @implementation RNFBFunctionsModule
229234 if (!httpsCallableStreamListeners) {
230235 httpsCallableStreamListeners = [NSMutableDictionary dictionary ];
231236 }
232-
237+
233238 // Use the provided URL directly
234239 NSURLComponents *components = [NSURLComponents componentsWithString: url];
235240 if (components == nil ) {
@@ -243,14 +248,14 @@ @implementation RNFBFunctionsModule
243248 }];
244249 return ;
245250 }
246-
251+
247252 // Override to emulator if provided
248253 if (host != nil && port != nil ) {
249254 components.scheme = @" http" ;
250255 components.host = host;
251256 components.port = port;
252257 }
253-
258+
254259 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: [components URL ]];
255260 [request setHTTPMethod: @" GET" ];
256261 [request setValue: @" text/event-stream, application/x-ndjson, */*" forHTTPHeaderField: @" Accept" ];
@@ -260,60 +265,64 @@ @implementation RNFBFunctionsModule
260265 config.URLCache = nil ;
261266 NSURLSession *session = [NSURLSession sessionWithConfiguration: config];
262267
263- NSURLSessionDataTask *task =
264- [session dataTaskWithRequest: request
265- completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) {
266- if (error) {
267- NSMutableDictionary *body = [@{@" error" : error.localizedDescription ?: @" error" } mutableCopy];
268- [RNFBSharedUtils sendJSEventForApp: firebaseApp
269- name: RNFB_FUNCTIONS_STREAMING_EVENT
270- body: @{
271- @" listenerId" : listenerId,
272- @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
273- @" body" : body
274- }];
275- } else if ([response isKindOfClass: [NSHTTPURLResponse class ]] &&
276- [(NSHTTPURLResponse *)response statusCode ] >= 400 ) {
277- NSHTTPURLResponse *http = (NSHTTPURLResponse *)response;
278- NSString *msg = [NSString stringWithFormat: @" http_error_%ld _%@ " ,
279- (long )http.statusCode,
280- [NSHTTPURLResponse localizedStringForStatusCode: http.statusCode]];
281- NSMutableDictionary *body = [@{@" error" : msg} mutableCopy];
282- [RNFBSharedUtils sendJSEventForApp: firebaseApp
283- name: RNFB_FUNCTIONS_STREAMING_EVENT
284- body: @{
285- @" listenerId" : listenerId,
286- @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
287- @" body" : body
288- }];
289- } else if (data.length > 0 ) {
290- NSString *payload = [[NSString alloc ] initWithData: data encoding: NSUTF8StringEncoding];
291- // Split into lines (handles SSE or NDJSON)
292- [payload enumerateLinesUsingBlock: ^(NSString *line, BOOL *stop) {
293- if (line.length == 0 ) return ;
294- NSString *trimmed = [line hasPrefix: @" data: " ] ? [line substringFromIndex: 6 ] : line;
295- NSMutableDictionary *body = [@{@" text" : trimmed} mutableCopy];
296- [RNFBSharedUtils sendJSEventForApp: firebaseApp
297- name: RNFB_FUNCTIONS_STREAMING_EVENT
298- body: @{
299- @" listenerId" : listenerId,
300- @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
301- @" body" : body
302- }];
303- }];
304- }
305- // Always emit done at end
306- [RNFBSharedUtils sendJSEventForApp: firebaseApp
307- name: RNFB_FUNCTIONS_STREAMING_EVENT
308- body: @{
309- @" listenerId" : listenerId,
310- @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
311- @" body" : @{@" done" : @YES }
312- }];
313- @synchronized (httpsCallableStreamListeners) {
314- [httpsCallableStreamListeners removeObjectForKey: listenerId];
315- }
316- }];
268+ NSURLSessionDataTask *task = [session
269+ dataTaskWithRequest: request
270+ completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) {
271+ if (error) {
272+ NSMutableDictionary *body =
273+ [@{@" error" : error.localizedDescription ?: @" error" } mutableCopy];
274+ [RNFBSharedUtils
275+ sendJSEventForApp: firebaseApp
276+ name: RNFB_FUNCTIONS_STREAMING_EVENT
277+ body: @{
278+ @" listenerId" : listenerId,
279+ @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
280+ @" body" : body
281+ }];
282+ } else if ([response isKindOfClass: [NSHTTPURLResponse class ]] &&
283+ [(NSHTTPURLResponse *)response statusCode ] >= 400 ) {
284+ NSHTTPURLResponse *http = (NSHTTPURLResponse *)response;
285+ NSString *msg = [NSString
286+ stringWithFormat: @" http_error_%ld _%@ " , (long )http.statusCode,
287+ [NSHTTPURLResponse localizedStringForStatusCode: http.statusCode]];
288+ NSMutableDictionary *body = [@{@" error" : msg} mutableCopy];
289+ [RNFBSharedUtils
290+ sendJSEventForApp: firebaseApp
291+ name: RNFB_FUNCTIONS_STREAMING_EVENT
292+ body: @{
293+ @" listenerId" : listenerId,
294+ @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
295+ @" body" : body
296+ }];
297+ } else if (data.length > 0 ) {
298+ NSString *payload = [[NSString alloc ] initWithData: data encoding: NSUTF8StringEncoding];
299+ // Split into lines (handles SSE or NDJSON)
300+ [payload enumerateLinesUsingBlock: ^(NSString *line, BOOL *stop) {
301+ if (line.length == 0 )
302+ return ;
303+ NSString *trimmed = [line hasPrefix: @" data: " ] ? [line substringFromIndex: 6 ] : line;
304+ NSMutableDictionary *body = [@{@" text" : trimmed} mutableCopy];
305+ [RNFBSharedUtils sendJSEventForApp: firebaseApp
306+ name: RNFB_FUNCTIONS_STREAMING_EVENT
307+ body: @{
308+ @" listenerId" : listenerId,
309+ @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
310+ @" body" : body
311+ }];
312+ }];
313+ }
314+ // Always emit done at end
315+ [RNFBSharedUtils sendJSEventForApp: firebaseApp
316+ name: RNFB_FUNCTIONS_STREAMING_EVENT
317+ body: @{
318+ @" listenerId" : listenerId,
319+ @" eventName" : RNFB_FUNCTIONS_STREAMING_EVENT,
320+ @" body" : @{@" done" : @YES }
321+ }];
322+ @synchronized (httpsCallableStreamListeners) {
323+ [httpsCallableStreamListeners removeObjectForKey: listenerId];
324+ }
325+ }];
317326
318327 @synchronized (httpsCallableStreamListeners) {
319328 httpsCallableStreamListeners[listenerId] = task;
0 commit comments