From 4ba3764332ce2d7a10dff5d3d1bc42458f655997 Mon Sep 17 00:00:00 2001 From: Mitul Golakiya Date: Wed, 20 Dec 2017 13:16:42 +0530 Subject: [PATCH 01/47] listner events added + new function to read messages with order and limit --- src/Firebase.Database/Database.uno | 198 +++++++++++++++++++++++++++++ src/Firebase.Database/JS.uno | 105 ++++++++++++++- 2 files changed, 302 insertions(+), 1 deletion(-) diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index 21234e2..034065b 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -58,6 +58,174 @@ namespace Firebase.Database @{_handle:Set(FirebaseDatabase.getInstance().getReference())}; @} + [Foreign(Language.ObjC)] + extern(iOS) + public static void ListenForChildAdded(string path, int count, Action f) + @{ + NSUInteger end = (NSUInteger) count; + FIRDatabaseReference *ref = @{DatabaseService._handle:Get()}; + [[[ref child:path] queryLimitedToLast:count] observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { + if([snapshot.value isEqual:[NSNull null]]) { + f(path, nil); + return; + } + + NSError *error; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:snapshot.value + options:(NSJSONWritingOptions)0 + error:&error]; + NSString *json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + f(path, json); + } withCancelBlock:^(NSError * _Nonnull error) { + NSString *erstr = [NSString stringWithFormat:@"Firebase Read Error: %@", error.localizedDescription]; + f(path, erstr); + }]; + @} + + [Foreign(Language.Java)] + extern(Android) + public static void ListenForChildAdded(string path, int count, Action f) + @{ + + @} + + [Foreign(Language.ObjC)] + extern(iOS) + public static void ReadByQueryEndingAtValue(string path, string keyName, string lastValue, int count, Action f) + @{ + long longLastValue = [lastValue longLongValue]; + NSNumber * lastChildValue = [NSNumber numberWithLong:longLastValue]; + FIRDatabaseReference *ref = @{DatabaseService._handle:Get()}; + [[[[[ref child:path] queryOrderedByChild:keyName] queryEndingAtValue:lastChildValue] queryLimitedToLast:count] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { + if([snapshot.value isEqual:[NSNull null]]) { + f(path, nil); + return; + } + + NSError *error; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:snapshot.value + options:(NSJSONWritingOptions)0 + error:&error]; + NSString *json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + f(path, json); + } withCancelBlock:^(NSError * _Nonnull error) { + NSString *erstr = [NSString stringWithFormat:@"Firebase Read Error: %@", error.localizedDescription]; + f(path, erstr); + }]; + @} + + [Foreign(Language.Java)] + extern(Android) + public static void ReadByQueryEndingAtValue(string path, string keyName, string lastValue, int count, Action f) + @{ + + @} + + [Foreign(Language.ObjC)] + extern(iOS) + public static void ListenForChildChanged(string path, Action f) + @{ + FIRDatabaseReference *ref = @{DatabaseService._handle:Get()}; + [[ref child:path] observeEventType:FIRDataEventTypeChildChanged withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { + if([snapshot.value isEqual:[NSNull null]]) { + f(path, nil); + return; + } + + NSError *error; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:snapshot.value + options:(NSJSONWritingOptions)0 + error:&error]; + NSString *json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + f(path, json); + } withCancelBlock:^(NSError * _Nonnull error) { + NSString *erstr = [NSString stringWithFormat:@"Firebase Read Error: %@", error.localizedDescription]; + f(path, erstr); + }]; + @} + + [Foreign(Language.Java)] + extern(Android) + public static void ListenForChildChanged(string path, Action f) + @{ + + @} + + [Foreign(Language.ObjC)] + extern(iOS) + public static void ListenForChildRemoved(string path, Action f) + @{ + FIRDatabaseReference *ref = @{DatabaseService._handle:Get()}; + [[ref child:path] observeEventType:FIRDataEventTypeChildRemoved withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { + if([snapshot.value isEqual:[NSNull null]]) { + f(path, nil); + return; + } + + NSError *error; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:snapshot.value + options:(NSJSONWritingOptions)0 + error:&error]; + NSString *json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + f(path, json); + } withCancelBlock:^(NSError * _Nonnull error) { + NSString *erstr = [NSString stringWithFormat:@"Firebase Read Error: %@", error.localizedDescription]; + f(path, erstr); + }]; + @} + + [Foreign(Language.Java)] + extern(Android) + public static void ListenForChildRemoved(string path, Action f) + @{ + + @} + + [Foreign(Language.ObjC)] + extern(iOS) + public static void ListenForChildMoved(string path, Action f) + @{ + FIRDatabaseReference *ref = @{DatabaseService._handle:Get()}; + [[ref child:path] observeEventType:FIRDataEventTypeChildMoved withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { + if([snapshot.value isEqual:[NSNull null]]) { + f(path, nil); + return; + } + + NSError *error; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:snapshot.value + options:(NSJSONWritingOptions)0 + error:&error]; + NSString *json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + f(path, json); + } withCancelBlock:^(NSError * _Nonnull error) { + NSString *erstr = [NSString stringWithFormat:@"Firebase Read Error: %@", error.localizedDescription]; + f(path, erstr); + }]; + @} + + [Foreign(Language.Java)] + extern(Android) + public static void ListenForChildMoved(string path, Action f) + @{ + + @} + + [Foreign(Language.ObjC)] + extern(iOS) + public static void DetachListeners(string path) + @{ + FIRDatabaseReference *ref = @{DatabaseService._handle:Get()}; + [[ref child:path] removeAllObservers]; + @} + + [Foreign(Language.Java)] + extern(Android) + public static void DetachListeners(string path) + @{ + + @} + [Foreign(Language.ObjC)] extern(iOS) public static void Listen(string path, Action f) @@ -263,6 +431,36 @@ namespace Firebase.Database { debug_log "Listen not implemented for desktop"; } + + public static void ReadByQueryEndingAtValue(string path, string keyName, string lastValue, int count, Action f) + { + debug_log "ReadByQueryEndingAtValue not implemented for desktop"; + } + + public static void ListenForChildAdded(string path, int count, Action f) + { + debug_log "ListenForChildAdded not implemented for desktop"; + } + + public static void ListenForChildChanged(string path, Action f) + { + debug_log "ListenForChildChanged not implemented for desktop"; + } + + public static void ListenForChildRemoved(string path, Action f) + { + debug_log "ListenForChildRemoved not implemented for desktop"; + } + + public static void ListenForChildMoved(string path, Action f) + { + debug_log "ListenForChildMoved not implemented for desktop"; + } + + public static void DetachListeners(string path) + { + debug_log "DetachListeners not implemented for desktop"; + } } extern(!mobile) diff --git a/src/Firebase.Database/JS.uno b/src/Firebase.Database/JS.uno index 82ecf73..816a82e 100644 --- a/src/Firebase.Database/JS.uno +++ b/src/Firebase.Database/JS.uno @@ -19,7 +19,7 @@ namespace Firebase.Database.JS { static readonly DatabaseModule _instance; - public DatabaseModule() : base(false,"data") + public DatabaseModule() : base(false,"data", "dataAdded", "dataChanged", "dataRemoved", "dataMoved", "readByQueryEndingAtValue") { if(_instance != null) return; Uno.UX.Resource.SetGlobalKey(_instance = this, "Firebase/Database"); @@ -28,8 +28,34 @@ namespace Firebase.Database.JS var onData = new NativeEvent("onData"); On("data", onData); + var onDataAdded = new NativeEvent("onDataAdded"); + On("dataAdded", onDataAdded); + + var onDataChanged = new NativeEvent("onDataChanged"); + On("dataChanged", onDataChanged); + + var onDataRemoved = new NativeEvent("onDataRemoved"); + On("dataRemoved", onDataRemoved); + + var onDataMoved = new NativeEvent("onDataMoved"); + On("dataMoved", onDataMoved); + + var onReadByQueryEndingAtValue = new NativeEvent("onReadByQueryEndingAtValue"); + On("readByQueryEndingAtValue", onReadByQueryEndingAtValue); + AddMember(onData); + AddMember(onDataAdded); + AddMember(onDataChanged); + AddMember(onDataRemoved); + AddMember(onDataMoved); + AddMember(onReadByQueryEndingAtValue); AddMember(new NativeFunction("listen", (NativeCallback)Listen)); + AddMember(new NativeFunction("listenOnAdded", (NativeCallback)ListenForChildAdded)); + AddMember(new NativeFunction("listenOnChanged", (NativeCallback)ListenForChildChanged)); + AddMember(new NativeFunction("listenOnRemoved", (NativeCallback)ListenForChildRemoved)); + AddMember(new NativeFunction("listenOnMoved", (NativeCallback)ListenForChildMoved)); + AddMember(new NativeFunction("readByQueryEndingAtValue", (NativeCallback)ReadByQueryEndingAtValue)); + AddMember(new NativeFunction("detachListeners", (NativeCallback)DetachListeners)); AddMember(new NativePromise("read", Read, null)); AddMember(new NativeFunction("push", (NativeCallback)Push)); AddMember(new NativeFunction("save", (NativeCallback)Save)); @@ -162,6 +188,31 @@ namespace Firebase.Database.JS Emit("data", path, msg); } + void ListenAddedCallback (string path, string msg) + { + Emit("dataAdded", path, msg); + } + + void ListenChangedCallback (string path, string msg) + { + Emit("dataChanged", path, msg); + } + + void ListenRemovedCallback (string path, string msg) + { + Emit("dataRemoved", path, msg); + } + + void ListenMovedCallback (string path, string msg) + { + Emit("dataMoved", path, msg); + } + + void ListenReadByQueryEndingAtValueCallback (string path, string msg) + { + Emit("readByQueryEndingAtValue", path, msg); + } + object Listen(Fuse.Scripting.Context context, object[] args) { debug_log "listen"; @@ -169,5 +220,57 @@ namespace Firebase.Database.JS DatabaseService.Listen(path, ListenCallback); return null; } + + object ListenForChildAdded(Fuse.Scripting.Context context, object[] args) + { + debug_log "ListenForChildAdded"; + var path = args[0].ToString(); + int count = Marshal.ToInt(args[1]); + DatabaseService.ListenForChildAdded(path,count, ListenAddedCallback); + return null; + } + + object ListenForChildChanged(Fuse.Scripting.Context context, object[] args) + { + debug_log "ListenForChildChanged"; + var path = args[0].ToString(); + DatabaseService.ListenForChildChanged(path, ListenChangedCallback); + return null; + } + + object ListenForChildRemoved(Fuse.Scripting.Context context, object[] args) + { + debug_log "ListenForChildRemoved"; + var path = args[0].ToString(); + DatabaseService.ListenForChildRemoved(path, ListenRemovedCallback); + return null; + } + + object ListenForChildMoved(Fuse.Scripting.Context context, object[] args) + { + debug_log "ListenForChildMoved"; + var path = args[0].ToString(); + DatabaseService.ListenForChildMoved(path, ListenMovedCallback); + return null; + } + + object ReadByQueryEndingAtValue(Fuse.Scripting.Context context, object[] args) + { + debug_log "ReadByQueryEndingAtValue"; + var path = args[0].ToString(); + var keyName = args[1].ToString(); + var lastValue = args[2].ToString(); + int count = Marshal.ToInt(args[3]); + DatabaseService.ReadByQueryEndingAtValue(path,keyName,lastValue, count, ListenReadByQueryEndingAtValueCallback); + return null; + } + + object DetachListeners(Fuse.Scripting.Context context, object[] args) + { + debug_log "DetachListeners"; + var path = args[0].ToString(); + DatabaseService.DetachListeners(path); + return null; + } } } From 31a8c6a85328b27a2f3b7317ff24a32bcf27fd7d Mon Sep 17 00:00:00 2001 From: Mitul Golakiya Date: Wed, 20 Dec 2017 16:12:13 +0530 Subject: [PATCH 02/47] push with timestamp function added --- src/Firebase.Database/Database.uno | 23 +++++++++++++++++++++++ src/Firebase.Database/JS.uno | 29 +++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index 034065b..3466cee 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -312,6 +312,24 @@ namespace Firebase.Database ref.child(path).setValue(values); @} + [Foreign(Language.ObjC)] + extern(iOS) + public static void SaveWithTimestamp(string path, ObjC.Object value) + @{ + FIRDatabaseReference *ref = @{DatabaseService._handle:Get()}; + NSMutableDictionary *messageDic = [[NSMutableDictionary alloc] initWithDictionary:value]; + [messageDic setValue:[FIRServerValue timestamp] forKey:@"timestamp"]; + [[ref child:path] setValue:messageDic]; + @} + + [Foreign(Language.Java)] + extern(Android) + public static void SaveWithTimestamp(string path, Java.Object value) + @{ + DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; + ref.child(path).setValue(value); + @} + [Foreign(Language.ObjC)] extern(iOS) public static void Save(string path, ObjC.Object value) @@ -427,6 +445,11 @@ namespace Firebase.Database Save(); } + public static void SaveWithTimestamp(string path, Object value) + { + Save(); + } + public static void Listen(string path, Action f) { debug_log "Listen not implemented for desktop"; diff --git a/src/Firebase.Database/JS.uno b/src/Firebase.Database/JS.uno index 816a82e..5731142 100644 --- a/src/Firebase.Database/JS.uno +++ b/src/Firebase.Database/JS.uno @@ -58,6 +58,7 @@ namespace Firebase.Database.JS AddMember(new NativeFunction("detachListeners", (NativeCallback)DetachListeners)); AddMember(new NativePromise("read", Read, null)); AddMember(new NativeFunction("push", (NativeCallback)Push)); + AddMember(new NativeFunction("pushWithTimestamp", (NativeCallback)PushWithTimestamp)); AddMember(new NativeFunction("save", (NativeCallback)Save)); AddMember(new NativeFunction("delete", (NativeCallback)Delete)); } @@ -151,6 +152,34 @@ namespace Firebase.Database.JS return push_path; } + static object PushWithTimestamp(Fuse.Scripting.Context context, object[] args) + { + var path = args[0].ToString(); + var push_path = DatabaseService.NewChildId(path); + if defined(iOS) + { + DatabaseService.SaveWithTimestamp( + path + "/" + push_path, + JSON.ObjCObject.FromJSON(JSON.ScriptingValue.ToJSON(args[1])) + ); + } + else if defined(Android) + { + DatabaseService.SaveWithTimestamp( + path + "/" + push_path, + JSON.JavaObject.FromJSON(JSON.ScriptingValue.ToJSON(args[1])) + ); + } + else + { + DoSave( + path + "/" + push_path, + args[1] + ); + } + return push_path; + } + static object Save(Fuse.Scripting.Context context, object[] args) { if defined(iOS) From af769c078fc3477fd48b0500296f0a7e497566d4 Mon Sep 17 00:00:00 2001 From: Mitul Golakiya Date: Fri, 22 Dec 2017 16:15:40 +0530 Subject: [PATCH 03/47] Event listners + timestamp in android --- src/Firebase.Database/Database.uno | 163 ++++++++++++++++++++++++++++- 1 file changed, 162 insertions(+), 1 deletion(-) diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index 3466cee..ebbd124 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -18,6 +18,10 @@ namespace Firebase.Database "com.google.firebase.database.DataSnapshot", "com.google.firebase.database.FirebaseDatabase", "com.google.firebase.database.ValueEventListener", + "com.google.firebase.database.ChildEventListener", + "com.google.firebase.database.Query", + "com.google.firebase.database.ServerValue", + "android.util.Log", "org.json.JSONObject", "java.util.Map", "java.util.HashMap")] @@ -86,7 +90,39 @@ namespace Firebase.Database extern(Android) public static void ListenForChildAdded(string path, int count, Action f) @{ + ChildEventListener childEventListener = new ChildEventListener() { + @Override + public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { + if (dataSnapshot.getValue() == null) { + return; + } + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } + + @Override + public void onChildChanged(DataSnapshot dataSnapshot, String s) { + + } + + @Override + public void onChildRemoved(DataSnapshot dataSnapshot) { + + } + + @Override + public void onChildMoved(DataSnapshot dataSnapshot, String s) { + + } + @Override + public void onCancelled(DatabaseError databaseError) { + f.run(path,databaseError.toString()); + } + }; + DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; + Query lastAddedQuery = ref.child(path).limitToLast(count); + lastAddedQuery.addChildEventListener(childEventListener); @} [Foreign(Language.ObjC)] @@ -118,7 +154,28 @@ namespace Firebase.Database extern(Android) public static void ReadByQueryEndingAtValue(string path, string keyName, string lastValue, int count, Action f) @{ + ValueEventListener dataListener = new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) + { + if (dataSnapshot.getValue() == null) { + return; + } + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } + @Override + public void onCancelled(DatabaseError databaseError) + { + f.run(path,databaseError.toString()); + } + }; + + long longLastValue = Long.parseLong(lastValue); + DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; + Query readQuery = ref.child(path).orderByChild(keyName).endAt(longLastValue).limitToLast(count); + readQuery.addValueEventListener(dataListener); @} [Foreign(Language.ObjC)] @@ -148,7 +205,38 @@ namespace Firebase.Database extern(Android) public static void ListenForChildChanged(string path, Action f) @{ + ChildEventListener childEventListener = new ChildEventListener() { + @Override + public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { + + } + + @Override + public void onChildChanged(DataSnapshot dataSnapshot, String s) { + if (dataSnapshot.getValue() == null) { + return; + } + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } + + @Override + public void onChildRemoved(DataSnapshot dataSnapshot) { + + } + + @Override + public void onChildMoved(DataSnapshot dataSnapshot, String s) { + + } + @Override + public void onCancelled(DatabaseError databaseError) { + f.run(path,databaseError.toString()); + } + }; + DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; + ref.child(path).addChildEventListener(childEventListener); @} [Foreign(Language.ObjC)] @@ -178,7 +266,38 @@ namespace Firebase.Database extern(Android) public static void ListenForChildRemoved(string path, Action f) @{ + ChildEventListener childEventListener = new ChildEventListener() { + @Override + public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { + } + + @Override + public void onChildChanged(DataSnapshot dataSnapshot, String s) { + + } + + @Override + public void onChildRemoved(DataSnapshot dataSnapshot) { + if (dataSnapshot.getValue() == null) { + return; + } + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } + + @Override + public void onChildMoved(DataSnapshot dataSnapshot, String s) { + + } + + @Override + public void onCancelled(DatabaseError databaseError) { + f.run(path,databaseError.toString()); + } + }; + DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; + ref.child(path).addChildEventListener(childEventListener); @} [Foreign(Language.ObjC)] @@ -208,7 +327,38 @@ namespace Firebase.Database extern(Android) public static void ListenForChildMoved(string path, Action f) @{ + ChildEventListener childEventListener = new ChildEventListener() { + @Override + public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { + + } + + @Override + public void onChildChanged(DataSnapshot dataSnapshot, String s) { + + } + @Override + public void onChildRemoved(DataSnapshot dataSnapshot) { + + } + + @Override + public void onChildMoved(DataSnapshot dataSnapshot, String s) { + if (dataSnapshot.getValue() == null) { + return; + } + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } + + @Override + public void onCancelled(DatabaseError databaseError) { + f.run(path,databaseError.toString()); + } + }; + DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; + ref.child(path).addChildEventListener(childEventListener); @} [Foreign(Language.ObjC)] @@ -327,7 +477,18 @@ namespace Firebase.Database public static void SaveWithTimestamp(string path, Java.Object value) @{ DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; - ref.child(path).setValue(value); + try { + Map obj = (Map) value; + if (obj != null) { + obj.put("timestamp", ServerValue.TIMESTAMP); + ref.child(path).setValue(obj); + } + else { + ref.child(path).setValue(value); + } + } catch (Throwable t) { + Log.e("Error ", "Could not Save message: \"" + value.toString() + "\""); + } @} [Foreign(Language.ObjC)] From 5438b8e6d914e886a2a0a1b509a0cf63f3fcaa8d Mon Sep 17 00:00:00 2001 From: Mitul Golakiya Date: Mon, 8 Jan 2018 17:09:49 +0530 Subject: [PATCH 04/47] Facebook login via firebase --- .../FacebookAuthentication.uno | 160 ++++++++++++++++++ src/Firebase.Authentication.Facebook/JS.uno | 25 ++- 2 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 src/Firebase.Authentication.Facebook/FacebookAuthentication.uno diff --git a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno new file mode 100644 index 0000000..0422de3 --- /dev/null +++ b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno @@ -0,0 +1,160 @@ +using Fuse; +using Fuse.Platform; +using Uno; +using Uno.Compiler.ExportTargetInterop; +using Firebase.Authentication; + + +namespace Firebase.Authentication.Facebook.JS +{ + +[extern(Android) ForeignInclude(Language.Java, + "com.fuse.Activity", + "android.content.Intent", + "com.facebook.*", + "com.facebook.login.*", + "com.facebook.appevents.AppEventsLogger", + "com.google.android.gms.tasks.OnCompleteListener", + "com.google.android.gms.tasks.Task", + "com.google.firebase.auth.*")] + + [extern(iOS) Require("Cocoapods.Podfile.Target", "pod 'FBSDKCoreKit'")] + [extern(iOS) Require("Cocoapods.Podfile.Target", "pod 'FBSDKShareKit'")] + [extern(iOS) Require("Cocoapods.Podfile.Target", "pod 'FBSDKLoginKit'")] + [extern(iOS) Require("AppDelegate.SourceFile.Declaration", "#include ")] + [extern(iOS) Require("Source.Include", "Firebase/Firebase.h")] + [extern(iOS) Require("Source.Include", "Firebase/Firebase.h")] + [extern(iOS) Require("Source.Include", "FirebaseAuth/FirebaseAuth.h")] + [extern(iOS) Require("Source.Include", "FBSDKCoreKit/FBSDKCoreKit.h")] + [extern(iOS) Require("Source.Include", "FBSDKLoginKit/FBSDKLoginKit.h")] + [extern(iOS) Require("Source.Include", "@{Firebase.Authentication.Facebook.JS.FacebookModule:Include}")] + [extern(iOS) Require("Source.Include", "@{FacebookService:Include}")] + + public class FacebookAuthentication + { + + public FacebookAuthentication() + { + + } + + [Foreign(Language.ObjC)] + public extern(iOS) void Login() + @{ + FBSDKLoginManager* login = [[FBSDKLoginManager alloc] init]; + [login + logInWithReadPermissions: @[@"public_profile"] + fromViewController: [[[UIApplication sharedApplication] keyWindow] rootViewController] + handler: ^(FBSDKLoginManagerLoginResult* result, NSError* error) + { + if (error) + { + NSString * message = @"Facebook SignIn Failed. Error code: "; + NSString *errorMessage = [NSString stringWithFormat:@"%@ %ld", message, error.code]; + @{OnFailure(string):Call(message)}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call(message)}; + return; + } + if (result.isCancelled) + { + NSString *error = @"Facebook Auth Stage Cancelled"; + @{OnFailure(string):Call(error)}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call(error)}; + return; + } + @{OnAuth(ObjC.Object):Call(result)}; + } + ]; + @} + + extern(Android) Java.Object _callbackManager; + [Foreign(Language.Java)] + public extern(Android) void Login() + @{ + FacebookSdk.sdkInitialize(Activity.getRootActivity()); + final CallbackManager callbackManager = CallbackManager.Factory.create(); + @{FacebookAuthentication:Of(_this)._callbackManager:Set(callbackManager)}; + Activity.subscribeToResults(new Activity.ResultListener() { + @Override + public boolean onResult(int requestCode, int resultCode, Intent data) { + return callbackManager.onActivityResult(requestCode, resultCode, data); + } + }); + CallbackManager callbackManagerFrom = (CallbackManager)@{FacebookAuthentication:Of(_this)._callbackManager:Get()}; + LoginManager.getInstance().registerCallback(callbackManagerFrom, + new FacebookCallback() + { + public void onSuccess(LoginResult loginResult) { + @{OnAuth(Java.Object):Call(loginResult.getAccessToken())}; + } + + public void onCancel() { + @{OnFailure(string):Call("Facebook Auth Stage Cancelled")}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call("Facebook Auth Stage Cancelled")}; + } + + public void onError(FacebookException error) { + String reason = "Facebook Auth Stage Errored (" + error.getClass().getName() + "):\n" + error.getMessage(); + @{OnFailure(string):Call(reason)}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call(reason)}; + } + } + ); + LoginManager.getInstance().logInWithReadPermissions(Activity.getRootActivity(), java.util.Arrays.asList("public_profile")); + @} + + extern(Mobile) + static void OnSuccess(string message) + { + AuthService.AnnounceSignIn(AuthProviderName.Facebook); + } + + extern(Mobile) + static void OnFailure(string reason) + { + AuthService.SignalError(-1, reason); + } + + [Foreign(Language.Java)] + static extern(Android) void OnAuth(Java.Object result) + @{ + final AccessToken token = (AccessToken)result; + AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken()); + @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(token.getToken())}; + FirebaseAuth.getInstance().signInWithCredential(credential) + .addOnCompleteListener(com.fuse.Activity.getRootActivity(), new OnCompleteListener() { + public void onComplete(Task task) { + if (task.isSuccessful()) + @{OnSuccess(string):Call("Success")}; + else + @{OnFailure(string):Call("Authentication against Firebase failed")}; + }}); + @} + + [Foreign(Language.ObjC)] + static extern(iOS) void OnAuth(ObjC.Object result) + @{ + FBSDKLoginManagerLoginResult *accessToken = (FBSDKLoginManagerLoginResult *)result; + NSString *tokenStr = accessToken.token.tokenString; + + if (tokenStr==NULL) + { + @{OnFailure(string):Call(@"Authentication against Firebase failed")}; + return; + } + + @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(tokenStr)}; + FIRAuthCredential* credential = [FIRFacebookAuthProvider credentialWithAccessToken:tokenStr]; + + // auth againsts firebase + [[FIRAuth auth] signInWithCredential:credential + completion:^(FIRUser* fuser, NSError* ferror) { + if (ferror) + @{OnFailure(string):Call(@"Authentication against Firebase failed")}; + else + @{OnSuccess(string):Call(@"success")}; + }]; + @} + + } +} \ No newline at end of file diff --git a/src/Firebase.Authentication.Facebook/JS.uno b/src/Firebase.Authentication.Facebook/JS.uno index 6c83437..cb8d166 100644 --- a/src/Firebase.Authentication.Facebook/JS.uno +++ b/src/Firebase.Authentication.Facebook/JS.uno @@ -17,15 +17,19 @@ namespace Firebase.Authentication.Facebook.JS public sealed class FacebookModule : NativeModule { static readonly FacebookModule _instance; - static NativeEvent _onAuth; + static NativeEvent _onAuth, _onError; + readonly FacebookAuthentication _facebookAuthentication; public FacebookModule() { if(_instance != null) return; Uno.UX.Resource.SetGlobalKey(_instance = this, "Firebase/Authentication/Facebook"); - + _facebookAuthentication = new FacebookAuthentication(); _onAuth = new NativeEvent("onAuth"); AddMember(_onAuth); + _onError = new NativeEvent("onFailed"); + AddMember(_onError); + AddMember(new NativeFunction("doFacebookLogin", (NativeCallback)DoFacebookLogin)); Firebase.Authentication.Facebook.FacebookService.Init(); } @@ -33,6 +37,21 @@ namespace Firebase.Authentication.Facebook.JS { _onAuth.RaiseAsync(token); } + + static void OnFailed(string err) + { + _onError.RaiseAsync(err); + } + + object DoFacebookLogin(Context context, object[] args) + { + if defined(iOS || Android) + { + _facebookAuthentication.Login(); + } + else{ } + return null; + } } -} +} \ No newline at end of file From 9e75a10958c6ddc2f4499560e00e75a87f1a1c7a Mon Sep 17 00:00:00 2001 From: Pavel Kostenko Date: Mon, 8 Jan 2018 21:21:12 +0600 Subject: [PATCH 05/47] * added missing package Fuse.JSON --- Fuse.JSON/JSON.unoproj | 13 +++ Fuse.JSON/JavaObject.uno | 87 ++++++++++++++++ Fuse.JSON/LICENSE | 21 ++++ Fuse.JSON/ObjCObject.uno | 82 +++++++++++++++ Fuse.JSON/ScriptingValue.uno | 82 +++++++++++++++ Fuse.JSON/Test.uno | 26 +++++ Fuse.JSON/Value.uno | 193 +++++++++++++++++++++++++++++++++++ 7 files changed, 504 insertions(+) create mode 100755 Fuse.JSON/JSON.unoproj create mode 100755 Fuse.JSON/JavaObject.uno create mode 100755 Fuse.JSON/LICENSE create mode 100755 Fuse.JSON/ObjCObject.uno create mode 100755 Fuse.JSON/ScriptingValue.uno create mode 100755 Fuse.JSON/Test.uno create mode 100755 Fuse.JSON/Value.uno diff --git a/Fuse.JSON/JSON.unoproj b/Fuse.JSON/JSON.unoproj new file mode 100755 index 0000000..caf3a7a --- /dev/null +++ b/Fuse.JSON/JSON.unoproj @@ -0,0 +1,13 @@ +{ + "Packages": [ + "Fuse", + "FuseJS", + ], + "Includes": [ + "Value.uno", + "ScriptingValue.uno", + "ObjCObject.uno", + "JavaObject.uno", + "Test.uno", + ] +} diff --git a/Fuse.JSON/JavaObject.uno b/Fuse.JSON/JavaObject.uno new file mode 100755 index 0000000..3ba948d --- /dev/null +++ b/Fuse.JSON/JavaObject.uno @@ -0,0 +1,87 @@ +using Uno; +using Uno.UX; +using Uno.Collections; +using Uno.Threading; +using Uno.IO; +using Uno.Compiler.ExportTargetInterop; +using Fuse; +using Fuse.Platform; +using Fuse.Scripting; +using Fuse.Reactive; + +namespace JSON +{ + public extern(Android) static class JavaObject + { + static Matcher _toJavaObject = new ToJavaObject(); + + public static Java.Object FromJSON(Value value) + { + return value.Match(_toJavaObject); + } + } + + [ForeignInclude(Language.Java,"java.lang.Object","java.util.List","java.util.ArrayList","java.util.Map","java.util.HashMap","android.util.Log")] + extern(Android) class ToJavaObject : Matcher + { + [Foreign(Language.Java)] + public Java.Object Case() @{ return null; @} + + [Foreign(Language.Java)] + public Java.Object Case(string str) @{ return str; @} + + [Foreign(Language.Java)] + public Java.Object Case(double num) @{ return (double) num; @} + + [Foreign(Language.Java)] + public Java.Object Case(bool b) @{ return (boolean) b; @} + + public Java.Object Case(IEnumerable> obj) + { + var dict = NewHashMap(); + + foreach (var keyValue in obj) + { + SetMapValue(dict, keyValue.Key, keyValue.Value); + } + + return dict; + } + + [Foreign(Language.Java)] + extern(Android) Java.Object NewHashMap() + @{ + return new HashMap(); + @} + + [Foreign(Language.Java)] + extern(Android) void SetMapValue(Java.Object dictHandle, string key, Java.Object value) + @{ + ((Map)dictHandle).put(key, value); + @} + + extern(Android) public Java.Object Case(IEnumerable array) + { + var result = NewArrayList(); + + foreach (var value in array) + { + AddArrayValue(result, value); + } + + return result; + } + + [Foreign(Language.Java)] + extern(Android) Java.Object NewArrayList() + @{ + return new ArrayList(); + @} + + [Foreign(Language.Java)] + extern(Android) void AddArrayValue(Java.Object arrayHandle, Java.Object value) + @{ + ((List) arrayHandle).add(value); + @} + } +} diff --git a/Fuse.JSON/LICENSE b/Fuse.JSON/LICENSE new file mode 100755 index 0000000..f127eb2 --- /dev/null +++ b/Fuse.JSON/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Olle Fredriksson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Fuse.JSON/ObjCObject.uno b/Fuse.JSON/ObjCObject.uno new file mode 100755 index 0000000..a9e018e --- /dev/null +++ b/Fuse.JSON/ObjCObject.uno @@ -0,0 +1,82 @@ +using Uno.Collections; +using Uno.Compiler.ExportTargetInterop; + +namespace JSON +{ + public extern(iOS) static class ObjCObject + { + static Matcher _toObjCObject = new ToObjCObject(); + + public static ObjC.Object FromJSON(Value value) + { + return value.Match(_toObjCObject); + } + } + + extern(iOS) class ToObjCObject : Matcher + { + [Foreign(Language.ObjC)] + public ObjC.Object Case() @{ return [NSNull null]; @} + + [Foreign(Language.ObjC)] + public ObjC.Object Case(string str) @{ return str; @} + + [Foreign(Language.ObjC)] + public ObjC.Object Case(double num) @{ return [NSNumber numberWithDouble:num]; @} + + [Foreign(Language.ObjC)] + public ObjC.Object Case(bool b) @{ return [NSNumber numberWithBool:(b ? YES : NO)]; @} + + public ObjC.Object Case(IEnumerable> obj) + { + var dict = NewNSMutableDictionary(); + foreach (var keyValue in obj) + SetDictValue(dict, keyValue.Key, keyValue.Value); + return CopyToImmutableDict(dict); + } + + [Foreign(Language.ObjC)] + ObjC.Object NewNSMutableDictionary() + @{ + return [NSMutableDictionary dictionary]; + @} + + [Foreign(Language.ObjC)] + void SetDictValue(ObjC.Object dictHandle, string key, ObjC.Object value) + @{ + ((NSMutableDictionary*)dictHandle)[key] = value; + @} + + [Foreign(Language.ObjC)] + ObjC.Object CopyToImmutableDict(ObjC.Object dictHandle) + @{ + return [((NSMutableDictionary*)dictHandle) copy]; + @} + + public ObjC.Object Case(IEnumerable arr) + { + var result = NewNSMutableArray(); + foreach (var value in arr) + AddArrayValue(result, value); + return CopyToImmutableArray(result); + } + + [Foreign(Language.ObjC)] + ObjC.Object NewNSMutableArray() + @{ + return [NSMutableArray array]; + @} + + [Foreign(Language.ObjC)] + void AddArrayValue(ObjC.Object arrayHandle, ObjC.Object value) + @{ + [((NSMutableArray*)arrayHandle) addObject:value]; + @} + + [Foreign(Language.ObjC)] + ObjC.Object CopyToImmutableArray(ObjC.Object arrayHandle) + @{ + return [((NSMutableArray*)arrayHandle) copy]; + @} + } +} diff --git a/Fuse.JSON/ScriptingValue.uno b/Fuse.JSON/ScriptingValue.uno new file mode 100755 index 0000000..df3821b --- /dev/null +++ b/Fuse.JSON/ScriptingValue.uno @@ -0,0 +1,82 @@ +using Fuse.Scripting; +using Uno; +using Uno.Collections; + +namespace JSON +{ + public static class ScriptingValue + { + public static object FromJSON(Context context, Value value) + { + return value.Match(new ToScriptingValue(context)); + } + + public static Value ToJSON(object value) + { + if (value == null) return Null.TheNull; + if (value is string) return new String((string)value); + if (value is double) return new Number((double)value); + if (value is int) return new Number((int)value); + if (value is bool) return new Bool((bool)value); + if (value is Fuse.Scripting.Array) + { + var sarr = (Fuse.Scripting.Array)value; + var len = sarr.Length; + var arr = new Value[len]; + for (int i = 0; i < len; ++i) + { + arr[i] = ToJSON(sarr[i]); + } + return new Array(arr); + } + if (value is Fuse.Scripting.Object) + { + var sobj = (Fuse.Scripting.Object)value; + var dict = new Dictionary(); + foreach (var key in sobj.Keys) + { + dict[key] = ToJSON(sobj[key]); + } + return new Object(dict); + } + throw new ArgumentException("Not JSON-convertible", nameof(value)); + } + } + + class ToScriptingValue : Matcher + { + readonly Context _context; + + public ToScriptingValue(Context context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + _context = context; + } + + public object Case() { return null; } + public object Case(string str) { return str; } + public object Case(double num) { return num; } + public object Case(bool b) { return b; } + public object Case(IEnumerable> obj) + { + var result = _context.NewObject(); + foreach (var keyValue in obj) + { + result[keyValue.Key] = keyValue.Value; + } + return result; + } + public object Case(IEnumerable arr) + { + var result = _context.NewArray(); + int i = 0; + foreach (var val in arr) + { + result[i] = val; + ++i; + } + return result; + } + } +} diff --git a/Fuse.JSON/Test.uno b/Fuse.JSON/Test.uno new file mode 100755 index 0000000..1b27a80 --- /dev/null +++ b/Fuse.JSON/Test.uno @@ -0,0 +1,26 @@ +using Fuse.Scripting; +using Uno.Collections; +using Uno.Compiler.ExportTargetInterop; + +public class Test : Uno.Application +{ + public Test() + { + if defined(iOS) + { + var d = new Dictionary(); + d["hej"] = new JSON.String("hopp"); + d["happ"] = new JSON.String("hupp"); + d["arr"] = new JSON.Array(new JSON.Value[] { new JSON.String("arrayValue") }); + var jsonObject = new JSON.Object(d); + var test = JSON.ObjCObject.FromJSON(jsonObject); + NSLog(test); + } + } + + [Foreign(Language.ObjC)] + extern(iOS) static void NSLog(ObjC.Object o) + @{ + ::NSLog(@"%@", o); + @} +} diff --git a/Fuse.JSON/Value.uno b/Fuse.JSON/Value.uno new file mode 100755 index 0000000..2092722 --- /dev/null +++ b/Fuse.JSON/Value.uno @@ -0,0 +1,193 @@ +using Uno; +using Uno.Collections; + +namespace JSON +{ + public interface Matcher + { + T Case(); // Null + T Case(string str); + T Case(double num); + T Case(bool b); + T Case(IEnumerable> obj); + T Case(IEnumerable arr); + } + + public interface Value + { + T Match(Matcher matcher); + } + + public class Null : Value + { + public T Match(Matcher matcher) { return matcher.Case(); } + private Null() { } + public static Null TheNull = new Null(); + } + + public class String : Value + { + readonly string _value; + public String(string value) + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + _value = value; + } + public T Match(Matcher matcher) + { + return matcher.Case(_value); + } + } + + public class Number : Value + { + readonly double _value; + public Number(double value) { _value = value; } + public Number(int value) { _value = (double)value; } + public T Match(Matcher matcher) { return matcher.Case(_value); } + } + + public class Bool : Value + { + readonly bool _value; + public Bool(bool value) { _value = value; } + public T Match(Matcher matcher) { return matcher.Case(_value); } + } + + public class Object : Value + { + readonly Dictionary _dict; + + public Object(Dictionary dict) + { + if (dict == null) + throw new ArgumentNullException(nameof(dict)); + _dict = dict; + } + + public T Match(Matcher matcher) + { + return matcher.Case( + new ObjectEnumerable( + _dict, + matcher)); + } + + class ObjectEnumerable : IEnumerable> + { + Dictionary _dict; + Matcher _matcher; + + public ObjectEnumerable(Dictionary dict, Matcher matcher) + { + _dict = dict; + _matcher = matcher; + } + + public IEnumerator> GetEnumerator() + { + return new ObjectEnumerator(_dict.GetEnumerator(), _matcher); + } + } + + class ObjectEnumerator : IEnumerator> + { + IEnumerator> _enumerator; + Matcher _matcher; + + public ObjectEnumerator(IEnumerator> enumerator, Matcher matcher) + { + _enumerator = enumerator; + _matcher = matcher; + } + + public bool MoveNext() { return _enumerator.MoveNext(); } + public void Reset() { _enumerator.Reset(); } + + public KeyValuePair Current + { + get + { + var current = _enumerator.Current; + return new KeyValuePair(current.Key, current.Value.Match(_matcher)); + } + } + + public void Dispose() + { + _enumerator = null; + _matcher = null; + } + } + } + + public class Array : Value + { + readonly Value[] _arr; + + public Array(Value[] arr) + { + if (arr == null) + throw new ArgumentNullException(nameof(arr)); + _arr = arr; + } + + public T Match(Matcher matcher) + { + return matcher.Case( + new ArrayEnumerable( + _arr, + matcher)); + } + + class ArrayEnumerable : IEnumerable + { + readonly Value[] _arr; + readonly Matcher _matcher; + + public ArrayEnumerable(Value[] arr, Matcher matcher) + { + _arr = arr; + _matcher = matcher; + } + + public IEnumerator GetEnumerator() + { + return new ArrayEnumerator( + _arr, + _matcher); + } + } + + class ArrayEnumerator : IEnumerator + { + Value[] _arr; + int _index; + Matcher _matcher; + + public ArrayEnumerator(Value[] arr, Matcher matcher) + { + _arr = arr; + _index = -1; + _matcher = matcher; + } + + public bool MoveNext() + { + ++_index; + return _index < _arr.Length; + } + + public void Reset() { _index = -1; } + + public T Current { get { return _arr[_index].Match(_matcher); } } + + public void Dispose() + { + _arr = null; + _matcher = null; + } + } + } +} From 7cbe3732237fc10344a98166b30a13814c7fe356 Mon Sep 17 00:00:00 2001 From: Mitul Golakiya Date: Mon, 29 Jan 2018 10:02:35 +0530 Subject: [PATCH 06/47] Fix: NativeEvent.RaiseAsync invalid parameters after Fuse 1.6 release --- src/Firebase.Authentication.Facebook/JS.uno | 4 ++-- src/Firebase.Authentication.Google/JS.uno | 2 +- src/Firebase.Authentication/JS.uno | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Firebase.Authentication.Facebook/JS.uno b/src/Firebase.Authentication.Facebook/JS.uno index cb8d166..3a20b8d 100644 --- a/src/Firebase.Authentication.Facebook/JS.uno +++ b/src/Firebase.Authentication.Facebook/JS.uno @@ -35,12 +35,12 @@ namespace Firebase.Authentication.Facebook.JS static void Auth(string token) { - _onAuth.RaiseAsync(token); + _onAuth.RaiseAsync(_onAuth.Context.ThreadWorker, token); } static void OnFailed(string err) { - _onError.RaiseAsync(err); + _onError.RaiseAsync(_onError.Context.ThreadWorker, err); } object DoFacebookLogin(Context context, object[] args) diff --git a/src/Firebase.Authentication.Google/JS.uno b/src/Firebase.Authentication.Google/JS.uno index cb9431e..115c7de 100644 --- a/src/Firebase.Authentication.Google/JS.uno +++ b/src/Firebase.Authentication.Google/JS.uno @@ -31,7 +31,7 @@ namespace Firebase.Authentication.Google.JS static void Auth(string idToken, string accessToken) { - _onAuth.RaiseAsync(idToken, accessToken); + _onAuth.RaiseAsync(_onAuth.Context.ThreadWorker, idToken, accessToken); } } } diff --git a/src/Firebase.Authentication/JS.uno b/src/Firebase.Authentication/JS.uno index 996b962..dcbec25 100644 --- a/src/Firebase.Authentication/JS.uno +++ b/src/Firebase.Authentication/JS.uno @@ -103,13 +103,13 @@ namespace Firebase.Authentication.JS static void OnUser() { var isSignedIn = GetSignedIn(); - _onSignInChanged.RaiseAsync(isSignedIn); + _onSignInChanged.RaiseAsync(_onSignInChanged.Context.ThreadWorker, isSignedIn); _instance.Emit("signedInStateChanged", isSignedIn); } static void OnError(int errorCode, string message) { - _onError.RaiseAsync(message, errorCode); + _onError.RaiseAsync(_onError.Context.ThreadWorker, message, errorCode); _instance.Emit("error", message, errorCode); } From 9408bef81d06c6f6eb169e3bdf5699e412b1f316 Mon Sep 17 00:00:00 2001 From: Mitul Golakiya Date: Mon, 29 Jan 2018 15:28:41 +0530 Subject: [PATCH 07/47] Revert "Fix: NativeEvent.RaiseAsync invalid parameters after Fuse 1.6 release" This reverts commit 7cbe3732237fc10344a98166b30a13814c7fe356. --- src/Firebase.Authentication.Facebook/JS.uno | 4 ++-- src/Firebase.Authentication.Google/JS.uno | 2 +- src/Firebase.Authentication/JS.uno | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Firebase.Authentication.Facebook/JS.uno b/src/Firebase.Authentication.Facebook/JS.uno index 3a20b8d..cb8d166 100644 --- a/src/Firebase.Authentication.Facebook/JS.uno +++ b/src/Firebase.Authentication.Facebook/JS.uno @@ -35,12 +35,12 @@ namespace Firebase.Authentication.Facebook.JS static void Auth(string token) { - _onAuth.RaiseAsync(_onAuth.Context.ThreadWorker, token); + _onAuth.RaiseAsync(token); } static void OnFailed(string err) { - _onError.RaiseAsync(_onError.Context.ThreadWorker, err); + _onError.RaiseAsync(err); } object DoFacebookLogin(Context context, object[] args) diff --git a/src/Firebase.Authentication.Google/JS.uno b/src/Firebase.Authentication.Google/JS.uno index 115c7de..cb9431e 100644 --- a/src/Firebase.Authentication.Google/JS.uno +++ b/src/Firebase.Authentication.Google/JS.uno @@ -31,7 +31,7 @@ namespace Firebase.Authentication.Google.JS static void Auth(string idToken, string accessToken) { - _onAuth.RaiseAsync(_onAuth.Context.ThreadWorker, idToken, accessToken); + _onAuth.RaiseAsync(idToken, accessToken); } } } diff --git a/src/Firebase.Authentication/JS.uno b/src/Firebase.Authentication/JS.uno index dcbec25..996b962 100644 --- a/src/Firebase.Authentication/JS.uno +++ b/src/Firebase.Authentication/JS.uno @@ -103,13 +103,13 @@ namespace Firebase.Authentication.JS static void OnUser() { var isSignedIn = GetSignedIn(); - _onSignInChanged.RaiseAsync(_onSignInChanged.Context.ThreadWorker, isSignedIn); + _onSignInChanged.RaiseAsync(isSignedIn); _instance.Emit("signedInStateChanged", isSignedIn); } static void OnError(int errorCode, string message) { - _onError.RaiseAsync(_onError.Context.ThreadWorker, message, errorCode); + _onError.RaiseAsync(message, errorCode); _instance.Emit("error", message, errorCode); } From 89dbfeaf4b59f1ec9d50ab9535c3b57227ce7505 Mon Sep 17 00:00:00 2001 From: Pavel Kostenko Date: Thu, 1 Feb 2018 10:43:58 +0600 Subject: [PATCH 08/47] * updated README.md and fixed Facebook auth error reporting --- README.md | 197 ++++++++++++++++++ .../FacebookAuthentication.uno | 4 +- 2 files changed, 199 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c0ae73f..aed2da6 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,200 @@ I'm an employee at Fuse, however any views, opinions or swearing at apis found i ## Obligatory Pic! ![wee](https://github.com/cbaggers/Fuse.Firebase/blob/master/docs/app.jpeg) + +## HOWTO + +### Create new record + +``` +var firebaseDb = require("Firebase/Database"); +var path = 'users'; +var data = { + name: 'Pavel' +}; + +// this will insert new object to given path +firebaseDb.pushWithTimestamp(path, data); + +// new object in database will have `timestamp` property set by Firebase server +{ + name: 'Pavel', + timestamp: 1517459417719 +} + +// if you want to receive event when record was created, read below +// if you do not want timestamp property to be created by firebase server +// use `.push(path, data)` method instead +``` + +### Read Data + +``` +// firebaseDb.read(path) + +var firebaseDb = require("Firebase/Database"); +var path = 'users/pavel'; +firebaseDb.read(path) + .then(function (json) { + // here json is a JSON string + console.log(JSON.parse(json)); + }) + .catch(function (reason) { + console.log('Unable to read path: ' + path); + }); +``` + +### Listen for data event + +* this event is fired when you change particular object. +* first you need to know the path to this object +* create listener +* subscribe to data event + +``` +var firebaseDb = require("Firebase/Database"); +var path1 = 'users/pavel'; +var path2 = 'users/mitul'; +// create listeners for data event for 2 paths +firebaseDb.listen(path1); +firebaseDb.listen(path2); + +// handle responses from Firebase +// you subscribe once, and will receive events for any path +// you're listening above +firebaseDb.on('data', function (eventPath, msg) { + // msg here is a JSON string + // track only given path + if (eventPath === path1) { + console.log(path1); + console.log(msg); + // convert JSON to object + var user1 = JSON.parse(msg); + } + if (eventPath === path2) { + console.log(path2); + console.log(msg); + // convert JSON to object + var user2 = JSON.parse(msg); + } + }); +``` + +### Listen for dataAdded events + +``` +var firebaseDb = require("Firebase/Database"); +var usersPath = 'users'; +var messagesPath = 'messages'; + +// create listener for given path +// 1 means that you will always receive last object from `path` after you call `.listenOnAdded` +// this doesn't means that this object was just added, it's just how firebase iOS/Android library works +// more on that: https://firebase.google.com/docs/database/ios/lists-of-data +// find FIRDataEventTypeChildAdded and read how it works. It's not our fault :) +// so you need to take care about that and do not insert same record twice +// it's not possible to set it to 0, so 1 is a safe default +// if you set it to 10 you'll get last 10 records from given `path` + +firebaseDb.listenOnAdded(usersPath, 1); +firebaseDb.listenOnAdded(messagesPath, 1); + +// now subscribe to `dataAdded` events +// you need to subscribe only once +// function below will be executed for any path +firebaseDb.on('dataAdded', function (eventPath, msg) { + // msg here is a JSON string + + // track only given path + if (eventPath === usersPath) { + // new user record was added, usually by push method + // if you created record using not .push method or + // pushWithTimestamp you will not receive event here + console.log(eventPath); + console.log(msg); + var newUser = JSON.parse(msg); + } + + if (eventPath === messagesPath) { + // new message record was added, usually by push method + // if you created record using not .push method or + // .pushWithTimestamp you will not receive event here + console.log(eventPath); + console.log(msg); + var newMessage = JSON.parse(msg); + } + }); + +``` + +### Listen for dataRemoved events + +``` +var firebaseDb = require("Firebase/Database"); +var usersPath = 'users'; +var messagesPath = 'messages'; + +// create listener for given path +// 1 means that you will always receive last object from `path` +// it's not possible to set it to 0, so 1 is a safe default +// if you set it to 10 you'll get last 10 records from given `path` + +firebaseDb.listenOnRemoved(usersPath, 1); +firebaseDb.listenOnRemoved(messagesPath, 1); + +// now subscribe to `dataAdded` events +// you need to subscribe only once +// function below will be executed for any path +firebaseDb.on('dataRemoved', function (eventPath, msg) { + // msg here is a JSON string + + // track only given path + if (eventPath === usersPath) { + // user record was removed + console.log(eventPath); + console.log(msg); + var newUser = JSON.parse(msg); + } + + if (eventPath === messagesPath) { + // message record was removed + console.log(eventPath); + console.log(msg); + var newMessage = JSON.parse(msg); + } +}); + +``` + +### Query subset of records + +* say you want to get old messages for particular user +* you want to get messages before particular timestamp + +``` +var chatMessagesPath = 'users/pavel/messages'; +var oldestMessageTimestamp = 1517459417719; +var count = 20; + +// we're going to query 20 messages before `oldestMessageTimestamp` + +firebaseDb.readByQueryEndingAtValue( + chatMessagesPath, + 'timestamp', // field we're comaring with + oldestMessageTimestamp, // oldest message timestamp on our device + count // how many records to get +); + +// you need to do this only once in your code +// this event handler will be called for every firebaseDb.readByQueryEndingAtValue method +firebaseDb.on('readByQueryEndingAtValue', function (eventPath, newMessages) { + // newMessages here is a JSON string + if (eventPath === chatMessagesPath) { + console.log(chatMesssagesPath); + console.log(newMessages); + var data = JSON.parse(newMessages); + } else { + // somebody requested data for other firebase path + } +}); +``` diff --git a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno index 0422de3..4b9f33b 100644 --- a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno +++ b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno @@ -51,8 +51,8 @@ namespace Firebase.Authentication.Facebook.JS { NSString * message = @"Facebook SignIn Failed. Error code: "; NSString *errorMessage = [NSString stringWithFormat:@"%@ %ld", message, error.code]; - @{OnFailure(string):Call(message)}; - @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call(message)}; + @{OnFailure(string):Call(errorMessage)}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call(errorMessage)}; return; } if (result.isCancelled) From a95a3a98dd278665fa6eeaf819e30f8838fb40ac Mon Sep 17 00:00:00 2001 From: Pavel Kostenko Date: Thu, 1 Feb 2018 10:46:22 +0600 Subject: [PATCH 09/47] * small fix in Read Data section of README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aed2da6..69812d8 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,8 @@ var path = 'users/pavel'; firebaseDb.read(path) .then(function (json) { // here json is a JSON string - console.log(JSON.parse(json)); + console.log(json); + var user = JSON.parse(json); }) .catch(function (reason) { console.log('Unable to read path: ' + path); From fc70b6be694d4c7f6cdac0fd5b5a9ee765bfca99 Mon Sep 17 00:00:00 2001 From: Pavel Kostenko Date: Thu, 1 Feb 2018 10:48:23 +0600 Subject: [PATCH 10/47] * added syntax highlighting to README JS code --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 69812d8..d7254ec 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ I'm an employee at Fuse, however any views, opinions or swearing at apis found i ### Create new record -``` +```JavaScript var firebaseDb = require("Firebase/Database"); var path = 'users'; var data = { @@ -56,7 +56,7 @@ firebaseDb.pushWithTimestamp(path, data); ### Read Data -``` +```JavaScript // firebaseDb.read(path) var firebaseDb = require("Firebase/Database"); @@ -79,7 +79,7 @@ firebaseDb.read(path) * create listener * subscribe to data event -``` +```JavaScript var firebaseDb = require("Firebase/Database"); var path1 = 'users/pavel'; var path2 = 'users/mitul'; @@ -110,7 +110,7 @@ firebaseDb.on('data', function (eventPath, msg) { ### Listen for dataAdded events -``` +```JavaScript var firebaseDb = require("Firebase/Database"); var usersPath = 'users'; var messagesPath = 'messages'; @@ -157,7 +157,7 @@ firebaseDb.on('dataAdded', function (eventPath, msg) { ### Listen for dataRemoved events -``` +```JavaScript var firebaseDb = require("Firebase/Database"); var usersPath = 'users'; var messagesPath = 'messages'; @@ -199,7 +199,7 @@ firebaseDb.on('dataRemoved', function (eventPath, msg) { * say you want to get old messages for particular user * you want to get messages before particular timestamp -``` +```JavaScript var chatMessagesPath = 'users/pavel/messages'; var oldestMessageTimestamp = 1517459417719; var count = 20; From 5d6a9dc0a6ec534e5da2f1b75be0737686ed9a0f Mon Sep 17 00:00:00 2001 From: Pavel Kostenko Date: Thu, 1 Feb 2018 10:53:42 +0600 Subject: [PATCH 11/47] * added doc for `detachListener` method --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index d7254ec..eb359a1 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,7 @@ firebaseDb.on('dataRemoved', function (eventPath, msg) { * you want to get messages before particular timestamp ```JavaScript +var firebaseDb = require("Firebase/Database"); var chatMessagesPath = 'users/pavel/messages'; var oldestMessageTimestamp = 1517459417719; var count = 20; @@ -226,3 +227,19 @@ firebaseDb.on('readByQueryEndingAtValue', function (eventPath, newMessages) { } }); ``` + +### Detach Listeners + +* when you don't want to receive events for particular path anymore, you need to detach listener + +``` +var firebaseDb = require("Firebase/Database"); +var usersPath = 'users'; +// say you subscribed to some path earlier +firebaseDb.listenOnRemoved(usersPath, 1); +// and now you don't want to receive dataRemoved events anymore +// maybe user was logged out etc. + +// do this, however this will also unsubscribe from `dataAdded` and `data` events +firebaseDb.detachListeners(usersPath); +``` From 0f9b039bd1406fde19706bea3be281e8512ff1bd Mon Sep 17 00:00:00 2001 From: Pavel Kostenko Date: Fri, 2 Feb 2018 10:27:22 +0600 Subject: [PATCH 12/47] * updated README, + ability of iOS device to receive FCM token, so we can sent push notifications to iOS device from Firebase --- README.md | 2 +- .../Firebase.Notifications.Android.unoproj | 5 +-- src/Firebase.Notifications.Android/JS.uno | 10 ++++++ .../iOSFirebaseNotificationCallbacks.h | 5 +++ .../iOSFirebaseNotificationCallbacks.mm | 15 ++++++++ .../iOSImpl.uno | 35 +++++++++++++++++++ 6 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.h create mode 100644 src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.mm create mode 100644 src/Firebase.Notifications.Android/iOSImpl.uno diff --git a/README.md b/README.md index eb359a1..2f8d359 100644 --- a/README.md +++ b/README.md @@ -232,7 +232,7 @@ firebaseDb.on('readByQueryEndingAtValue', function (eventPath, newMessages) { * when you don't want to receive events for particular path anymore, you need to detach listener -``` +```JavaScript var firebaseDb = require("Firebase/Database"); var usersPath = 'users'; // say you subscribed to some path earlier diff --git a/src/Firebase.Notifications.Android/Firebase.Notifications.Android.unoproj b/src/Firebase.Notifications.Android/Firebase.Notifications.Android.unoproj index 708c3d9..4bdb10b 100644 --- a/src/Firebase.Notifications.Android/Firebase.Notifications.Android.unoproj +++ b/src/Firebase.Notifications.Android/Firebase.Notifications.Android.unoproj @@ -22,11 +22,12 @@ "Includes": [ "Common.uno:Source", "JS.uno:Source", - - "Android/Impl.uno:Source", + "iOSImpl.uno:Source", "Android/Impl.cpp.uxl:Extensions", "Android/PushNotificationReceiver.java:Java:android", "Android/PushNotificationIDService.java:Java:android", + "iOSFirebaseNotificationCallbacks.h:ObjCHeader:iOS", + "iOSFirebaseNotificationCallbacks.mm:ObjCSource:iOS", "Android/Assets/DefaultIcon.png:File" ] } diff --git a/src/Firebase.Notifications.Android/JS.uno b/src/Firebase.Notifications.Android/JS.uno index 8db1ae7..fe4112c 100644 --- a/src/Firebase.Notifications.Android/JS.uno +++ b/src/Firebase.Notifications.Android/JS.uno @@ -26,6 +26,8 @@ namespace Firebase.Notifications public sealed class NotificationModule : NativeEventEmitterModule { static readonly NotificationModule _instance; + readonly iOSImpl _iOSImpl; + static NativeEvent _onRegistrationSucceedediOS; public NotificationModule() : base(true, @@ -35,6 +37,8 @@ namespace Firebase.Notifications if (_instance != null) return; Resource.SetGlobalKey(_instance = this, "Firebase/Notifications"); + _iOSImpl = new iOSImpl(); + // Old-style events for backwards compatibility var onReceivedMessage = new NativeEvent("onReceivedMessage"); var onRegistrationFailed = new NativeEvent("onRegistrationFailed"); @@ -55,6 +59,8 @@ namespace Firebase.Notifications AddMember(onRegistrationFailed); AddMember(new NativeFunction("clearBadgeNumber", ClearBadgeNumber)); AddMember(new NativeFunction("clearAllNotifications", ClearAllNotifications)); + _onRegistrationSucceedediOS = new NativeEvent("onRegistrationSucceedediOS"); + AddMember(_onRegistrationSucceedediOS); Firebase.Notifications.NotificationService.ReceivedNotification += OnReceivedNotification; Firebase.Notifications.NotificationService.RegistrationSucceeded += OnRegistrationSucceeded; @@ -83,6 +89,10 @@ namespace Firebase.Notifications Emit("registrationSucceeded", message); } + static void OnRegistrationSucceedediOS(string message) { + _onRegistrationSucceedediOS.RaiseAsync(message); + } + /** @scriptevent error @param message A backend specific reason for the failure. diff --git a/src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.h b/src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.h new file mode 100644 index 0000000..659ea5f --- /dev/null +++ b/src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.h @@ -0,0 +1,5 @@ +#import +#include + +@interface FireNotificationCallbacks : NSObject +@end diff --git a/src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.mm b/src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.mm new file mode 100644 index 0000000..cf5195c --- /dev/null +++ b/src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.mm @@ -0,0 +1,15 @@ +#import +#include <@{Firebase.Notifications.NotificationModule:Include}> +#include <@{ObjC.Object:Include}> +#include + +@implementation FireNotificationCallbacks : NSObject + + +- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken { + NSLog(@"FCM registration token: %@", fcmToken); + + @{Firebase.Notifications.NotificationModule.OnRegistrationSucceedediOS(string):Call(fcmToken)}; +} + +@end diff --git a/src/Firebase.Notifications.Android/iOSImpl.uno b/src/Firebase.Notifications.Android/iOSImpl.uno new file mode 100644 index 0000000..f36e9ce --- /dev/null +++ b/src/Firebase.Notifications.Android/iOSImpl.uno @@ -0,0 +1,35 @@ +using Uno; +using Uno.UX; +using Uno.Collections; +using Uno.Compiler.ExportTargetInterop; +using Fuse; +using Fuse.Triggers; +using Uno.Threading; + +namespace Firebase.Notifications +{ + [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Messaging'")] + [extern(iOS) Require("Source.Include", "iOSFirebaseNotificationCallbacks.h")] + [Require("Source.Include", "Firebase/Firebase.h")] + + public class iOSImpl + { + extern(ios) static internal ObjC.Object _iosDelegate; + + public iOSImpl() { + Start(); + } + + extern(!iOS) + public void Start() { } + + [Foreign(Language.ObjC)] + extern(iOS) + public void Start() + @{ + FireNotificationCallbacks* fireCB = [[FireNotificationCallbacks alloc] init]; + @{_iosDelegate:Set(fireCB)}; + [FIRMessaging messaging].delegate = (id)fireCB; + @} + } +} From bf4a3ec52bb2323cc8d84a390786ed679d974585 Mon Sep 17 00:00:00 2001 From: Pavel Kostenko Date: Fri, 2 Feb 2018 11:32:01 +0600 Subject: [PATCH 13/47] * fix PushNotification issue for Android --- .../Firebase.Notifications.Android.unoproj | 1 + src/Firebase.Notifications.Android/iOSImpl.uno | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Firebase.Notifications.Android/Firebase.Notifications.Android.unoproj b/src/Firebase.Notifications.Android/Firebase.Notifications.Android.unoproj index 4bdb10b..e2a1ed0 100644 --- a/src/Firebase.Notifications.Android/Firebase.Notifications.Android.unoproj +++ b/src/Firebase.Notifications.Android/Firebase.Notifications.Android.unoproj @@ -22,6 +22,7 @@ "Includes": [ "Common.uno:Source", "JS.uno:Source", + "Android/Impl.uno:Source", "iOSImpl.uno:Source", "Android/Impl.cpp.uxl:Extensions", "Android/PushNotificationReceiver.java:Java:android", diff --git a/src/Firebase.Notifications.Android/iOSImpl.uno b/src/Firebase.Notifications.Android/iOSImpl.uno index f36e9ce..7aefb70 100644 --- a/src/Firebase.Notifications.Android/iOSImpl.uno +++ b/src/Firebase.Notifications.Android/iOSImpl.uno @@ -10,7 +10,7 @@ namespace Firebase.Notifications { [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Messaging'")] [extern(iOS) Require("Source.Include", "iOSFirebaseNotificationCallbacks.h")] - [Require("Source.Include", "Firebase/Firebase.h")] + [extern(iOS) Require("Source.Include", "Firebase/Firebase.h")] public class iOSImpl { From 84711182eb36d6e2f060a0eaa06ab2c5852caba4 Mon Sep 17 00:00:00 2001 From: Luis Rodriguez Date: Tue, 6 Feb 2018 22:20:44 -0600 Subject: [PATCH 14/47] new query by child value implementation --- README.md | 35 +++++++++-- src/Firebase.Database/Database.uno | 94 ++++++++++++++++++++++++++++-- src/Firebase.Database/JS.uno | 9 +++ 3 files changed, 128 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 2f8d359..db93851 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,29 @@ firebaseDb.read(path) }); ``` +### Read Data with Query + +Sometimes you need to search for a certain value in an object, instead or iterating in the cliente +use this implementation to let the Firebase do the query for you. + +The following example will give you all the objects where the key name is equal to Luis Rodriguez, +great for searching when you do not know the key and when you use Push to save data. + +```JavaScript +// firebaseDb.readByQueryEqualToValue(path,key,value) + +var firebaseDb = require("Firebase/Database"); +firebaseDb.readByQueryEqualToValue("users","name","Luis Rodriguez") + .then(function (json) { + // here json is a JSON string + console.log(json); + var user = JSON.parse(json); + }) + .catch(function (reason) { + console.log('Unable to read path: ' + path); + }); +``` + ### Listen for data event * this event is fired when you change particular object. @@ -132,20 +155,20 @@ firebaseDb.listenOnAdded(messagesPath, 1); // function below will be executed for any path firebaseDb.on('dataAdded', function (eventPath, msg) { // msg here is a JSON string - + // track only given path if (eventPath === usersPath) { // new user record was added, usually by push method - // if you created record using not .push method or + // if you created record using not .push method or // pushWithTimestamp you will not receive event here console.log(eventPath); console.log(msg); var newUser = JSON.parse(msg); } - + if (eventPath === messagesPath) { // new message record was added, usually by push method - // if you created record using not .push method or + // if you created record using not .push method or // .pushWithTimestamp you will not receive event here console.log(eventPath); console.log(msg); @@ -175,7 +198,7 @@ firebaseDb.listenOnRemoved(messagesPath, 1); // function below will be executed for any path firebaseDb.on('dataRemoved', function (eventPath, msg) { // msg here is a JSON string - + // track only given path if (eventPath === usersPath) { // user record was removed @@ -183,7 +206,7 @@ firebaseDb.on('dataRemoved', function (eventPath, msg) { console.log(msg); var newUser = JSON.parse(msg); } - + if (eventPath === messagesPath) { // message record was removed console.log(eventPath); diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index ebbd124..84cfae6 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -137,7 +137,7 @@ namespace Firebase.Database f(path, nil); return; } - + NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:snapshot.value options:(NSJSONWritingOptions)0 @@ -171,7 +171,7 @@ namespace Firebase.Database f.run(path,databaseError.toString()); } }; - + long longLastValue = Long.parseLong(lastValue); DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; Query readQuery = ref.child(path).orderByChild(keyName).endAt(longLastValue).limitToLast(count); @@ -330,7 +330,7 @@ namespace Firebase.Database ChildEventListener childEventListener = new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { - + } @Override @@ -606,7 +606,7 @@ namespace Firebase.Database Save(); } - public static void SaveWithTimestamp(string path, Object value) + public static void SaveWithTimestamp(string path, Object value) { Save(); } @@ -656,6 +656,14 @@ namespace Firebase.Database } } + internal class ReadByQueryEqualToValue : Promise + { + public ReadByQueryEqualToValue(string path, string key, string val) + { + Reject(new Exception("Not implemented on desktop")); + } + } + [Require("Entity", "DatabaseService")] [Require("Source.Import","FirebaseDatabase/FIRDatabase.h")] [Require("Source.Include","@{DatabaseService:Include}")] @@ -687,6 +695,38 @@ namespace Firebase.Database void Reject(string reason) { Reject(new Exception(reason)); } } + [Require("Entity", "DatabaseService")] + [Require("Source.Import","FirebaseDatabase/FIRDatabase.h")] + [Require("Source.Include","@{DatabaseService:Include}")] + extern(iOS) + internal class ReadByQueryEqualToValue : Promise + { + [Foreign(Language.ObjC)] + public ReadByQueryEqualToValue(string path, string key, string val) + @{ + FIRDatabaseReference *ref = @{DatabaseService._handle:Get()}; + + [[[[ref child:path] queryOrderedByChild:key] queryEqualToValue:val] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { + NSError *error; + + @{ReadByQueryEqualToValue:Of(_this).Resolve(string):Call(( + ([snapshot.value isEqual:[NSNull null]]) + ? nil + : ([snapshot.value isKindOfClass:[NSString class]]) + ? [NSString stringWithFormat:@"\"%@\"", snapshot.value] + : ([snapshot.value isKindOfClass:[NSNumber class]]) + ? [NSString stringWithFormat:@"%@", snapshot.value] + : [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:snapshot.value options:(NSJSONWritingOptions)0 error:&error] encoding:NSUTF8StringEncoding] + ))}; + + } withCancelBlock:^(NSError * _Nonnull error) { + NSString *erstr = [NSString stringWithFormat:@"Firebase Read Error: %@", error.localizedDescription]; + @{ReadByQueryEqualToValue:Of(_this).Reject(string):Call(erstr)}; + }]; + @} + void Reject(string reason) { Reject(new Exception(reason)); } + } + [ForeignInclude(Language.Java, "com.google.firebase.database.DatabaseReference", "com.google.firebase.database.DatabaseError", @@ -732,4 +772,50 @@ namespace Firebase.Database @} void Reject(string reason) { Reject(new Exception(reason)); } } + + [ForeignInclude(Language.Java, + "com.google.firebase.database.DatabaseReference", + "com.google.firebase.database.DatabaseError", + "com.google.firebase.database.DatabaseReference", + "com.google.firebase.database.DataSnapshot", + "com.google.firebase.database.ValueEventListener", + "org.json.JSONObject", + "org.json.JSONArray", + "java.util.Map", + "java.util.List")] + extern(Android) + internal class ReadByQueryEqualToValue : Promise + { + [Foreign(Language.Java)] + public ReadByQueryEqualToValue(string path) + @{ + ValueEventListener dataListener = new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) + { + Object snapshotValue = dataSnapshot.getValue(); + @{ReadByQueryEqualToValue:Of(_this).Resolve(string):Call(( + (snapshotValue == null) + ? null + : (snapshotValue instanceof Map) + ? new JSONObject((Map) snapshotValue).toString() + : (snapshotValue instanceof List) + ? new JSONArray((List) snapshotValue).toString() + : (snapshotValue instanceof String) + ? "\"" + snapshotValue.toString() + "\"" + : snapshotValue.toString() + ))}; + } + + @Override + public void onCancelled(DatabaseError databaseError) + { + @{ReadByQueryEqualToValue:Of(_this).Reject(string):Call(databaseError.toString())}; + } + }; + DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; + ref.child(path).orderByChild(key).equalTo(val).addListenerForSingleValueEvent(dataListener); + @} + void Reject(string reason) { Reject(new Exception(reason)); } + } } diff --git a/src/Firebase.Database/JS.uno b/src/Firebase.Database/JS.uno index 5731142..35e5816 100644 --- a/src/Firebase.Database/JS.uno +++ b/src/Firebase.Database/JS.uno @@ -57,6 +57,7 @@ namespace Firebase.Database.JS AddMember(new NativeFunction("readByQueryEndingAtValue", (NativeCallback)ReadByQueryEndingAtValue)); AddMember(new NativeFunction("detachListeners", (NativeCallback)DetachListeners)); AddMember(new NativePromise("read", Read, null)); + AddMember(new NativePromise("readByQueryEqualToValue", ReadByQueryEqualToValue, null)); AddMember(new NativeFunction("push", (NativeCallback)Push)); AddMember(new NativeFunction("pushWithTimestamp", (NativeCallback)PushWithTimestamp)); AddMember(new NativeFunction("save", (NativeCallback)Save)); @@ -69,6 +70,14 @@ namespace Firebase.Database.JS return new Read(path); } + static Future ReadByQueryEqualToValue(object[] args) + { + var path = args[0].ToString(); + var key = args[1].ToString(); + var val = args[2].ToString(); + return new ReadByQueryEqualToValue(path,key,val); + } + static void DoSave(string path, object arg) { if (arg is Fuse.Scripting.Object) From fffa4653c685a5223e530b79449fa9e8ae98764a Mon Sep 17 00:00:00 2001 From: Luis Rodriguez Date: Tue, 6 Feb 2018 22:27:28 -0600 Subject: [PATCH 15/47] docs fix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index db93851..a550bed 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ firebaseDb.read(path) ### Read Data with Query -Sometimes you need to search for a certain value in an object, instead or iterating in the cliente +Sometimes you need to search for a certain value in an object, instead or iterating in the client use this implementation to let the Firebase do the query for you. The following example will give you all the objects where the key name is equal to Luis Rodriguez, @@ -91,7 +91,7 @@ firebaseDb.readByQueryEqualToValue("users","name","Luis Rodriguez") var user = JSON.parse(json); }) .catch(function (reason) { - console.log('Unable to read path: ' + path); + console.log('Unable to read -> ' +reason); }); ``` From caf744f266ec839a5b6b064b0d4a3f374b313cf7 Mon Sep 17 00:00:00 2001 From: Pavel Kostenko Date: Mon, 12 Feb 2018 12:14:55 +0600 Subject: [PATCH 16/47] * fix deprecated messages during `fuse preview -t=iOS`, after upgrading to FuseTools 1.6.1 --- src/Firebase.Authentication.Facebook/JS.uno | 6 ++++-- src/Firebase.Authentication.Google/JS.uno | 3 ++- src/Firebase.Authentication/JS.uno | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Firebase.Authentication.Facebook/JS.uno b/src/Firebase.Authentication.Facebook/JS.uno index cb8d166..ed97517 100644 --- a/src/Firebase.Authentication.Facebook/JS.uno +++ b/src/Firebase.Authentication.Facebook/JS.uno @@ -35,12 +35,14 @@ namespace Firebase.Authentication.Facebook.JS static void Auth(string token) { - _onAuth.RaiseAsync(token); + _onAuth.RaiseAsync(_onAuth.Context.ThreadWorker, token); + //_onAuth.RaiseAsync(token); } static void OnFailed(string err) { - _onError.RaiseAsync(err); + _onError.RaiseAsync(_onError.Context.ThreadWorker, err); + //_onError.RaiseAsync(err); } object DoFacebookLogin(Context context, object[] args) diff --git a/src/Firebase.Authentication.Google/JS.uno b/src/Firebase.Authentication.Google/JS.uno index cb9431e..37fc1e0 100644 --- a/src/Firebase.Authentication.Google/JS.uno +++ b/src/Firebase.Authentication.Google/JS.uno @@ -31,7 +31,8 @@ namespace Firebase.Authentication.Google.JS static void Auth(string idToken, string accessToken) { - _onAuth.RaiseAsync(idToken, accessToken); + _onAuth.RaiseAsync(_onAuth.Context.ThreadWorker, idToken, accessToken); + //_onAuth.RaiseAsync(idToken, accessToken); } } } diff --git a/src/Firebase.Authentication/JS.uno b/src/Firebase.Authentication/JS.uno index 996b962..64e3c43 100644 --- a/src/Firebase.Authentication/JS.uno +++ b/src/Firebase.Authentication/JS.uno @@ -103,13 +103,15 @@ namespace Firebase.Authentication.JS static void OnUser() { var isSignedIn = GetSignedIn(); - _onSignInChanged.RaiseAsync(isSignedIn); + _onSignInChanged.RaiseAsync(_onSignInChanged.Context.ThreadWorker, isSignedIn); + //_onSignInChanged.RaiseAsync(isSignedIn); _instance.Emit("signedInStateChanged", isSignedIn); } static void OnError(int errorCode, string message) { - _onError.RaiseAsync(message, errorCode); + //_onError.RaiseAsync(message, errorCode); + _onError.RaiseAsync(_onError.Context.ThreadWorker, errorCode); _instance.Emit("error", message, errorCode); } From 3185d642bcd2328957d8aa0b72a4a30bdcd396eb Mon Sep 17 00:00:00 2001 From: Luis Rodriguez Date: Wed, 14 Feb 2018 14:00:57 -0600 Subject: [PATCH 17/47] Fixed extern !mobile and arguments in query I do not know what I was thinking, I have two FuseFirebase repos, must have missed this. --- src/Firebase.Database/Database.uno | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index 84cfae6..546fa16 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -656,6 +656,7 @@ namespace Firebase.Database } } + extern(!mobile) internal class ReadByQueryEqualToValue : Promise { public ReadByQueryEqualToValue(string path, string key, string val) @@ -787,7 +788,7 @@ namespace Firebase.Database internal class ReadByQueryEqualToValue : Promise { [Foreign(Language.Java)] - public ReadByQueryEqualToValue(string path) + public ReadByQueryEqualToValue(string path, string key, string val) @{ ValueEventListener dataListener = new ValueEventListener() { @Override From f10d0364de511d1b944a0bbe343ad44fe99d9bcd Mon Sep 17 00:00:00 2001 From: Luis Rodriguez Date: Wed, 14 Feb 2018 23:58:29 -0600 Subject: [PATCH 18/47] simple storage added, uploads picture and returns URL part of this code was written by Bolav --- README.md | 37 ++++- src/Firebase.Storage/Firebase.Storage.unoproj | 12 ++ src/Firebase.Storage/JS.uno | 33 +++++ src/Firebase.Storage/Storage.uno | 128 ++++++++++++++++++ 4 files changed, 204 insertions(+), 6 deletions(-) create mode 100755 src/Firebase.Storage/Firebase.Storage.unoproj create mode 100755 src/Firebase.Storage/JS.uno create mode 100755 src/Firebase.Storage/Storage.uno diff --git a/README.md b/README.md index 2f8d359..48d3e73 100644 --- a/README.md +++ b/README.md @@ -132,20 +132,20 @@ firebaseDb.listenOnAdded(messagesPath, 1); // function below will be executed for any path firebaseDb.on('dataAdded', function (eventPath, msg) { // msg here is a JSON string - + // track only given path if (eventPath === usersPath) { // new user record was added, usually by push method - // if you created record using not .push method or + // if you created record using not .push method or // pushWithTimestamp you will not receive event here console.log(eventPath); console.log(msg); var newUser = JSON.parse(msg); } - + if (eventPath === messagesPath) { // new message record was added, usually by push method - // if you created record using not .push method or + // if you created record using not .push method or // .pushWithTimestamp you will not receive event here console.log(eventPath); console.log(msg); @@ -175,7 +175,7 @@ firebaseDb.listenOnRemoved(messagesPath, 1); // function below will be executed for any path firebaseDb.on('dataRemoved', function (eventPath, msg) { // msg here is a JSON string - + // track only given path if (eventPath === usersPath) { // user record was removed @@ -183,7 +183,7 @@ firebaseDb.on('dataRemoved', function (eventPath, msg) { console.log(msg); var newUser = JSON.parse(msg); } - + if (eventPath === messagesPath) { // message record was removed console.log(eventPath); @@ -243,3 +243,28 @@ firebaseDb.listenOnRemoved(usersPath, 1); // do this, however this will also unsubscribe from `dataAdded` and `data` events firebaseDb.detachListeners(usersPath); ``` + +### Simple Storage +* For now, this uploads a picture to FirebaseStorage and returns the URL to access it. Part of this code was written by [Bolav](https://github.com/bolav). + +* Works great on both iOS and Android. + +* Also usable with `CameraRoll` and `ImageTools` + +```Javascript +var Camera = require("FuseJS/Camera"); +var Storage = require("Firebase/Storage"); +var path = "pictures/cats/mycat.jpg" + +Camera.takePicture(640,480).then(function(image) +{ + Storage.upload(path,image.path) // Make sure you use the path + .then(function(url){ + console.log(url); // Receives the URL as a promise + }).catch(function(err){ + console.log(err) + }) +}).catch(function(error) { + //Something went wrong, see error for details +}); +``` diff --git a/src/Firebase.Storage/Firebase.Storage.unoproj b/src/Firebase.Storage/Firebase.Storage.unoproj new file mode 100755 index 0000000..a70ae9e --- /dev/null +++ b/src/Firebase.Storage/Firebase.Storage.unoproj @@ -0,0 +1,12 @@ +{ + "Projects": [ + "../Firebase/Firebase.unoproj" + ], + "Packages": [ + "Fuse", + "FuseJS" + ], + "Includes": [ + "*" + ] +} diff --git a/src/Firebase.Storage/JS.uno b/src/Firebase.Storage/JS.uno new file mode 100755 index 0000000..303d45c --- /dev/null +++ b/src/Firebase.Storage/JS.uno @@ -0,0 +1,33 @@ +using Uno; +using Uno.UX; +using Uno.Threading; +using Uno.Text; +using Uno.Platform; +using Uno.Compiler.ExportTargetInterop; +using Uno.Collections; +using Fuse; +using Fuse.Scripting; +using Fuse.Reactive; + +namespace Firebase.Storage.JS +{ + [UXGlobalModule] + public sealed class StorageModule : NativeModule + { + static readonly StorageModule _instance; + public StorageModule() + { + if(_instance != null) return; + Uno.UX.Resource.SetGlobalKey(_instance = this, "Firebase/Storage"); + Firebase.Storage.StorageService.Init(); + AddMember(new NativePromise("upload", Upload, null)); + } + + static Future Upload(object[] args) + { + var storagepath = args[0].ToString(); + var filepath = args[1].ToString(); + return new Upload(storagepath, filepath); + } + } +} diff --git a/src/Firebase.Storage/Storage.uno b/src/Firebase.Storage/Storage.uno new file mode 100755 index 0000000..42d5198 --- /dev/null +++ b/src/Firebase.Storage/Storage.uno @@ -0,0 +1,128 @@ +using Uno; +using Uno.UX; +using Uno.Collections; +using Uno.Compiler.ExportTargetInterop; +using Fuse; +using Fuse.Triggers; +using Fuse.Controls; +using Fuse.Controls.Native; +using Fuse.Controls.Native.Android; +using Uno.Threading; + +namespace Firebase.Storage +{ + [ForeignInclude(Language.Java, + "com.google.firebase.storage.FirebaseStorage", + "com.google.firebase.storage.OnProgressListener", + "com.google.firebase.storage.StorageReference", + "com.google.firebase.storage.UploadTask")] + [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Storage'")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-storage:9.2.0")] + [extern(iOS) Require("Source.Import","FirebaseStorage/FirebaseStorage.h")] + extern(mobile) + static class StorageService + { + static bool _initialized; + extern(android) static Java.Object _handle; + extern(ios) public static ObjC.Object _handle; + + public static void Init() + { + if (!_initialized) + { + if defined(android) AndroidInit(); + if defined(ios) iOSInit(); + _initialized = true; + } + } + + [Foreign(Language.ObjC)] + extern(iOS) + public static void iOSInit() + @{ + [FIRStorage storage]; + @{_handle:Set([[FIRStorage storage] reference])}; + @} + + + [Foreign(Language.Java)] + extern(android) + public static void AndroidInit() + @{ + @{_handle:Set(FirebaseStorage.getInstance().getReference())}; + @} + } + + extern(!mobile) + static class StorageService + { + public static void Init() {} + } + + extern(!mobile) + internal class Upload : Promise + { + public Upload(string storagepath, string filepath) + { + Reject(new Exception("Not implemented on desktop")); + } + } + + [Require("Entity", "StorageService")] + [Require("Source.Include","@{StorageService:Include}")] + [extern(iOS) Require("Source.Import","FirebaseStorage/FirebaseStorage.h")] + extern(iOS) + internal class Upload : Promise + { + [Foreign(Language.ObjC)] + public Upload(string storagepath, string filepath) + @{ + FIRStorageReference *ref = @{StorageService._handle:Get()}; + NSURL *localFile = [NSURL fileURLWithPath:filepath]; + FIRStorageUploadTask *uploadTask = [[ref child:storagepath] putFile:localFile metadata:nil completion:^(FIRStorageMetadata *metadata, NSError *error) { + if (error != nil) { + NSString *erstr = [NSString stringWithFormat:@"Firebase Storage Upload Error: %@", error.localizedDescription]; + @{Upload:Of(_this).Reject(string):Call(erstr)}; + } else { + NSURL *downloadURL = metadata.downloadURL; + @{Upload:Of(_this).Resolve(string):Call([downloadURL absoluteString])}; + } + }]; + @} + void Reject(string reason) { Reject(new Exception(reason)); } + } + + [ForeignInclude(Language.Java, + "com.google.android.gms.tasks.OnFailureListener", + "com.google.android.gms.tasks.OnSuccessListener", + "com.google.firebase.storage.FirebaseStorage", + "com.google.firebase.storage.OnProgressListener", + "com.google.firebase.storage.StorageReference", + "com.google.firebase.storage.UploadTask", + "java.io.File", + "android.net.Uri")] + extern(Android) + internal class Upload : Promise + { + [Foreign(Language.Java)] + public Upload(string storagepath, string filepath) + @{ + StorageReference ref = (StorageReference)@{StorageService._handle:Get()}; + Uri file = Uri.fromFile(new File(filepath)); + StorageReference childRef = ref.child(storagepath); + + childRef.putFile(file).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(Exception exception) { + @{Upload:Of(_this).Reject(string):Call(exception.toString())}; + } + }).addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { + @{Upload:Of(_this).Resolve(string):Call(taskSnapshot.getDownloadUrl().toString())}; + } + }); + @} + void Reject(string reason) { Reject(new Exception(reason)); } + } +} From 1924b04bf50e35f2f2c085d63bd74746098abfde Mon Sep 17 00:00:00 2001 From: Mitul Golakiya Date: Fri, 16 Feb 2018 09:41:19 +0530 Subject: [PATCH 19/47] Revert "simple storage added, uploads picture and returns URL" This reverts commit f10d0364de511d1b944a0bbe343ad44fe99d9bcd. --- README.md | 37 +---- src/Firebase.Storage/Firebase.Storage.unoproj | 12 -- src/Firebase.Storage/JS.uno | 33 ----- src/Firebase.Storage/Storage.uno | 128 ------------------ 4 files changed, 6 insertions(+), 204 deletions(-) delete mode 100755 src/Firebase.Storage/Firebase.Storage.unoproj delete mode 100755 src/Firebase.Storage/JS.uno delete mode 100755 src/Firebase.Storage/Storage.uno diff --git a/README.md b/README.md index 48d3e73..2f8d359 100644 --- a/README.md +++ b/README.md @@ -132,20 +132,20 @@ firebaseDb.listenOnAdded(messagesPath, 1); // function below will be executed for any path firebaseDb.on('dataAdded', function (eventPath, msg) { // msg here is a JSON string - + // track only given path if (eventPath === usersPath) { // new user record was added, usually by push method - // if you created record using not .push method or + // if you created record using not .push method or // pushWithTimestamp you will not receive event here console.log(eventPath); console.log(msg); var newUser = JSON.parse(msg); } - + if (eventPath === messagesPath) { // new message record was added, usually by push method - // if you created record using not .push method or + // if you created record using not .push method or // .pushWithTimestamp you will not receive event here console.log(eventPath); console.log(msg); @@ -175,7 +175,7 @@ firebaseDb.listenOnRemoved(messagesPath, 1); // function below will be executed for any path firebaseDb.on('dataRemoved', function (eventPath, msg) { // msg here is a JSON string - + // track only given path if (eventPath === usersPath) { // user record was removed @@ -183,7 +183,7 @@ firebaseDb.on('dataRemoved', function (eventPath, msg) { console.log(msg); var newUser = JSON.parse(msg); } - + if (eventPath === messagesPath) { // message record was removed console.log(eventPath); @@ -243,28 +243,3 @@ firebaseDb.listenOnRemoved(usersPath, 1); // do this, however this will also unsubscribe from `dataAdded` and `data` events firebaseDb.detachListeners(usersPath); ``` - -### Simple Storage -* For now, this uploads a picture to FirebaseStorage and returns the URL to access it. Part of this code was written by [Bolav](https://github.com/bolav). - -* Works great on both iOS and Android. - -* Also usable with `CameraRoll` and `ImageTools` - -```Javascript -var Camera = require("FuseJS/Camera"); -var Storage = require("Firebase/Storage"); -var path = "pictures/cats/mycat.jpg" - -Camera.takePicture(640,480).then(function(image) -{ - Storage.upload(path,image.path) // Make sure you use the path - .then(function(url){ - console.log(url); // Receives the URL as a promise - }).catch(function(err){ - console.log(err) - }) -}).catch(function(error) { - //Something went wrong, see error for details -}); -``` diff --git a/src/Firebase.Storage/Firebase.Storage.unoproj b/src/Firebase.Storage/Firebase.Storage.unoproj deleted file mode 100755 index a70ae9e..0000000 --- a/src/Firebase.Storage/Firebase.Storage.unoproj +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Projects": [ - "../Firebase/Firebase.unoproj" - ], - "Packages": [ - "Fuse", - "FuseJS" - ], - "Includes": [ - "*" - ] -} diff --git a/src/Firebase.Storage/JS.uno b/src/Firebase.Storage/JS.uno deleted file mode 100755 index 303d45c..0000000 --- a/src/Firebase.Storage/JS.uno +++ /dev/null @@ -1,33 +0,0 @@ -using Uno; -using Uno.UX; -using Uno.Threading; -using Uno.Text; -using Uno.Platform; -using Uno.Compiler.ExportTargetInterop; -using Uno.Collections; -using Fuse; -using Fuse.Scripting; -using Fuse.Reactive; - -namespace Firebase.Storage.JS -{ - [UXGlobalModule] - public sealed class StorageModule : NativeModule - { - static readonly StorageModule _instance; - public StorageModule() - { - if(_instance != null) return; - Uno.UX.Resource.SetGlobalKey(_instance = this, "Firebase/Storage"); - Firebase.Storage.StorageService.Init(); - AddMember(new NativePromise("upload", Upload, null)); - } - - static Future Upload(object[] args) - { - var storagepath = args[0].ToString(); - var filepath = args[1].ToString(); - return new Upload(storagepath, filepath); - } - } -} diff --git a/src/Firebase.Storage/Storage.uno b/src/Firebase.Storage/Storage.uno deleted file mode 100755 index 42d5198..0000000 --- a/src/Firebase.Storage/Storage.uno +++ /dev/null @@ -1,128 +0,0 @@ -using Uno; -using Uno.UX; -using Uno.Collections; -using Uno.Compiler.ExportTargetInterop; -using Fuse; -using Fuse.Triggers; -using Fuse.Controls; -using Fuse.Controls.Native; -using Fuse.Controls.Native.Android; -using Uno.Threading; - -namespace Firebase.Storage -{ - [ForeignInclude(Language.Java, - "com.google.firebase.storage.FirebaseStorage", - "com.google.firebase.storage.OnProgressListener", - "com.google.firebase.storage.StorageReference", - "com.google.firebase.storage.UploadTask")] - [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Storage'")] - [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-storage:9.2.0")] - [extern(iOS) Require("Source.Import","FirebaseStorage/FirebaseStorage.h")] - extern(mobile) - static class StorageService - { - static bool _initialized; - extern(android) static Java.Object _handle; - extern(ios) public static ObjC.Object _handle; - - public static void Init() - { - if (!_initialized) - { - if defined(android) AndroidInit(); - if defined(ios) iOSInit(); - _initialized = true; - } - } - - [Foreign(Language.ObjC)] - extern(iOS) - public static void iOSInit() - @{ - [FIRStorage storage]; - @{_handle:Set([[FIRStorage storage] reference])}; - @} - - - [Foreign(Language.Java)] - extern(android) - public static void AndroidInit() - @{ - @{_handle:Set(FirebaseStorage.getInstance().getReference())}; - @} - } - - extern(!mobile) - static class StorageService - { - public static void Init() {} - } - - extern(!mobile) - internal class Upload : Promise - { - public Upload(string storagepath, string filepath) - { - Reject(new Exception("Not implemented on desktop")); - } - } - - [Require("Entity", "StorageService")] - [Require("Source.Include","@{StorageService:Include}")] - [extern(iOS) Require("Source.Import","FirebaseStorage/FirebaseStorage.h")] - extern(iOS) - internal class Upload : Promise - { - [Foreign(Language.ObjC)] - public Upload(string storagepath, string filepath) - @{ - FIRStorageReference *ref = @{StorageService._handle:Get()}; - NSURL *localFile = [NSURL fileURLWithPath:filepath]; - FIRStorageUploadTask *uploadTask = [[ref child:storagepath] putFile:localFile metadata:nil completion:^(FIRStorageMetadata *metadata, NSError *error) { - if (error != nil) { - NSString *erstr = [NSString stringWithFormat:@"Firebase Storage Upload Error: %@", error.localizedDescription]; - @{Upload:Of(_this).Reject(string):Call(erstr)}; - } else { - NSURL *downloadURL = metadata.downloadURL; - @{Upload:Of(_this).Resolve(string):Call([downloadURL absoluteString])}; - } - }]; - @} - void Reject(string reason) { Reject(new Exception(reason)); } - } - - [ForeignInclude(Language.Java, - "com.google.android.gms.tasks.OnFailureListener", - "com.google.android.gms.tasks.OnSuccessListener", - "com.google.firebase.storage.FirebaseStorage", - "com.google.firebase.storage.OnProgressListener", - "com.google.firebase.storage.StorageReference", - "com.google.firebase.storage.UploadTask", - "java.io.File", - "android.net.Uri")] - extern(Android) - internal class Upload : Promise - { - [Foreign(Language.Java)] - public Upload(string storagepath, string filepath) - @{ - StorageReference ref = (StorageReference)@{StorageService._handle:Get()}; - Uri file = Uri.fromFile(new File(filepath)); - StorageReference childRef = ref.child(storagepath); - - childRef.putFile(file).addOnFailureListener(new OnFailureListener() { - @Override - public void onFailure(Exception exception) { - @{Upload:Of(_this).Reject(string):Call(exception.toString())}; - } - }).addOnSuccessListener(new OnSuccessListener() { - @Override - public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { - @{Upload:Of(_this).Resolve(string):Call(taskSnapshot.getDownloadUrl().toString())}; - } - }); - @} - void Reject(string reason) { Reject(new Exception(reason)); } - } -} From 57e9a4c3da3458d3d0ae1ebe3d75b0bf20c6d6b3 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Fri, 16 Feb 2018 15:29:28 +0530 Subject: [PATCH 20/47] Remove _onSignInChanged event --- src/Firebase.Authentication/JS.uno | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Firebase.Authentication/JS.uno b/src/Firebase.Authentication/JS.uno index 64e3c43..5430c97 100644 --- a/src/Firebase.Authentication/JS.uno +++ b/src/Firebase.Authentication/JS.uno @@ -103,8 +103,6 @@ namespace Firebase.Authentication.JS static void OnUser() { var isSignedIn = GetSignedIn(); - _onSignInChanged.RaiseAsync(_onSignInChanged.Context.ThreadWorker, isSignedIn); - //_onSignInChanged.RaiseAsync(isSignedIn); _instance.Emit("signedInStateChanged", isSignedIn); } From 663f6f518026b8fce1b3710ae785ece88cbb16f0 Mon Sep 17 00:00:00 2001 From: Hiren Bharodiya Date: Tue, 20 Feb 2018 15:22:59 +0530 Subject: [PATCH 21/47] Update README.md --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/README.md b/README.md index 2f8d359..a6d0eb9 100644 --- a/README.md +++ b/README.md @@ -243,3 +243,45 @@ firebaseDb.listenOnRemoved(usersPath, 1); // do this, however this will also unsubscribe from `dataAdded` and `data` events firebaseDb.detachListeners(usersPath); ``` + +### Upload an Image to Firebase + +* Upload an image using Camera + +```JavaScript +var Camera = require('FuseJS/Camera'); + +var imagePath = "images/test.jpg"; +Camera.takePicture(640,480).then(function(image) { + + Storage.upload(imagePath, image.path) // Make sure you use the path + .then(function(url) { + console.log('url' + url); // Receives the URL as a promise + }).catch(function(err) { + console.log('err' + err); + }) +}).catch(function(error) { + //Something went wrong, see error for details + console.log('error ' + error); +}); +``` + +* Upload an image using CameraRoll/Gallery + +```JavaScript +var CameraRoll = require("FuseJS/CameraRoll"); + +var imagePath = "images/test.jpg"; +CameraRoll.getImage() +.then(function(image) { + Storage.upload(imagePath, image.path) // Make sure you use the path + .then(function(url) { + console.log('url ' + url); // Receives the URL as a promise + }).catch(function(err) { + console.log('err ' + err); + }) +}, function(error) { + // Will be called if the user aborted the selection or if an error occurred. + console.log('error ' + error); +}); +``` From 63701b7eab64b4957277463ec940c704dbccf3f0 Mon Sep 17 00:00:00 2001 From: HirenBharodiya Date: Tue, 20 Feb 2018 15:38:45 +0530 Subject: [PATCH 22/47] Revert "Revert "simple storage added, uploads picture and returns URL"" This reverts commit 1924b04bf50e35f2f2c085d63bd74746098abfde. # Conflicts: # README.md --- README.md | 37 ++++- src/Firebase.Storage/Firebase.Storage.unoproj | 12 ++ src/Firebase.Storage/JS.uno | 33 +++++ src/Firebase.Storage/Storage.uno | 128 ++++++++++++++++++ 4 files changed, 204 insertions(+), 6 deletions(-) create mode 100755 src/Firebase.Storage/Firebase.Storage.unoproj create mode 100755 src/Firebase.Storage/JS.uno create mode 100755 src/Firebase.Storage/Storage.uno diff --git a/README.md b/README.md index a6d0eb9..a4b50cb 100644 --- a/README.md +++ b/README.md @@ -132,20 +132,20 @@ firebaseDb.listenOnAdded(messagesPath, 1); // function below will be executed for any path firebaseDb.on('dataAdded', function (eventPath, msg) { // msg here is a JSON string - + // track only given path if (eventPath === usersPath) { // new user record was added, usually by push method - // if you created record using not .push method or + // if you created record using not .push method or // pushWithTimestamp you will not receive event here console.log(eventPath); console.log(msg); var newUser = JSON.parse(msg); } - + if (eventPath === messagesPath) { // new message record was added, usually by push method - // if you created record using not .push method or + // if you created record using not .push method or // .pushWithTimestamp you will not receive event here console.log(eventPath); console.log(msg); @@ -175,7 +175,7 @@ firebaseDb.listenOnRemoved(messagesPath, 1); // function below will be executed for any path firebaseDb.on('dataRemoved', function (eventPath, msg) { // msg here is a JSON string - + // track only given path if (eventPath === usersPath) { // user record was removed @@ -183,7 +183,7 @@ firebaseDb.on('dataRemoved', function (eventPath, msg) { console.log(msg); var newUser = JSON.parse(msg); } - + if (eventPath === messagesPath) { // message record was removed console.log(eventPath); @@ -250,6 +250,7 @@ firebaseDb.detachListeners(usersPath); ```JavaScript var Camera = require('FuseJS/Camera'); +var Storage = require('Firebase/Storage'); var imagePath = "images/test.jpg"; Camera.takePicture(640,480).then(function(image) { @@ -270,6 +271,7 @@ Camera.takePicture(640,480).then(function(image) { ```JavaScript var CameraRoll = require("FuseJS/CameraRoll"); +var Storage = require('Firebase/Storage'); var imagePath = "images/test.jpg"; CameraRoll.getImage() @@ -283,5 +285,28 @@ CameraRoll.getImage() }, function(error) { // Will be called if the user aborted the selection or if an error occurred. console.log('error ' + error); + +### Simple Storage +* For now, this uploads a picture to FirebaseStorage and returns the URL to access it. Part of this code was written by [Bolav](https://github.com/bolav). + +* Works great on both iOS and Android. + +* Also usable with `CameraRoll` and `ImageTools` + +```Javascript +var Camera = require("FuseJS/Camera"); +var Storage = require("Firebase/Storage"); +var path = "pictures/cats/mycat.jpg" + +Camera.takePicture(640,480).then(function(image) +{ + Storage.upload(path,image.path) // Make sure you use the path + .then(function(url){ + console.log(url); // Receives the URL as a promise + }).catch(function(err){ + console.log(err) + }) +}).catch(function(error) { + //Something went wrong, see error for details }); ``` diff --git a/src/Firebase.Storage/Firebase.Storage.unoproj b/src/Firebase.Storage/Firebase.Storage.unoproj new file mode 100755 index 0000000..a70ae9e --- /dev/null +++ b/src/Firebase.Storage/Firebase.Storage.unoproj @@ -0,0 +1,12 @@ +{ + "Projects": [ + "../Firebase/Firebase.unoproj" + ], + "Packages": [ + "Fuse", + "FuseJS" + ], + "Includes": [ + "*" + ] +} diff --git a/src/Firebase.Storage/JS.uno b/src/Firebase.Storage/JS.uno new file mode 100755 index 0000000..303d45c --- /dev/null +++ b/src/Firebase.Storage/JS.uno @@ -0,0 +1,33 @@ +using Uno; +using Uno.UX; +using Uno.Threading; +using Uno.Text; +using Uno.Platform; +using Uno.Compiler.ExportTargetInterop; +using Uno.Collections; +using Fuse; +using Fuse.Scripting; +using Fuse.Reactive; + +namespace Firebase.Storage.JS +{ + [UXGlobalModule] + public sealed class StorageModule : NativeModule + { + static readonly StorageModule _instance; + public StorageModule() + { + if(_instance != null) return; + Uno.UX.Resource.SetGlobalKey(_instance = this, "Firebase/Storage"); + Firebase.Storage.StorageService.Init(); + AddMember(new NativePromise("upload", Upload, null)); + } + + static Future Upload(object[] args) + { + var storagepath = args[0].ToString(); + var filepath = args[1].ToString(); + return new Upload(storagepath, filepath); + } + } +} diff --git a/src/Firebase.Storage/Storage.uno b/src/Firebase.Storage/Storage.uno new file mode 100755 index 0000000..42d5198 --- /dev/null +++ b/src/Firebase.Storage/Storage.uno @@ -0,0 +1,128 @@ +using Uno; +using Uno.UX; +using Uno.Collections; +using Uno.Compiler.ExportTargetInterop; +using Fuse; +using Fuse.Triggers; +using Fuse.Controls; +using Fuse.Controls.Native; +using Fuse.Controls.Native.Android; +using Uno.Threading; + +namespace Firebase.Storage +{ + [ForeignInclude(Language.Java, + "com.google.firebase.storage.FirebaseStorage", + "com.google.firebase.storage.OnProgressListener", + "com.google.firebase.storage.StorageReference", + "com.google.firebase.storage.UploadTask")] + [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Storage'")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-storage:9.2.0")] + [extern(iOS) Require("Source.Import","FirebaseStorage/FirebaseStorage.h")] + extern(mobile) + static class StorageService + { + static bool _initialized; + extern(android) static Java.Object _handle; + extern(ios) public static ObjC.Object _handle; + + public static void Init() + { + if (!_initialized) + { + if defined(android) AndroidInit(); + if defined(ios) iOSInit(); + _initialized = true; + } + } + + [Foreign(Language.ObjC)] + extern(iOS) + public static void iOSInit() + @{ + [FIRStorage storage]; + @{_handle:Set([[FIRStorage storage] reference])}; + @} + + + [Foreign(Language.Java)] + extern(android) + public static void AndroidInit() + @{ + @{_handle:Set(FirebaseStorage.getInstance().getReference())}; + @} + } + + extern(!mobile) + static class StorageService + { + public static void Init() {} + } + + extern(!mobile) + internal class Upload : Promise + { + public Upload(string storagepath, string filepath) + { + Reject(new Exception("Not implemented on desktop")); + } + } + + [Require("Entity", "StorageService")] + [Require("Source.Include","@{StorageService:Include}")] + [extern(iOS) Require("Source.Import","FirebaseStorage/FirebaseStorage.h")] + extern(iOS) + internal class Upload : Promise + { + [Foreign(Language.ObjC)] + public Upload(string storagepath, string filepath) + @{ + FIRStorageReference *ref = @{StorageService._handle:Get()}; + NSURL *localFile = [NSURL fileURLWithPath:filepath]; + FIRStorageUploadTask *uploadTask = [[ref child:storagepath] putFile:localFile metadata:nil completion:^(FIRStorageMetadata *metadata, NSError *error) { + if (error != nil) { + NSString *erstr = [NSString stringWithFormat:@"Firebase Storage Upload Error: %@", error.localizedDescription]; + @{Upload:Of(_this).Reject(string):Call(erstr)}; + } else { + NSURL *downloadURL = metadata.downloadURL; + @{Upload:Of(_this).Resolve(string):Call([downloadURL absoluteString])}; + } + }]; + @} + void Reject(string reason) { Reject(new Exception(reason)); } + } + + [ForeignInclude(Language.Java, + "com.google.android.gms.tasks.OnFailureListener", + "com.google.android.gms.tasks.OnSuccessListener", + "com.google.firebase.storage.FirebaseStorage", + "com.google.firebase.storage.OnProgressListener", + "com.google.firebase.storage.StorageReference", + "com.google.firebase.storage.UploadTask", + "java.io.File", + "android.net.Uri")] + extern(Android) + internal class Upload : Promise + { + [Foreign(Language.Java)] + public Upload(string storagepath, string filepath) + @{ + StorageReference ref = (StorageReference)@{StorageService._handle:Get()}; + Uri file = Uri.fromFile(new File(filepath)); + StorageReference childRef = ref.child(storagepath); + + childRef.putFile(file).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(Exception exception) { + @{Upload:Of(_this).Reject(string):Call(exception.toString())}; + } + }).addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { + @{Upload:Of(_this).Resolve(string):Call(taskSnapshot.getDownloadUrl().toString())}; + } + }); + @} + void Reject(string reason) { Reject(new Exception(reason)); } + } +} From be82c8af72fce063d7d78e6761b94a0cb13dfc73 Mon Sep 17 00:00:00 2001 From: Hiren Bharodiya Date: Tue, 20 Feb 2018 15:41:12 +0530 Subject: [PATCH 23/47] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a4b50cb..62ecc97 100644 --- a/README.md +++ b/README.md @@ -285,6 +285,7 @@ CameraRoll.getImage() }, function(error) { // Will be called if the user aborted the selection or if an error occurred. console.log('error ' + error); +``` ### Simple Storage * For now, this uploads a picture to FirebaseStorage and returns the URL to access it. Part of this code was written by [Bolav](https://github.com/bolav). From 58f574f55093fd2dfc5c67ed7143f9b9afe83c9c Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Thu, 22 Feb 2018 08:12:18 +0530 Subject: [PATCH 24/47] Add missimg message parameter in Authentication error event --- src/Firebase.Authentication/JS.uno | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Firebase.Authentication/JS.uno b/src/Firebase.Authentication/JS.uno index 5430c97..9ea5628 100644 --- a/src/Firebase.Authentication/JS.uno +++ b/src/Firebase.Authentication/JS.uno @@ -109,12 +109,10 @@ namespace Firebase.Authentication.JS static void OnError(int errorCode, string message) { //_onError.RaiseAsync(message, errorCode); - _onError.RaiseAsync(_onError.Context.ThreadWorker, errorCode); + _onError.RaiseAsync(_onError.Context.ThreadWorker, message, errorCode); _instance.Emit("error", message, errorCode); } - - // functions static Future GetToken(object[] arg) { From c0c46fe3a97283d7b98f81640c1860d1a5517441 Mon Sep 17 00:00:00 2001 From: Hiren Bharodiya Date: Thu, 22 Feb 2018 11:08:27 +0530 Subject: [PATCH 25/47] Update README.md --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 62ecc97..2ecf448 100644 --- a/README.md +++ b/README.md @@ -311,3 +311,23 @@ Camera.takePicture(640,480).then(function(image) //Something went wrong, see error for details }); ``` + +### Read Data with Query + +* Get all the objects where the key name is equal to pavel + +```Javascript +var path = user; +var key = name; +var value = ‘pavel’; + +firebaseDb.readByQueryEqualToValue(path, key, value) +.then(function (json) { + // here json is a JSON string + console.log('json '+ json); + var user = JSON.parse(json); +}) +.catch(function (reason) { + console.log('Unable to read -> ' + reason); +}); +``` From e96ec9bce779c3df4717c018aca55b9752dc16b8 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Tue, 27 Feb 2018 19:43:32 +0530 Subject: [PATCH 26/47] Add function to get FCM token in android --- src/Firebase.Notifications.Android/Common.uno | 23 +++++++++++++++++++ src/Firebase.Notifications.Android/JS.uno | 10 ++++++++ 2 files changed, 33 insertions(+) diff --git a/src/Firebase.Notifications.Android/Common.uno b/src/Firebase.Notifications.Android/Common.uno index 50263ad..580e355 100644 --- a/src/Firebase.Notifications.Android/Common.uno +++ b/src/Firebase.Notifications.Android/Common.uno @@ -10,6 +10,9 @@ using Uno.Threading; namespace Firebase.Notifications { [Require("Entity","Firebase.Core.Init()")] + [ForeignInclude(Language.Java, + "android.util.Log", + "com.google.firebase.iid.FirebaseInstanceId")] public static class NotificationService { extern(!Android) @@ -143,5 +146,25 @@ namespace Firebase.Notifications @} public extern(!iOS && !Android) static void ClearAllNotifications() { } + + [Foreign(Language.ObjC)] + public extern(iOS) static String GetFCMToken() + @{ + // [UIApplication sharedApplication].applicationIconBadgeNumber = 1; + // [UIApplication sharedApplication].applicationIconBadgeNumber = 0; + return @""; + @} + + [Foreign(Language.Java)] + public extern(Android) static String GetFCMToken() + @{ + String refreshedToken = FirebaseInstanceId.getInstance().getToken(); + Log.d("TOKEN", "Refreshed token: " + refreshedToken); + return refreshedToken; + @} + + public extern(!iOS && !Android) static String GetFCMToken() { return ""; } + + } } diff --git a/src/Firebase.Notifications.Android/JS.uno b/src/Firebase.Notifications.Android/JS.uno index fe4112c..66b2224 100644 --- a/src/Firebase.Notifications.Android/JS.uno +++ b/src/Firebase.Notifications.Android/JS.uno @@ -59,6 +59,7 @@ namespace Firebase.Notifications AddMember(onRegistrationFailed); AddMember(new NativeFunction("clearBadgeNumber", ClearBadgeNumber)); AddMember(new NativeFunction("clearAllNotifications", ClearAllNotifications)); + AddMember(new NativeFunction("getFCMToken", GetFCMToken)); _onRegistrationSucceedediOS = new NativeEvent("onRegistrationSucceedediOS"); AddMember(_onRegistrationSucceedediOS); @@ -127,5 +128,14 @@ namespace Firebase.Notifications Firebase.Notifications.NotificationService.ClearAllNotifications(); return null; } + + public object GetFCMToken(Context context, object[] args) + { + var token = Firebase.Notifications.NotificationService.GetFCMToken(); + if (token != null) { + Emit("registrationSucceeded", token); + } + return null; + } } } From cf1b91fd68a4a1e8da0340a5ac4ad574e0ac2f37 Mon Sep 17 00:00:00 2001 From: Luis Rodriguez Date: Tue, 27 Feb 2018 21:27:14 -0600 Subject: [PATCH 27/47] Better queries You can now query booleans and numbers --- src/Firebase.Database/Database.uno | 17 +++++++++++++---- src/Firebase.Database/JS.uno | 22 ++++++++++++++++++++-- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index 546fa16..76ea34c 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -659,7 +659,7 @@ namespace Firebase.Database extern(!mobile) internal class ReadByQueryEqualToValue : Promise { - public ReadByQueryEqualToValue(string path, string key, string val) + public ReadByQueryEqualToValue(string path, string key, object val) { Reject(new Exception("Not implemented on desktop")); } @@ -703,7 +703,7 @@ namespace Firebase.Database internal class ReadByQueryEqualToValue : Promise { [Foreign(Language.ObjC)] - public ReadByQueryEqualToValue(string path, string key, string val) + public ReadByQueryEqualToValue(string path, string key, ObjC.Object val) @{ FIRDatabaseReference *ref = @{DatabaseService._handle:Get()}; @@ -788,7 +788,7 @@ namespace Firebase.Database internal class ReadByQueryEqualToValue : Promise { [Foreign(Language.Java)] - public ReadByQueryEqualToValue(string path, string key, string val) + public ReadByQueryEqualToValue(string path, string key, Java.Object val) @{ ValueEventListener dataListener = new ValueEventListener() { @Override @@ -815,7 +815,16 @@ namespace Firebase.Database } }; DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; - ref.child(path).orderByChild(key).equalTo(val).addListenerForSingleValueEvent(dataListener); + if(val instanceof String){ + String obj = (String) val; + ref.child(path).orderByChild(key).equalTo(obj).addListenerForSingleValueEvent(dataListener); + } else if (val instanceof Double){ + Double obj = (Double) val; + ref.child(path).orderByChild(key).equalTo(obj).addListenerForSingleValueEvent(dataListener); + } else if( val instanceof Boolean ){ + Boolean obj = (Boolean) val; + ref.child(path).orderByChild(key).equalTo(obj).addListenerForSingleValueEvent(dataListener); + } @} void Reject(string reason) { Reject(new Exception(reason)); } } diff --git a/src/Firebase.Database/JS.uno b/src/Firebase.Database/JS.uno index 35e5816..37b4716 100644 --- a/src/Firebase.Database/JS.uno +++ b/src/Firebase.Database/JS.uno @@ -74,8 +74,26 @@ namespace Firebase.Database.JS { var path = args[0].ToString(); var key = args[1].ToString(); - var val = args[2].ToString(); - return new ReadByQueryEqualToValue(path,key,val); + var val = args[2]; + + if defined(iOS) + { + return new ReadEqualTo( + path, key, + JSON.ObjCObject.FromJSON(JSON.ScriptingValue.ToJSON(val)) + ); + } + else if defined(Android) + { + return new ReadEqualTo( + path, key, + JSON.JavaObject.FromJSON(JSON.ScriptingValue.ToJSON(val)) + ); + } + else + { + return new ReadEqualTo(path,key,val); + } } static void DoSave(string path, object arg) From f83797a010ec7fff783c53fbe8cccdb46c5c00c3 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Wed, 28 Feb 2018 12:25:42 +0530 Subject: [PATCH 28/47] Add capability to get FCM token via function in iOS --- src/Firebase.Notifications.Android/Common.uno | 6 +++--- src/Firebase.Notifications.Android/JS.uno | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Firebase.Notifications.Android/Common.uno b/src/Firebase.Notifications.Android/Common.uno index 580e355..5b2539e 100644 --- a/src/Firebase.Notifications.Android/Common.uno +++ b/src/Firebase.Notifications.Android/Common.uno @@ -13,6 +13,7 @@ namespace Firebase.Notifications [ForeignInclude(Language.Java, "android.util.Log", "com.google.firebase.iid.FirebaseInstanceId")] + [extern(iOS) Require("Source.Include", "Firebase/Firebase.h")] public static class NotificationService { extern(!Android) @@ -150,9 +151,8 @@ namespace Firebase.Notifications [Foreign(Language.ObjC)] public extern(iOS) static String GetFCMToken() @{ - // [UIApplication sharedApplication].applicationIconBadgeNumber = 1; - // [UIApplication sharedApplication].applicationIconBadgeNumber = 0; - return @""; + NSString *fcmToken = [[FIRInstanceID instanceID] token]; + return fcmToken; @} [Foreign(Language.Java)] diff --git a/src/Firebase.Notifications.Android/JS.uno b/src/Firebase.Notifications.Android/JS.uno index 66b2224..6a7e335 100644 --- a/src/Firebase.Notifications.Android/JS.uno +++ b/src/Firebase.Notifications.Android/JS.uno @@ -91,7 +91,8 @@ namespace Firebase.Notifications } static void OnRegistrationSucceedediOS(string message) { - _onRegistrationSucceedediOS.RaiseAsync(message); + //_onRegistrationSucceedediOS.RaiseAsync(message); + // App is getting crash sometimes at this function and now we are getting FCM token via GetFCMToken(), so we can put it in comment } /** From edf39a5b0407321fae8cbf1d4d5ba04c91bd31a7 Mon Sep 17 00:00:00 2001 From: HirenBharodiya Date: Tue, 6 Mar 2018 12:05:02 +0530 Subject: [PATCH 29/47] Revert "Merge branch 'better-query' of https://github.com/LuisRodriguezLD/Fuse.Firebase into LuisRodriguezLD-better-query" This reverts commit a4a8741c3c5006b82cde4a76ca570d633f427722, reversing changes made to f83797a010ec7fff783c53fbe8cccdb46c5c00c3. --- src/Firebase.Database/Database.uno | 17 ++++------------- src/Firebase.Database/JS.uno | 22 ++-------------------- 2 files changed, 6 insertions(+), 33 deletions(-) diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index 76ea34c..546fa16 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -659,7 +659,7 @@ namespace Firebase.Database extern(!mobile) internal class ReadByQueryEqualToValue : Promise { - public ReadByQueryEqualToValue(string path, string key, object val) + public ReadByQueryEqualToValue(string path, string key, string val) { Reject(new Exception("Not implemented on desktop")); } @@ -703,7 +703,7 @@ namespace Firebase.Database internal class ReadByQueryEqualToValue : Promise { [Foreign(Language.ObjC)] - public ReadByQueryEqualToValue(string path, string key, ObjC.Object val) + public ReadByQueryEqualToValue(string path, string key, string val) @{ FIRDatabaseReference *ref = @{DatabaseService._handle:Get()}; @@ -788,7 +788,7 @@ namespace Firebase.Database internal class ReadByQueryEqualToValue : Promise { [Foreign(Language.Java)] - public ReadByQueryEqualToValue(string path, string key, Java.Object val) + public ReadByQueryEqualToValue(string path, string key, string val) @{ ValueEventListener dataListener = new ValueEventListener() { @Override @@ -815,16 +815,7 @@ namespace Firebase.Database } }; DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; - if(val instanceof String){ - String obj = (String) val; - ref.child(path).orderByChild(key).equalTo(obj).addListenerForSingleValueEvent(dataListener); - } else if (val instanceof Double){ - Double obj = (Double) val; - ref.child(path).orderByChild(key).equalTo(obj).addListenerForSingleValueEvent(dataListener); - } else if( val instanceof Boolean ){ - Boolean obj = (Boolean) val; - ref.child(path).orderByChild(key).equalTo(obj).addListenerForSingleValueEvent(dataListener); - } + ref.child(path).orderByChild(key).equalTo(val).addListenerForSingleValueEvent(dataListener); @} void Reject(string reason) { Reject(new Exception(reason)); } } diff --git a/src/Firebase.Database/JS.uno b/src/Firebase.Database/JS.uno index 37b4716..35e5816 100644 --- a/src/Firebase.Database/JS.uno +++ b/src/Firebase.Database/JS.uno @@ -74,26 +74,8 @@ namespace Firebase.Database.JS { var path = args[0].ToString(); var key = args[1].ToString(); - var val = args[2]; - - if defined(iOS) - { - return new ReadEqualTo( - path, key, - JSON.ObjCObject.FromJSON(JSON.ScriptingValue.ToJSON(val)) - ); - } - else if defined(Android) - { - return new ReadEqualTo( - path, key, - JSON.JavaObject.FromJSON(JSON.ScriptingValue.ToJSON(val)) - ); - } - else - { - return new ReadEqualTo(path,key,val); - } + var val = args[2].ToString(); + return new ReadByQueryEqualToValue(path,key,val); } static void DoSave(string path, object arg) From 9e4fc3572df6103bfe21523d68eb519e8bc48c8b Mon Sep 17 00:00:00 2001 From: Luis Rodriguez Date: Tue, 6 Mar 2018 00:46:38 -0600 Subject: [PATCH 30/47] name change I had the wrong name, sorry about that --- src/Firebase.Database/JS.uno | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Firebase.Database/JS.uno b/src/Firebase.Database/JS.uno index 37b4716..6737257 100644 --- a/src/Firebase.Database/JS.uno +++ b/src/Firebase.Database/JS.uno @@ -78,21 +78,21 @@ namespace Firebase.Database.JS if defined(iOS) { - return new ReadEqualTo( + return new ReadByQueryEqualToValue( path, key, JSON.ObjCObject.FromJSON(JSON.ScriptingValue.ToJSON(val)) ); } else if defined(Android) { - return new ReadEqualTo( + return new ReadByQueryEqualToValue( path, key, JSON.JavaObject.FromJSON(JSON.ScriptingValue.ToJSON(val)) ); } else { - return new ReadEqualTo(path,key,val); + return new ReadByQueryEqualToValue(path,key,val); } } From 598c69faf54805f3d4ee497fd335a229991eba92 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Mon, 19 Mar 2018 12:44:19 +0530 Subject: [PATCH 31/47] Fix: Endless loading loop at app startup --- .../FacebookAuthentication.uno | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno index 4b9f33b..9c59017 100644 --- a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno +++ b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno @@ -120,12 +120,13 @@ namespace Firebase.Authentication.Facebook.JS @{ final AccessToken token = (AccessToken)result; AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken()); - @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(token.getToken())}; FirebaseAuth.getInstance().signInWithCredential(credential) .addOnCompleteListener(com.fuse.Activity.getRootActivity(), new OnCompleteListener() { public void onComplete(Task task) { - if (task.isSuccessful()) + if (task.isSuccessful()) { + @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(token.getToken())}; @{OnSuccess(string):Call("Success")}; + } else @{OnFailure(string):Call("Authentication against Firebase failed")}; }}); @@ -143,7 +144,6 @@ namespace Firebase.Authentication.Facebook.JS return; } - @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(tokenStr)}; FIRAuthCredential* credential = [FIRFacebookAuthProvider credentialWithAccessToken:tokenStr]; // auth againsts firebase @@ -151,8 +151,10 @@ namespace Firebase.Authentication.Facebook.JS completion:^(FIRUser* fuser, NSError* ferror) { if (ferror) @{OnFailure(string):Call(@"Authentication against Firebase failed")}; - else - @{OnSuccess(string):Call(@"success")}; + else { + @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(tokenStr)}; + @{OnSuccess(string):Call(@"success")}; + } }]; @} From 3ef7be1e3433d651adfb3d7482dbc9384a97e97c Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Tue, 20 Mar 2018 10:53:14 +0530 Subject: [PATCH 32/47] Add try catch for Firebase read functions on Android --- src/Firebase.Database/Database.uno | 48 ++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index 76ea34c..9001fa6 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -96,8 +96,12 @@ namespace Firebase.Database if (dataSnapshot.getValue() == null) { return; } - JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); - f.run(path,json.toString()); + try { + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } catch (Throwable t) { + Log.e("Error ", "Could not Parse JSON: \"" + dataSnapshot.getValue() + "\""); + } } @Override @@ -161,8 +165,12 @@ namespace Firebase.Database if (dataSnapshot.getValue() == null) { return; } - JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); - f.run(path,json.toString()); + try { + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } catch (Throwable t) { + Log.e("Error ", "Could not Parse JSON: \"" + dataSnapshot.getValue() + "\""); + } } @Override @@ -216,8 +224,12 @@ namespace Firebase.Database if (dataSnapshot.getValue() == null) { return; } - JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); - f.run(path,json.toString()); + try { + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } catch (Throwable t) { + Log.e("Error ", "Could not Parse JSON: \"" + dataSnapshot.getValue() + "\""); + } } @Override @@ -282,8 +294,12 @@ namespace Firebase.Database if (dataSnapshot.getValue() == null) { return; } - JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); - f.run(path,json.toString()); + try { + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } catch (Throwable t) { + Log.e("Error ", "Could not Parse JSON: \"" + dataSnapshot.getValue() + "\""); + } } @Override @@ -348,8 +364,12 @@ namespace Firebase.Database if (dataSnapshot.getValue() == null) { return; } - JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); - f.run(path,json.toString()); + try { + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } catch (Throwable t) { + Log.e("Error ", "Could not Parse JSON: \"" + dataSnapshot.getValue() + "\""); + } } @Override @@ -407,8 +427,12 @@ namespace Firebase.Database @Override public void onDataChange(DataSnapshot dataSnapshot) { - JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); - f.run(path,json.toString()); + try { + JSONObject json = new JSONObject((Map)dataSnapshot.getValue()); + f.run(path,json.toString()); + } catch (Throwable t) { + Log.e("Error ", "Could not Parse JSON: \"" + dataSnapshot.getValue() + "\""); + } } @Override From 5d498cb865220a2ad6e10b884b7ebcbd07994467 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Thu, 22 Mar 2018 16:08:24 +0530 Subject: [PATCH 33/47] Remove Native Logs --- src/Firebase.Authentication/iOSImpl.uno | 2 -- src/Firebase.Notifications.Android/Common.uno | 1 - .../iOSFirebaseNotificationCallbacks.mm | 2 -- 3 files changed, 5 deletions(-) diff --git a/src/Firebase.Authentication/iOSImpl.uno b/src/Firebase.Authentication/iOSImpl.uno index 56491bf..8e849b6 100644 --- a/src/Firebase.Authentication/iOSImpl.uno +++ b/src/Firebase.Authentication/iOSImpl.uno @@ -64,10 +64,8 @@ namespace Firebase.Authentication [Foreign(Language.ObjC)] public GetToken() @{ - NSLog(@"We are in obj-c trying to get token"); FIRUser* user = [FIRAuth auth].currentUser; [user getTokenWithCompletion: ^(NSString *_Nullable token, NSError *_Nullable error) { - NSLog(@"%@", token); if (error) { @{GetToken:Of(_this).Reject(string):Call(@"failed getting token for user")}; } else { diff --git a/src/Firebase.Notifications.Android/Common.uno b/src/Firebase.Notifications.Android/Common.uno index 5b2539e..f7e5a4b 100644 --- a/src/Firebase.Notifications.Android/Common.uno +++ b/src/Firebase.Notifications.Android/Common.uno @@ -159,7 +159,6 @@ namespace Firebase.Notifications public extern(Android) static String GetFCMToken() @{ String refreshedToken = FirebaseInstanceId.getInstance().getToken(); - Log.d("TOKEN", "Refreshed token: " + refreshedToken); return refreshedToken; @} diff --git a/src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.mm b/src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.mm index cf5195c..42e0f88 100644 --- a/src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.mm +++ b/src/Firebase.Notifications.Android/iOSFirebaseNotificationCallbacks.mm @@ -7,8 +7,6 @@ @implementation FireNotificationCallbacks : NSObject - (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken { - NSLog(@"FCM registration token: %@", fcmToken); - @{Firebase.Notifications.NotificationModule.OnRegistrationSucceedediOS(string):Call(fcmToken)}; } From 16bd3a2fc81a0283c3a43e0e4e937548b2ae9eb6 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Thu, 22 Mar 2018 17:17:51 +0530 Subject: [PATCH 34/47] Remove all debug_log --- src/Firebase.AdMob/AdMob.uno | 2 -- src/Firebase.Analytics/Analytics.uno | 4 +--- src/Firebase.Database/Database.uno | 16 +++++++--------- src/Firebase.Database/JS.uno | 13 ------------- 4 files changed, 8 insertions(+), 27 deletions(-) diff --git a/src/Firebase.AdMob/AdMob.uno b/src/Firebase.AdMob/AdMob.uno index d2f8c5e..e536e43 100644 --- a/src/Firebase.AdMob/AdMob.uno +++ b/src/Firebase.AdMob/AdMob.uno @@ -49,7 +49,6 @@ namespace Firebase.AdMob if defined(Android) { if (AdUnitId == null) { - debug_log "No AdUnitId"; throw new Uno.Exception("Not initialized."); } _native = new AndroidGADBannerView(AdUnitId); @@ -58,7 +57,6 @@ namespace Firebase.AdMob else if defined(iOS) { if (AdUnitId == null) { - debug_log "No AdUnitId"; throw new Uno.Exception("Not initialized."); } _native = new iOSGADBannerView(AdUnitId); diff --git a/src/Firebase.Analytics/Analytics.uno b/src/Firebase.Analytics/Analytics.uno index bb771ff..d9e9127 100644 --- a/src/Firebase.Analytics/Analytics.uno +++ b/src/Firebase.Analytics/Analytics.uno @@ -66,8 +66,6 @@ namespace Firebase.Analytics internal static class AnalyticsService { public static void Init() {} - public static void LogEvent(string name, string[] keys, string[] vals, int len) { - debug_log "LogEvent: " + name; - } + public static void LogEvent(string name, string[] keys, string[] vals, int len) { } } } diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index 9001fa6..3787055 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -603,11 +603,9 @@ namespace Firebase.Database public static void Init() {} public static string NewChildId(string path) { - debug_log "NewChildId not implemented for desktop"; return "unknown"; } public static void Save() { - debug_log "Save not implemented for desktop"; } public static void Save(string path, string[] keys, string[] vals, int len) { @@ -637,37 +635,37 @@ namespace Firebase.Database public static void Listen(string path, Action f) { - debug_log "Listen not implemented for desktop"; + } public static void ReadByQueryEndingAtValue(string path, string keyName, string lastValue, int count, Action f) { - debug_log "ReadByQueryEndingAtValue not implemented for desktop"; + } public static void ListenForChildAdded(string path, int count, Action f) { - debug_log "ListenForChildAdded not implemented for desktop"; + } public static void ListenForChildChanged(string path, Action f) { - debug_log "ListenForChildChanged not implemented for desktop"; + } public static void ListenForChildRemoved(string path, Action f) { - debug_log "ListenForChildRemoved not implemented for desktop"; + } public static void ListenForChildMoved(string path, Action f) { - debug_log "ListenForChildMoved not implemented for desktop"; + } public static void DetachListeners(string path) { - debug_log "DetachListeners not implemented for desktop"; + } } diff --git a/src/Firebase.Database/JS.uno b/src/Firebase.Database/JS.uno index 768f4cd..5d4f910 100644 --- a/src/Firebase.Database/JS.uno +++ b/src/Firebase.Database/JS.uno @@ -76,9 +76,6 @@ namespace Firebase.Database.JS var key = args[1].ToString(); var val = args[2]; - debug_log "ReadByQueryEqualToValue"; - debug_log(path); - if defined(iOS) { return new ReadByQueryEqualToValue( @@ -147,9 +144,6 @@ namespace Firebase.Database.JS } else { - debug_log("Save: Unimplemented Javascript type"); - debug_log arg; - debug_log arg.GetType(); throw new Exception("Save: Unimplemented Javascript type"); } } @@ -274,7 +268,6 @@ namespace Firebase.Database.JS object Listen(Fuse.Scripting.Context context, object[] args) { - debug_log "listen"; var path = args[0].ToString(); DatabaseService.Listen(path, ListenCallback); return null; @@ -282,7 +275,6 @@ namespace Firebase.Database.JS object ListenForChildAdded(Fuse.Scripting.Context context, object[] args) { - debug_log "ListenForChildAdded"; var path = args[0].ToString(); int count = Marshal.ToInt(args[1]); DatabaseService.ListenForChildAdded(path,count, ListenAddedCallback); @@ -291,7 +283,6 @@ namespace Firebase.Database.JS object ListenForChildChanged(Fuse.Scripting.Context context, object[] args) { - debug_log "ListenForChildChanged"; var path = args[0].ToString(); DatabaseService.ListenForChildChanged(path, ListenChangedCallback); return null; @@ -299,7 +290,6 @@ namespace Firebase.Database.JS object ListenForChildRemoved(Fuse.Scripting.Context context, object[] args) { - debug_log "ListenForChildRemoved"; var path = args[0].ToString(); DatabaseService.ListenForChildRemoved(path, ListenRemovedCallback); return null; @@ -307,7 +297,6 @@ namespace Firebase.Database.JS object ListenForChildMoved(Fuse.Scripting.Context context, object[] args) { - debug_log "ListenForChildMoved"; var path = args[0].ToString(); DatabaseService.ListenForChildMoved(path, ListenMovedCallback); return null; @@ -315,7 +304,6 @@ namespace Firebase.Database.JS object ReadByQueryEndingAtValue(Fuse.Scripting.Context context, object[] args) { - debug_log "ReadByQueryEndingAtValue"; var path = args[0].ToString(); var keyName = args[1].ToString(); var lastValue = args[2].ToString(); @@ -326,7 +314,6 @@ namespace Firebase.Database.JS object DetachListeners(Fuse.Scripting.Context context, object[] args) { - debug_log "DetachListeners"; var path = args[0].ToString(); DatabaseService.DetachListeners(path); return null; From ffb00a51de69579768aa6dc80d84e8ef6c75b1c1 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Wed, 28 Mar 2018 19:53:31 +0530 Subject: [PATCH 35/47] Set FirebaseDB.DetachListeners for Android --- src/Firebase.Database/Database.uno | 75 ++++++++++++++++++- .../Firebase.Database.unoproj | 3 +- .../FirebaseQueryObject.java | 45 +++++++++++ 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 src/Firebase.Database/FirebaseQueryObject.java diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index 3787055..a6e017b 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -24,7 +24,8 @@ namespace Firebase.Database "android.util.Log", "org.json.JSONObject", "java.util.Map", - "java.util.HashMap")] + "java.util.HashMap", + "java.util.ArrayList")] [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Database'")] [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-database:9.2.0")] [extern(iOS) Require("Source.Import","FirebaseDatabase/FIRDatabase.h")] @@ -34,6 +35,10 @@ namespace Firebase.Database static bool _initialized; extern(android) static Java.Object _handle; extern(ios) public static ObjC.Object _handle; + extern(android) static Java.Object _valueListenerMap; // For storing ChildEventListener + extern(android) static Java.Object _childListenerMap; // For storing ValueEventListener + extern(android) static Java.Object _queryListenerArray; // For storing Query EventListener + public static void Init() { @@ -60,6 +65,11 @@ namespace Firebase.Database public static void AndroidInit() @{ @{_handle:Set(FirebaseDatabase.getInstance().getReference())}; + + // Initialize variables + @{_childListenerMap:Set(new HashMap())}; + @{_valueListenerMap:Set(new HashMap())}; + @{_queryListenerArray:Set(new ArrayList())}; @} [Foreign(Language.ObjC)] @@ -127,6 +137,11 @@ namespace Firebase.Database DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; Query lastAddedQuery = ref.child(path).limitToLast(count); lastAddedQuery.addChildEventListener(childEventListener); + + @SuppressWarnings("unchecked") // For removing cast check warnings + ArrayList queryListenerArray = (ArrayList)@{DatabaseService._queryListenerArray:Get()}; + FirebaseQueryObject firebaseQueryObject = new FirebaseQueryObject(path, lastAddedQuery, childEventListener); + queryListenerArray.add(firebaseQueryObject); // Add firebaseQueryObject to query array @} [Foreign(Language.ObjC)] @@ -184,6 +199,11 @@ namespace Firebase.Database DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; Query readQuery = ref.child(path).orderByChild(keyName).endAt(longLastValue).limitToLast(count); readQuery.addValueEventListener(dataListener); + + @SuppressWarnings("unchecked") + ArrayList queryListenerArray = (ArrayList)@{DatabaseService._queryListenerArray:Get()}; + FirebaseQueryObject firebaseQueryObject = new FirebaseQueryObject(path, readQuery, dataListener); + queryListenerArray.add(firebaseQueryObject); @} [Foreign(Language.ObjC)] @@ -249,6 +269,9 @@ namespace Firebase.Database }; DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; ref.child(path).addChildEventListener(childEventListener); + @SuppressWarnings("unchecked") + HashMap mListenerMap = (HashMap)@{DatabaseService._childListenerMap:Get()}; + mListenerMap.put(path, childEventListener); // Add to Child event listener map @} [Foreign(Language.ObjC)] @@ -314,6 +337,9 @@ namespace Firebase.Database }; DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; ref.child(path).addChildEventListener(childEventListener); + @SuppressWarnings("unchecked") + HashMap mListenerMap = (HashMap)@{DatabaseService._childListenerMap:Get()}; + mListenerMap.put(path, childEventListener); @} [Foreign(Language.ObjC)] @@ -379,6 +405,9 @@ namespace Firebase.Database }; DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; ref.child(path).addChildEventListener(childEventListener); + @SuppressWarnings("unchecked") + HashMap mListenerMap = (HashMap)@{DatabaseService._childListenerMap:Get()}; + mListenerMap.put(path, childEventListener); @} [Foreign(Language.ObjC)] @@ -393,7 +422,44 @@ namespace Firebase.Database extern(Android) public static void DetachListeners(string path) @{ + DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; + + // Remove ChildEventListener if any set with this path + @SuppressWarnings("unchecked") + HashMap childListenerMap = (HashMap)@{DatabaseService._childListenerMap:Get()}; + for (Map.Entry entry : childListenerMap.entrySet()) { + String pathString = entry.getKey(); + if (pathString.equals(path)) { // Check for path name + ChildEventListener listener = entry.getValue(); + ref.child(path).removeEventListener(listener); + childListenerMap.remove(entry); + } + } + + // Remove ValueEventListener if any set with this path + @SuppressWarnings("unchecked") + HashMap valueListenerMap = (HashMap)@{DatabaseService._valueListenerMap:Get()}; + for (Map.Entry entry : valueListenerMap.entrySet()) { + String pathString = entry.getKey(); + if (pathString.equals(path)) { + ValueEventListener listener = entry.getValue(); + ref.child(path).removeEventListener(listener); + valueListenerMap.remove(entry); + } + } + // Remove Query ValueEventListener if any set with this path + @SuppressWarnings("unchecked") + ArrayList queryListenerArray = (ArrayList)@{DatabaseService._queryListenerArray:Get()}; + for (FirebaseQueryObject firebaseQueryObject : queryListenerArray) { + if (firebaseQueryObject.getPath().equals(path)) { + if (firebaseQueryObject.getChildEventListener() != null) + firebaseQueryObject.getQuery().removeEventListener(firebaseQueryObject.getChildEventListener()); + + if (firebaseQueryObject.getValueEventListener() != null) + firebaseQueryObject.getQuery().removeEventListener(firebaseQueryObject.getValueEventListener()); + } + } @} [Foreign(Language.ObjC)] @@ -443,6 +509,9 @@ namespace Firebase.Database }; DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; ref.child(path).addValueEventListener(dataListener); + @SuppressWarnings("unchecked") + HashMap mListenerMap = (HashMap)@{DatabaseService._valueListenerMap:Get()}; + mListenerMap.put(path, dataListener); // Add to Value event listener Map @} @@ -759,6 +828,7 @@ namespace Firebase.Database "org.json.JSONObject", "org.json.JSONArray", "java.util.Map", + "java.util.HashMap", "java.util.List")] extern(Android) internal class Read : Promise @@ -792,6 +862,9 @@ namespace Firebase.Database }; DatabaseReference ref = (DatabaseReference)@{DatabaseService._handle:Get()}; ref.child(path).addListenerForSingleValueEvent(dataListener); + @SuppressWarnings("unchecked") + HashMap mListenerMap = (HashMap)@{DatabaseService._valueListenerMap:Get()}; + mListenerMap.put(path, dataListener); @} void Reject(string reason) { Reject(new Exception(reason)); } } diff --git a/src/Firebase.Database/Firebase.Database.unoproj b/src/Firebase.Database/Firebase.Database.unoproj index d79bbd0..2d943c0 100644 --- a/src/Firebase.Database/Firebase.Database.unoproj +++ b/src/Firebase.Database/Firebase.Database.unoproj @@ -8,6 +8,7 @@ "FuseJS" ], "Includes": [ - "*" + "*", + "FirebaseQueryObject.java:Java:Android", ] } diff --git a/src/Firebase.Database/FirebaseQueryObject.java b/src/Firebase.Database/FirebaseQueryObject.java new file mode 100644 index 0000000..9e40f6e --- /dev/null +++ b/src/Firebase.Database/FirebaseQueryObject.java @@ -0,0 +1,45 @@ +package com.foreign.Firebase.Database; + +import com.google.firebase.database.ChildEventListener; +import com.google.firebase.database.Query; +import com.google.firebase.database.ValueEventListener; + +/** + * Created by dhvlsimac on 28/03/18. + */ + +public class FirebaseQueryObject { + + private String path; + private Query query; + private ChildEventListener childEventListener; + private ValueEventListener valueEventListener; + + FirebaseQueryObject(String path, Query query, ChildEventListener listener) { + this.path = path; + this.query = query; + this.childEventListener = listener; + } + + FirebaseQueryObject(String path, Query query, ValueEventListener listener) { + this.path = path; + this.query = query; + this.valueEventListener = listener; + } + + public String getPath() { + return path; + } + + public Query getQuery() { + return query; + } + + public ChildEventListener getChildEventListener() { + return childEventListener; + } + + public ValueEventListener getValueEventListener() { + return valueEventListener; + } +} From d561cb58287198253cd80db7c3a2a66365dd7a80 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Thu, 29 Mar 2018 09:47:16 +0530 Subject: [PATCH 36/47] Resolve Context is obsolete warnings --- src/Firebase.Authentication.Facebook/JS.uno | 4 ++-- src/Firebase.Authentication.Google/JS.uno | 2 +- src/Firebase.Authentication/JS.uno | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Firebase.Authentication.Facebook/JS.uno b/src/Firebase.Authentication.Facebook/JS.uno index ed97517..4a97c58 100644 --- a/src/Firebase.Authentication.Facebook/JS.uno +++ b/src/Firebase.Authentication.Facebook/JS.uno @@ -35,13 +35,13 @@ namespace Firebase.Authentication.Facebook.JS static void Auth(string token) { - _onAuth.RaiseAsync(_onAuth.Context.ThreadWorker, token); + _onAuth.RaiseAsync(_onAuth.ThreadWorker, token); //_onAuth.RaiseAsync(token); } static void OnFailed(string err) { - _onError.RaiseAsync(_onError.Context.ThreadWorker, err); + _onError.RaiseAsync(_onError.ThreadWorker, err); //_onError.RaiseAsync(err); } diff --git a/src/Firebase.Authentication.Google/JS.uno b/src/Firebase.Authentication.Google/JS.uno index 37fc1e0..53e4715 100644 --- a/src/Firebase.Authentication.Google/JS.uno +++ b/src/Firebase.Authentication.Google/JS.uno @@ -31,7 +31,7 @@ namespace Firebase.Authentication.Google.JS static void Auth(string idToken, string accessToken) { - _onAuth.RaiseAsync(_onAuth.Context.ThreadWorker, idToken, accessToken); + _onAuth.RaiseAsync(_onAuth.ThreadWorker, idToken, accessToken); //_onAuth.RaiseAsync(idToken, accessToken); } } diff --git a/src/Firebase.Authentication/JS.uno b/src/Firebase.Authentication/JS.uno index 9ea5628..520cb9f 100644 --- a/src/Firebase.Authentication/JS.uno +++ b/src/Firebase.Authentication/JS.uno @@ -109,7 +109,7 @@ namespace Firebase.Authentication.JS static void OnError(int errorCode, string message) { //_onError.RaiseAsync(message, errorCode); - _onError.RaiseAsync(_onError.Context.ThreadWorker, message, errorCode); + _onError.RaiseAsync(_onError.ThreadWorker, message, errorCode); _instance.Emit("error", message, errorCode); } From 7d005327016b1d6ea9969a776f36e8b183ad3a50 Mon Sep 17 00:00:00 2001 From: Dhaval Golakiya Date: Thu, 3 May 2018 16:37:55 +0530 Subject: [PATCH 37/47] Add Firebase Phone auth support --- .../AndroidImpl.uno | 6 +- .../Authentication.uno | 2 +- .../AndroidImpl.uno | 199 ++++++++++++++++++ .../Authentication.uno | 60 ++++++ .../Firebase.Authentication.Phone.unoproj | 14 ++ src/Firebase.Authentication.Phone/JS.uno | 47 +++++ src/Firebase.Authentication.Phone/iOSImpl.uno | 124 +++++++++++ src/Firebase.Authentication.Phone/iOSImpl.uxl | 7 + .../Authentication.uno | 4 +- .../Firebase.Authentication.unoproj | 3 +- src/Firebase.Database/Database.uno | 2 +- .../Android/Impl.uno | 2 +- src/Firebase.Storage/Storage.uno | 2 +- src/Firebase/Core.uno | 2 +- 14 files changed, 463 insertions(+), 11 deletions(-) create mode 100644 src/Firebase.Authentication.Phone/AndroidImpl.uno create mode 100644 src/Firebase.Authentication.Phone/Authentication.uno create mode 100644 src/Firebase.Authentication.Phone/Firebase.Authentication.Phone.unoproj create mode 100644 src/Firebase.Authentication.Phone/JS.uno create mode 100644 src/Firebase.Authentication.Phone/iOSImpl.uno create mode 100644 src/Firebase.Authentication.Phone/iOSImpl.uxl diff --git a/src/Firebase.Authentication.Email/AndroidImpl.uno b/src/Firebase.Authentication.Email/AndroidImpl.uno index 45a9f2a..670d17e 100644 --- a/src/Firebase.Authentication.Email/AndroidImpl.uno +++ b/src/Firebase.Authentication.Email/AndroidImpl.uno @@ -18,7 +18,7 @@ namespace Firebase.Authentication.Email "com.google.firebase.auth.AuthResult", "com.google.firebase.auth.FirebaseAuth", "com.google.firebase.auth.FirebaseUser")] - [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:9.2.0")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:11.8.0")] extern(android) internal class CreateUser : Promise { @@ -60,7 +60,7 @@ namespace Firebase.Authentication.Email "com.google.firebase.auth.AuthResult", "com.google.firebase.auth.FirebaseAuth", "com.google.firebase.auth.FirebaseUser")] - [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:9.2.0")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:11.8.0")] extern(android) internal class SignInUser : Promise { @@ -103,7 +103,7 @@ namespace Firebase.Authentication.Email "com.google.firebase.auth.EmailAuthProvider", "com.google.firebase.auth.AuthCredential", "com.google.firebase.auth.UserProfileChangeRequest")] - [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:9.2.0")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:11.8.0")] extern(android) internal class ReAuthenticate : Promise { diff --git a/src/Firebase.Authentication.Google/Authentication.uno b/src/Firebase.Authentication.Google/Authentication.uno index ef4f676..e612c61 100644 --- a/src/Firebase.Authentication.Google/Authentication.uno +++ b/src/Firebase.Authentication.Google/Authentication.uno @@ -30,7 +30,7 @@ namespace Firebase.Authentication.Google "com.google.firebase.auth.FirebaseAuth", "com.google.firebase.auth.FirebaseUser", "com.google.firebase.auth.GoogleAuthProvider")] - [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:9.2.0")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:11.8.0")] [Require("Gradle.Dependency.Compile", "com.google.android.gms:play-services-auth:9.2.0")] [Require("Cocoapods.Podfile.Target", "pod 'GoogleSignIn'")] [Require("AppDelegate.HeaderFile.Declaration", "#include ")] diff --git a/src/Firebase.Authentication.Phone/AndroidImpl.uno b/src/Firebase.Authentication.Phone/AndroidImpl.uno new file mode 100644 index 0000000..46336fd --- /dev/null +++ b/src/Firebase.Authentication.Phone/AndroidImpl.uno @@ -0,0 +1,199 @@ +using Uno; +using Uno.UX; +using Uno.Collections; +using Uno.Compiler.ExportTargetInterop; +using Fuse; +using Fuse.Triggers; +using Fuse.Controls; +using Fuse.Controls.Native; +using Fuse.Controls.Native.Android; +using Uno.Threading; +using Firebase.Authentication; + +namespace Firebase.Authentication.Phone +{ + [ForeignInclude(Language.Java, "java.util.ArrayList", "java.util.List", "android.content.Intent", + "java.util.concurrent.TimeUnit", + "android.content.SharedPreferences", + "android.util.Log", + "android.preference.PreferenceManager", + "com.google.android.gms.tasks.OnCompleteListener", + "com.google.android.gms.tasks.Task", + "com.google.firebase.auth.PhoneAuthProvider", + "com.google.firebase.auth.PhoneAuthCredential", + "com.google.firebase.auth.FirebaseAuth", + "com.google.firebase.auth.AuthResult", + "com.google.firebase.FirebaseException", + "com.google.firebase.FirebaseTooManyRequestsException", + "com.google.firebase.auth.FirebaseAuthInvalidCredentialsException")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:11.8.0")] + extern(android) + internal class CreateUser : Promise + { + + public CreateUser(string phone) + { + Init(phone); + } + + [Foreign(Language.Java)] + public void Init(string phone) + @{ + PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() { + + @Override + public void onVerificationCompleted(PhoneAuthCredential credential) { + // This callback will be invoked in two situations: + // 1 - Instant verification. In some cases the phone number can be instantly + // verified without needing to send or enter a verification code. + // 2 - Auto-retrieval. On some devices Google Play services can automatically + // detect the incoming verification SMS and perform verification without + // user action. + Log.d("Log ", "onVerificationCompleted:" + credential); + FirebaseAuth.getInstance().signInWithCredential(credential) + .addOnCompleteListener(com.fuse.Activity.getRootActivity(), new OnCompleteListener() { + public void onComplete(Task task) { + if (task.isSuccessful()) { + @{CreateUser:Of(_this).Auth(string):Call(task.getResult().getUser().getIdToken(false).getResult().getToken())}; + } + else { + Log.d("Log ", " " + task.getException().toString()); + @{CreateUser:Of(_this).Reject(string):Call(task.getException().toString())}; + } + }}); + } + + @Override + public void onVerificationFailed(FirebaseException e) { + // This callback is invoked in an invalid request for verification is made, + // for instance if the the phone number format is not valid. + Log.w("Log ", "onVerificationFailed", e); + + if (e instanceof FirebaseAuthInvalidCredentialsException) { + // Invalid request + // ... + } else if (e instanceof FirebaseTooManyRequestsException) { + // The SMS quota for the project has been exceeded + // ... + } + + @{CreateUser:Of(_this).Reject(string):Call("SMS failed")}; + + // Show a message and update the UI + // ... + } + + @Override + public void onCodeSent(String verificationId, + PhoneAuthProvider.ForceResendingToken token) { + // The SMS verification code has been sent to the provided phone number, we + // now need to ask the user to enter the code and then construct a credential + // by combining the code with a verification ID. + Log.d("Log ", "onCodeSent:" + verificationId); + + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(com.fuse.Activity.getRootActivity()); + SharedPreferences.Editor editor = preferences.edit(); + editor.putString("authVerificationID", verificationId); + editor.apply(); + @{CreateUser:Of(_this).Resolve(string):Call("Code sent")}; + } + }; + + PhoneAuthProvider.getInstance().verifyPhoneNumber( + phone, // Phone number to verify + 60, // Timeout duration + TimeUnit.SECONDS, // Unit of timeout + com.fuse.Activity.getRootActivity(), // Activity (for callback binding) + mCallbacks); + + @} + + void Resolve(string message) + { + base.Resolve(message); + } + + void Reject(string reason) + { + AuthService.SignalError(-1, reason); + Reject(new Exception(reason)); + } + + void Auth(string message) { + AuthService.AnnounceSignIn(AuthProviderName.Phone); + base.Resolve(message); + } + + } + + [ForeignInclude(Language.Java, "android.content.SharedPreferences", + "android.preference.PreferenceManager", + "com.google.android.gms.tasks.OnCompleteListener", + "com.google.android.gms.tasks.Task", + "com.google.firebase.auth.PhoneAuthProvider", + "com.google.firebase.auth.PhoneAuthCredential", + "com.google.firebase.auth.FirebaseAuth", + "com.google.firebase.auth.AuthResult")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:11.8.0")] + extern(android) + internal class ValidateUser : Promise + { + + public ValidateUser(string code) + { + Init(code); + } + + [Foreign(Language.Java)] + public void Init(string code) + @{ + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(com.fuse.Activity.getRootActivity()); + String mVerificationId = preferences.getString("authVerificationID", "Error"); + if (mVerificationId.equals("Error")) { + @{ValidateUser:Of(_this).Reject(string):Call("Firebase failed to create user")}; + return; + } + PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, code); + FirebaseAuth.getInstance().signInWithCredential(credential) + .addOnCompleteListener(com.fuse.Activity.getRootActivity(), new OnCompleteListener() { + public void onComplete(Task task) + { + if (task.isSuccessful()) + @{ValidateUser:Of(_this).Resolve(string):Call(task.getResult().getUser().getIdToken(false).getResult().getToken())}; + else + @{ValidateUser:Of(_this).Reject(string):Call("Firebase failed to create user")}; + } + }); + @} + + void Resolve(string message) + { + AuthService.AnnounceSignIn(AuthProviderName.Phone); + base.Resolve(message); + } + + void Reject(string reason) + { + AuthService.SignalError(-1, reason); + Reject(new Exception(reason)); + } + + } + + extern(android) + internal class ReAuthenticate : Promise + { + + [Foreign(Language.Java)] + public ReAuthenticate(string phone) + @{ + + @} + + void Reject(string reason) + { + Reject(new Exception(reason)); + } + + } +} diff --git a/src/Firebase.Authentication.Phone/Authentication.uno b/src/Firebase.Authentication.Phone/Authentication.uno new file mode 100644 index 0000000..aa18157 --- /dev/null +++ b/src/Firebase.Authentication.Phone/Authentication.uno @@ -0,0 +1,60 @@ +using Uno; +using Uno.UX; +using Uno.Collections; +using Uno.Compiler.ExportTargetInterop; +using Fuse; +using Fuse.Triggers; +using Fuse.Controls; +using Fuse.Controls.Native; +using Fuse.Controls.Native.Android; +using Uno.Threading; +using Firebase.Authentication; + +namespace Firebase.Authentication.Phone +{ + public class PhoneService : Firebase.Authentication.AuthProvider + { + static bool _initd = false; + + internal static void Init() + { + if (_initd) return; + var es = new PhoneService(); + Firebase.Authentication.AuthService.RegisterAuthProvider(es); + _initd = true; + } + + public override AuthProviderName Name { get { return AuthProviderName.Phone; } } + + public override void Start() {} + + public override void SignOut() {} + + public override Promise ReAuthenticate(string phone, string password) + { + return new ReAuthenticate(phone); + } + } + + extern(!mobile) + internal class CreateUser : Promise + { + public CreateUser(string phone) { } + public void Reject(string reason) { } + } + + extern(!mobile) + internal class ValidateUser : Promise + { + public ValidateUser(string code) { } + public void Reject(string reason) { } + } + + extern(!mobile) + internal class ReAuthenticate : Promise + { + public ReAuthenticate(string phone ) { } + public void Reject(string reason) { } + } + +} diff --git a/src/Firebase.Authentication.Phone/Firebase.Authentication.Phone.unoproj b/src/Firebase.Authentication.Phone/Firebase.Authentication.Phone.unoproj new file mode 100644 index 0000000..d14fef5 --- /dev/null +++ b/src/Firebase.Authentication.Phone/Firebase.Authentication.Phone.unoproj @@ -0,0 +1,14 @@ +{ + "RootNamespace":"", + "Packages": [ + "Fuse", + "FuseJS" + ], + "Projects": [ + "../Firebase.Authentication/Firebase.Authentication.unoproj" + ], + "Includes": [ + "*" + ] +} + diff --git a/src/Firebase.Authentication.Phone/JS.uno b/src/Firebase.Authentication.Phone/JS.uno new file mode 100644 index 0000000..05ab3a3 --- /dev/null +++ b/src/Firebase.Authentication.Phone/JS.uno @@ -0,0 +1,47 @@ +using Uno; +using Uno.UX; +using Uno.Threading; +using Uno.Text; +using Uno.Platform; +using Uno.Compiler.ExportTargetInterop; +using Uno.Collections; +using Fuse; +using Fuse.Scripting; +using Fuse.Reactive; + +namespace Firebase.Authentication.Phone.JS +{ + /** + */ + [UXGlobalModule] + public sealed class PhoneModule : NativeModule + { + // static NativeEvent _onReceivedMessage; + static readonly PhoneModule _instance; + + public PhoneModule() + { + if(_instance != null) return; + Uno.UX.Resource.SetGlobalKey(_instance = this, "Firebase/Authentication/Phone"); + + Firebase.Authentication.Phone.PhoneService.Init(); + + AddMember(new NativePromise("createUserWithPhoneNumber", CreateUserWithPhoneNumber)); + AddMember(new NativePromise("validateUserWithCode", ValidateUserWithCode)); + // AddMember(new NativePromise("updatePassword", UpdatePassword)); + } + + Future CreateUserWithPhoneNumber(object[] args) + { + var phone = (string)args[0]; + return new Firebase.Authentication.Phone.CreateUser(phone); + } + + Future ValidateUserWithCode(object[] args) + { + var code = (string)args[0]; + return new Firebase.Authentication.Phone.ValidateUser(code); + } + + } +} diff --git a/src/Firebase.Authentication.Phone/iOSImpl.uno b/src/Firebase.Authentication.Phone/iOSImpl.uno new file mode 100644 index 0000000..cf3013c --- /dev/null +++ b/src/Firebase.Authentication.Phone/iOSImpl.uno @@ -0,0 +1,124 @@ +using Uno; +using Uno.UX; +using Uno.Collections; +using Uno.Compiler.ExportTargetInterop; +using Fuse; +using Fuse.Triggers; +using Fuse.Controls; +using Fuse.Controls.Native; +using Fuse.Controls.Native.Android; +using Uno.Threading; +using Firebase.Authentication; + +namespace Firebase.Authentication.Phone +{ + [Require("AppDelegate.SourceFile.Declaration", "#include ")] + [Require("AppDelegate.SourceFile.Declaration", "#include ")] + [Require("Source.Include", "Firebase/Firebase.h")] + [Require("Source.Include", "FirebaseAuth/FirebaseAuth.h")] + [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Auth'")] + extern(iOS) + class CreateUser : Promise + { + [Foreign(Language.ObjC)] + public CreateUser(string phone) + @{ + [[FIRPhoneAuthProvider provider] + verifyPhoneNumber:phone + UIDelegate:nil + completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { + if (error) { + NSLog(@"%@", error.localizedDescription); + @{CreateUser:Of(_this).Reject(string):Call(error.localizedDescription)}; + } + else { + // Sign in using the verificationID and the code sent to the user + // ... + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + [defaults setObject:verificationID forKey:@"authVerificationID"]; + NSLog(@"%@", verificationID); + @{CreateUser:Of(_this).Resolve(string):Call(@"Code sent")}; + } + }]; + @} + + void Resolve(string message) + { + base.Resolve(message); + } + + void Reject(string reason) + { + AuthService.SignalError(-1, reason); + Reject(new Exception(reason)); + } + } + + [Require("Source.Include", "Firebase/Firebase.h")] + [Require("Source.Include", "FirebaseAuth/FirebaseAuth.h")] + [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Auth'")] + extern(iOS) + class ValidateUser : Promise + { + [Foreign(Language.ObjC)] + public ValidateUser(string code) + @{ + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSString *verificationID = [defaults stringForKey:@"authVerificationID"]; + NSLog(@"%@", verificationID); + FIRAuthCredential *credential = [[FIRPhoneAuthProvider provider] + credentialWithVerificationID:verificationID + verificationCode:code]; + [[FIRAuth auth] + signInWithCredential:credential + completion:^(FIRUser *user, NSError *error) { + if (error) { + NSLog(@"%@", error.localizedDescription); + @{ValidateUser:Of(_this).Reject(string):Call(error.localizedDescription)}; + } + else { + [user getIDTokenWithCompletion:^(NSString *idToken, NSError* fidError) { + if (fidError) { + @{ValidateUser:Of(_this).Reject(string):Call(fidError.localizedDescription)}; + } + else { + @{ValidateUser:Of(_this).Resolve(string):Call(idToken)}; + } + }]; + } + }]; + @} + + void Resolve(string message) + { + AuthService.AnnounceSignIn(AuthProviderName.Phone); + base.Resolve(message); + } + + void Reject(string reason) + { + AuthService.SignalError(-1, reason); + } + } + + [Require("Source.Include", "Firebase/Firebase.h")] + [Require("Source.Include", "FirebaseAuth/FirebaseAuth.h")] + [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Auth'")] + [Require("Source.Include", "@{Firebase.Authentication.User:Include}")] + extern(iOS) + class ReAuthenticate : Promise + { + [Foreign(Language.ObjC)] + public ReAuthenticate(string code) + @{ + + @} + + void Reject(string reason) + { + Reject(new Exception(reason)); + } + + } + +} diff --git a/src/Firebase.Authentication.Phone/iOSImpl.uxl b/src/Firebase.Authentication.Phone/iOSImpl.uxl new file mode 100644 index 0000000..cdd8fa1 --- /dev/null +++ b/src/Firebase.Authentication.Phone/iOSImpl.uxl @@ -0,0 +1,7 @@ + + + + + diff --git a/src/Firebase.Authentication/Authentication.uno b/src/Firebase.Authentication/Authentication.uno index 6ac297c..5878796 100644 --- a/src/Firebase.Authentication/Authentication.uno +++ b/src/Firebase.Authentication/Authentication.uno @@ -12,7 +12,7 @@ using Uno.Threading; namespace Firebase.Authentication { // this enum is a shame but we want to talk about the backend even when it isnt included - public enum AuthProviderName { None, Email, Facebook, Google } + public enum AuthProviderName { None, Email, Facebook, Google, Phone } [ForeignInclude(Language.Java, "java.util.ArrayList", "java.util.List", "android.graphics.Color", "com.google.android.gms.tasks.OnCompleteListener", @@ -20,7 +20,7 @@ namespace Firebase.Authentication "com.google.firebase.auth.AuthResult", "com.google.firebase.auth.FirebaseAuth", "com.google.firebase.auth.FirebaseUser")] - [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:9.2.0")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:11.8.0")] [Require("AppDelegate.SourceFile.Declaration", "#include <@{Firebase.Authentication.AuthService:Include}>")] [extern(iOS) Require("Source.Include", "Firebase/Firebase.h")] [extern(iOS) Require("Source.Include", "FirebaseAuth/FirebaseAuth.h")] diff --git a/src/Firebase.Authentication/Firebase.Authentication.unoproj b/src/Firebase.Authentication/Firebase.Authentication.unoproj index 97ac26d..2babcec 100644 --- a/src/Firebase.Authentication/Firebase.Authentication.unoproj +++ b/src/Firebase.Authentication/Firebase.Authentication.unoproj @@ -12,7 +12,8 @@ "Firebase.Authentication.Google", "Firebase.Authentication.Facebook", "Firebase.Authentication.Twitter", - "Firebase.Authentication.Github" + "Firebase.Authentication.Github", + "Firebase.Authentication.Phone" ], "Includes": [ "*" diff --git a/src/Firebase.Database/Database.uno b/src/Firebase.Database/Database.uno index a6e017b..9d428df 100644 --- a/src/Firebase.Database/Database.uno +++ b/src/Firebase.Database/Database.uno @@ -27,7 +27,7 @@ namespace Firebase.Database "java.util.HashMap", "java.util.ArrayList")] [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Database'")] - [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-database:9.2.0")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-database:11.8.0")] [extern(iOS) Require("Source.Import","FirebaseDatabase/FIRDatabase.h")] extern(mobile) static class DatabaseService diff --git a/src/Firebase.Notifications.Android/Android/Impl.uno b/src/Firebase.Notifications.Android/Android/Impl.uno index 1ecbd8e..8be893f 100644 --- a/src/Firebase.Notifications.Android/Android/Impl.uno +++ b/src/Firebase.Notifications.Android/Android/Impl.uno @@ -23,7 +23,7 @@ namespace Firebase.Notifications "android.os.Bundle", "com.fuse.firebase.Notifications.PushNotificationReceiver", "com.google.firebase.messaging.RemoteMessage")] - [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-messaging:9.2.0")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-messaging:11.8.0")] extern(Android) internal class AndroidImpl { diff --git a/src/Firebase.Storage/Storage.uno b/src/Firebase.Storage/Storage.uno index 42d5198..2220482 100755 --- a/src/Firebase.Storage/Storage.uno +++ b/src/Firebase.Storage/Storage.uno @@ -17,7 +17,7 @@ namespace Firebase.Storage "com.google.firebase.storage.StorageReference", "com.google.firebase.storage.UploadTask")] [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Storage'")] - [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-storage:9.2.0")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-storage:11.8.0")] [extern(iOS) Require("Source.Import","FirebaseStorage/FirebaseStorage.h")] extern(mobile) static class StorageService diff --git a/src/Firebase/Core.uno b/src/Firebase/Core.uno index f879631..d9786e1 100644 --- a/src/Firebase/Core.uno +++ b/src/Firebase/Core.uno @@ -12,7 +12,7 @@ namespace Firebase { [ForeignInclude(Language.Java, "java.util.ArrayList", "java.util.List", "android.graphics.Color")] [Require("Gradle.Dependency.ClassPath", "com.google.gms:google-services:3.0.0")] - [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-core:9.2.0")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-core:11.8.0")] [Require("Gradle.BuildFile.End", "apply plugin: 'com.google.gms.google-services'")] [Require("Cocoapods.Podfile.Target", "pod 'Firebase/Core'")] From bb180c65cc0ae8cac2872d015728d303a2858c0f Mon Sep 17 00:00:00 2001 From: Dhaval Golakiya Date: Mon, 7 May 2018 10:22:59 +0530 Subject: [PATCH 38/47] Add Native event for handle Code sent event on Android --- src/Firebase.Authentication.Phone/AndroidImpl.uno | 2 +- src/Firebase.Authentication.Phone/JS.uno | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Firebase.Authentication.Phone/AndroidImpl.uno b/src/Firebase.Authentication.Phone/AndroidImpl.uno index 46336fd..7bcdb87 100644 --- a/src/Firebase.Authentication.Phone/AndroidImpl.uno +++ b/src/Firebase.Authentication.Phone/AndroidImpl.uno @@ -95,7 +95,7 @@ namespace Firebase.Authentication.Phone SharedPreferences.Editor editor = preferences.edit(); editor.putString("authVerificationID", verificationId); editor.apply(); - @{CreateUser:Of(_this).Resolve(string):Call("Code sent")}; + @{Firebase.Authentication.Phone.JS.PhoneModule.CodeSent(string):Call("Code sent")}; } }; diff --git a/src/Firebase.Authentication.Phone/JS.uno b/src/Firebase.Authentication.Phone/JS.uno index 05ab3a3..ff1c50c 100644 --- a/src/Firebase.Authentication.Phone/JS.uno +++ b/src/Firebase.Authentication.Phone/JS.uno @@ -16,8 +16,8 @@ namespace Firebase.Authentication.Phone.JS [UXGlobalModule] public sealed class PhoneModule : NativeModule { - // static NativeEvent _onReceivedMessage; static readonly PhoneModule _instance; + static NativeEvent _onCodeSent; public PhoneModule() { @@ -25,10 +25,11 @@ namespace Firebase.Authentication.Phone.JS Uno.UX.Resource.SetGlobalKey(_instance = this, "Firebase/Authentication/Phone"); Firebase.Authentication.Phone.PhoneService.Init(); + _onCodeSent = new NativeEvent("onCodeSentEvent"); + AddMember(_onCodeSent); AddMember(new NativePromise("createUserWithPhoneNumber", CreateUserWithPhoneNumber)); AddMember(new NativePromise("validateUserWithCode", ValidateUserWithCode)); - // AddMember(new NativePromise("updatePassword", UpdatePassword)); } Future CreateUserWithPhoneNumber(object[] args) @@ -43,5 +44,10 @@ namespace Firebase.Authentication.Phone.JS return new Firebase.Authentication.Phone.ValidateUser(code); } + static void CodeSent(string token) + { + _onCodeSent.RaiseAsync(_onCodeSent.ThreadWorker, token); + } + } } From 744e33a9cdbd30bbc1389c2c3c09b7e65531a13d Mon Sep 17 00:00:00 2001 From: Dhaval Golakiya Date: Mon, 7 May 2018 12:04:56 +0530 Subject: [PATCH 39/47] Resend OTP code from Fiirebase Phone Auth --- .../AndroidImpl.uno | 118 ++++++++++++++++++ src/Firebase.Authentication.Phone/JS.uno | 14 +++ 2 files changed, 132 insertions(+) diff --git a/src/Firebase.Authentication.Phone/AndroidImpl.uno b/src/Firebase.Authentication.Phone/AndroidImpl.uno index 7bcdb87..21e32ea 100644 --- a/src/Firebase.Authentication.Phone/AndroidImpl.uno +++ b/src/Firebase.Authentication.Phone/AndroidImpl.uno @@ -31,6 +31,8 @@ namespace Firebase.Authentication.Phone internal class CreateUser : Promise { + extern(android) static internal Java.Object mResendToken; + public CreateUser(string phone) { Init(phone); @@ -95,6 +97,7 @@ namespace Firebase.Authentication.Phone SharedPreferences.Editor editor = preferences.edit(); editor.putString("authVerificationID", verificationId); editor.apply(); + @{mResendToken:Set(token)}; @{Firebase.Authentication.Phone.JS.PhoneModule.CodeSent(string):Call("Code sent")}; } }; @@ -180,6 +183,121 @@ namespace Firebase.Authentication.Phone } + [ForeignInclude(Language.Java, "java.util.ArrayList", "java.util.List", "android.content.Intent", + "java.util.concurrent.TimeUnit", + "android.content.SharedPreferences", + "android.util.Log", + "android.preference.PreferenceManager", + "com.google.android.gms.tasks.OnCompleteListener", + "com.google.android.gms.tasks.Task", + "com.google.firebase.auth.PhoneAuthProvider", + "com.google.firebase.auth.PhoneAuthCredential", + "com.google.firebase.auth.FirebaseAuth", + "com.google.firebase.auth.AuthResult", + "com.google.firebase.FirebaseException", + "com.google.firebase.FirebaseTooManyRequestsException", + "com.google.firebase.auth.FirebaseAuthInvalidCredentialsException")] + [Require("Gradle.Dependency.Compile", "com.google.firebase:firebase-auth:11.8.0")] + extern(android) + internal class ResendCodeValidation : Promise + { + + public ResendCodeValidation(string phone) + { + Init(phone); + } + + [Foreign(Language.Java)] + public void Init(string phone) + @{ + PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() { + + @Override + public void onVerificationCompleted(PhoneAuthCredential credential) { + // This callback will be invoked in two situations: + // 1 - Instant verification. In some cases the phone number can be instantly + // verified without needing to send or enter a verification code. + // 2 - Auto-retrieval. On some devices Google Play services can automatically + // detect the incoming verification SMS and perform verification without + // user action. + Log.d("Log ", "onVerificationCompleted:" + credential); + FirebaseAuth.getInstance().signInWithCredential(credential) + .addOnCompleteListener(com.fuse.Activity.getRootActivity(), new OnCompleteListener() { + public void onComplete(Task task) { + if (task.isSuccessful()) { + @{ResendCodeValidation:Of(_this).Auth(string):Call(task.getResult().getUser().getIdToken(false).getResult().getToken())}; + } + else { + Log.d("Log ", " " + task.getException().toString()); + @{ResendCodeValidation:Of(_this).Reject(string):Call(task.getException().toString())}; + } + }}); + } + + @Override + public void onVerificationFailed(FirebaseException e) { + // This callback is invoked in an invalid request for verification is made, + // for instance if the the phone number format is not valid. + Log.w("Log ", "onVerificationFailed", e); + + if (e instanceof FirebaseAuthInvalidCredentialsException) { + // Invalid request + // ... + } else if (e instanceof FirebaseTooManyRequestsException) { + // The SMS quota for the project has been exceeded + // ... + } + + @{ResendCodeValidation:Of(_this).Reject(string):Call("SMS failed")}; + + // Show a message and update the UI + // ... + } + + @Override + public void onCodeSent(String verificationId, + PhoneAuthProvider.ForceResendingToken token) { + // The SMS verification code has been sent to the provided phone number, we + // now need to ask the user to enter the code and then construct a credential + // by combining the code with a verification ID. + Log.d("Log ", "onCodeSent:" + verificationId); + + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(com.fuse.Activity.getRootActivity()); + SharedPreferences.Editor editor = preferences.edit(); + editor.putString("authVerificationID", verificationId); + editor.apply(); + @{Firebase.Authentication.Phone.JS.PhoneModule.CodeSent(string):Call("Code sent")}; + } + }; + + PhoneAuthProvider.ForceResendingToken mResendToken = (PhoneAuthProvider.ForceResendingToken)@{Firebase.Authentication.Phone.CreateUser.mResendToken}; + PhoneAuthProvider.getInstance().verifyPhoneNumber( + phone, // Phone number to verify + 60, // Timeout duration + TimeUnit.SECONDS, // Unit of timeout + com.fuse.Activity.getRootActivity(), // Activity (for callback binding) + mCallbacks, + mResendToken); + @} + + void Resolve(string message) + { + base.Resolve(message); + } + + void Reject(string reason) + { + AuthService.SignalError(-1, reason); + Reject(new Exception(reason)); + } + + void Auth(string message) { + AuthService.AnnounceSignIn(AuthProviderName.Phone); + base.Resolve(message); + } + + } + extern(android) internal class ReAuthenticate : Promise { diff --git a/src/Firebase.Authentication.Phone/JS.uno b/src/Firebase.Authentication.Phone/JS.uno index ff1c50c..ec090a3 100644 --- a/src/Firebase.Authentication.Phone/JS.uno +++ b/src/Firebase.Authentication.Phone/JS.uno @@ -30,6 +30,7 @@ namespace Firebase.Authentication.Phone.JS AddMember(new NativePromise("createUserWithPhoneNumber", CreateUserWithPhoneNumber)); AddMember(new NativePromise("validateUserWithCode", ValidateUserWithCode)); + AddMember(new NativePromise("resendCodeValidation", ResendCodeValidation)); } Future CreateUserWithPhoneNumber(object[] args) @@ -44,6 +45,19 @@ namespace Firebase.Authentication.Phone.JS return new Firebase.Authentication.Phone.ValidateUser(code); } + Future ResendCodeValidation(object[] args) + { + var phone = (string)args[0]; + if defined(Android) + { + return new Firebase.Authentication.Phone.ResendCodeValidation(phone); + } else if defined(iOS) { + return new Firebase.Authentication.Phone.CreateUser(phone); + } else { + return null; + } + } + static void CodeSent(string token) { _onCodeSent.RaiseAsync(_onCodeSent.ThreadWorker, token); From 31942a08af075f8dfe7fdb1b53c1714878843374 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Thu, 17 May 2018 17:52:44 +0530 Subject: [PATCH 40/47] Link Facebook with current Firebase auth user --- .../FacebookAuthentication.uno | 110 ++++++++++++++++++ src/Firebase.Authentication.Facebook/JS.uno | 12 ++ 2 files changed, 122 insertions(+) diff --git a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno index 9c59017..a6c6cfe 100644 --- a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno +++ b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno @@ -158,5 +158,115 @@ namespace Firebase.Authentication.Facebook.JS }]; @} + + [Foreign(Language.ObjC)] + public extern(iOS) void LinkFacebook() + @{ + FBSDKLoginManager* login = [[FBSDKLoginManager alloc] init]; + [login + logInWithReadPermissions: @[@"public_profile"] + fromViewController: [[[UIApplication sharedApplication] keyWindow] rootViewController] + handler: ^(FBSDKLoginManagerLoginResult* result, NSError* error) + { + if (error) + { + NSString * message = @"Facebook SignIn Failed. Error code: "; + NSString *errorMessage = [NSString stringWithFormat:@"%@ %ld", message, error.code]; + @{OnFailure(string):Call(errorMessage)}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call(errorMessage)}; + return; + } + if (result.isCancelled) + { + NSString *error = @"Facebook Auth Stage Cancelled"; + @{OnFailure(string):Call(error)}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call(error)}; + return; + } + @{OnLinkFacebookWithFirebase(ObjC.Object):Call(result)}; + } + ]; + @} + + [Foreign(Language.Java)] + public extern(Android) void LinkFacebook() + @{ + FacebookSdk.sdkInitialize(Activity.getRootActivity()); + final CallbackManager callbackManager = CallbackManager.Factory.create(); + @{FacebookAuthentication:Of(_this)._callbackManager:Set(callbackManager)}; + Activity.subscribeToResults(new Activity.ResultListener() { + @Override + public boolean onResult(int requestCode, int resultCode, Intent data) { + return callbackManager.onActivityResult(requestCode, resultCode, data); + } + }); + CallbackManager callbackManagerFrom = (CallbackManager)@{FacebookAuthentication:Of(_this)._callbackManager:Get()}; + LoginManager.getInstance().registerCallback(callbackManagerFrom, + new FacebookCallback() + { + public void onSuccess(LoginResult loginResult) { + @{OnLinkFacebookWithFirebase(Java.Object):Call(loginResult.getAccessToken())}; + } + + public void onCancel() { + @{OnFailure(string):Call("Facebook Auth Stage Cancelled")}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call("Facebook Auth Stage Cancelled")}; + } + + public void onError(FacebookException error) { + String reason = "Facebook Auth Stage Errored (" + error.getClass().getName() + "):\n" + error.getMessage(); + @{OnFailure(string):Call(reason)}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call(reason)}; + } + } + ); + LoginManager.getInstance().logInWithReadPermissions(Activity.getRootActivity(), java.util.Arrays.asList("public_profile")); + @} + + + [Foreign(Language.ObjC)] + static extern(iOS) void OnLinkFacebookWithFirebase(ObjC.Object result) + @{ + FBSDKLoginManagerLoginResult *accessToken = (FBSDKLoginManagerLoginResult *)result; + NSString *tokenStr = accessToken.token.tokenString; + + if (tokenStr==NULL) + { + @{OnFailure(string):Call(@"Authentication against Firebase failed")}; + return; + } + + FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:tokenStr]; + + [[FIRAuth auth].currentUser linkAndRetrieveDataWithCredential:credential + completion:^(FIRAuthDataResult *result, NSError *_Nullable error) { + if (error) + @{OnFailure(string):Call(@"Authentication against Firebase failed")}; + else { + @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(tokenStr)}; + @{OnSuccess(string):Call(@"success")}; + } + }]; + @} + + [Foreign(Language.Java)] + static extern(Android) void OnLinkFacebookWithFirebase(Java.Object result) + @{ + final AccessToken token = (AccessToken)result; + AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken()); + FirebaseAuth.getInstance().getCurrentUser().linkWithCredential(credential) + .addOnCompleteListener(com.fuse.Activity.getRootActivity(), new OnCompleteListener() { + @Override + public void onComplete(Task task) { + if (task.isSuccessful()) { + @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(token.getToken())}; + @{OnSuccess(string):Call("Success")}; + } else { + @{OnFailure(string):Call("Authentication against Firebase failed")}; + } + } + }); + @} + } } \ No newline at end of file diff --git a/src/Firebase.Authentication.Facebook/JS.uno b/src/Firebase.Authentication.Facebook/JS.uno index 4a97c58..98a9b76 100644 --- a/src/Firebase.Authentication.Facebook/JS.uno +++ b/src/Firebase.Authentication.Facebook/JS.uno @@ -30,6 +30,7 @@ namespace Firebase.Authentication.Facebook.JS _onError = new NativeEvent("onFailed"); AddMember(_onError); AddMember(new NativeFunction("doFacebookLogin", (NativeCallback)DoFacebookLogin)); + AddMember(new NativeFunction("linkFacebook", (NativeCallback)LinkFacebook)); Firebase.Authentication.Facebook.FacebookService.Init(); } @@ -54,6 +55,17 @@ namespace Firebase.Authentication.Facebook.JS else{ } return null; } + + object LinkFacebook(Context context, object[] args) + { + if defined(iOS || Android) + { + _facebookAuthentication.LinkFacebook(); + } + else{ } + return null; + } + } } \ No newline at end of file From 3087d63b9500e681490adc2c9c21092a1607f6c6 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Fri, 18 May 2018 12:34:49 +0530 Subject: [PATCH 41/47] Handle User already link with this provider error --- .../FacebookAuthentication.uno | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno index a6c6cfe..770cc00 100644 --- a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno +++ b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno @@ -240,9 +240,14 @@ namespace Firebase.Authentication.Facebook.JS [[FIRAuth auth].currentUser linkAndRetrieveDataWithCredential:credential completion:^(FIRAuthDataResult *result, NSError *_Nullable error) { - if (error) - @{OnFailure(string):Call(@"Authentication against Firebase failed")}; - else { + if (error) { + if (error.code == FIRAuthErrorCodeProviderAlreadyLinked) { + @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(tokenStr)}; + @{OnSuccess(string):Call(@"success")}; + } else { + @{OnFailure(string):Call(@"Authentication against Firebase failed")}; + } + } else { @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(tokenStr)}; @{OnSuccess(string):Call(@"success")}; } @@ -262,11 +267,19 @@ namespace Firebase.Authentication.Facebook.JS @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(token.getToken())}; @{OnSuccess(string):Call("Success")}; } else { - @{OnFailure(string):Call("Authentication against Firebase failed")}; + if (task.getException() != null) { + if (task.getException().getMessage().equals("User has already been linked to the given provider.")) { + @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(token.getToken())}; + @{OnSuccess(string):Call("Success")}; + } else { + @{OnFailure(string):Call("Authentication against Firebase failed")}; + } + } else { + @{OnFailure(string):Call("Authentication against Firebase failed")}; + } } } }); @} - } } \ No newline at end of file From b8c1fb7bd0270e884f1e56c41b06d5eb139b2f92 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Fri, 18 May 2018 12:43:12 +0530 Subject: [PATCH 42/47] Fix: getTokenWithCompletion method is deprecated issue --- src/Firebase.Authentication/iOSImpl.uno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Firebase.Authentication/iOSImpl.uno b/src/Firebase.Authentication/iOSImpl.uno index 8e849b6..bd5271a 100644 --- a/src/Firebase.Authentication/iOSImpl.uno +++ b/src/Firebase.Authentication/iOSImpl.uno @@ -65,7 +65,7 @@ namespace Firebase.Authentication public GetToken() @{ FIRUser* user = [FIRAuth auth].currentUser; - [user getTokenWithCompletion: ^(NSString *_Nullable token, NSError *_Nullable error) { + [user getIDTokenWithCompletion: ^(NSString *_Nullable token, NSError *_Nullable error) { if (error) { @{GetToken:Of(_this).Reject(string):Call(@"failed getting token for user")}; } else { From ce6104b477df71290c8b4ddd1bc9dced41702921 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Fri, 25 May 2018 11:25:16 +0530 Subject: [PATCH 43/47] Fix: Account already linked with another provider error --- .../FacebookAuthentication.uno | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno index 770cc00..a6b9bc0 100644 --- a/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno +++ b/src/Firebase.Authentication.Facebook/FacebookAuthentication.uno @@ -245,7 +245,8 @@ namespace Firebase.Authentication.Facebook.JS @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(tokenStr)}; @{OnSuccess(string):Call(@"success")}; } else { - @{OnFailure(string):Call(@"Authentication against Firebase failed")}; + @{OnFailure(string):Call(@"Link Firebase failed")}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call(error.localizedDescription)}; } } else { @{Firebase.Authentication.Facebook.JS.FacebookModule.Auth(string):Call(tokenStr)}; @@ -273,9 +274,11 @@ namespace Firebase.Authentication.Facebook.JS @{OnSuccess(string):Call("Success")}; } else { @{OnFailure(string):Call("Authentication against Firebase failed")}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call(task.getException().getMessage())}; } } else { @{OnFailure(string):Call("Authentication against Firebase failed")}; + @{Firebase.Authentication.Facebook.JS.FacebookModule.OnFailed(string):Call("Link Firebase failed")}; } } } From b38f0af0f1ceb00b5f0f16432a294770425f1c43 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Thu, 31 May 2018 12:50:55 +0530 Subject: [PATCH 44/47] Get callback when OTP code is invalid --- src/Firebase.Authentication.Phone/AndroidImpl.uno | 4 ++-- src/Firebase.Authentication.Phone/iOSImpl.uno | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Firebase.Authentication.Phone/AndroidImpl.uno b/src/Firebase.Authentication.Phone/AndroidImpl.uno index 21e32ea..74427e1 100644 --- a/src/Firebase.Authentication.Phone/AndroidImpl.uno +++ b/src/Firebase.Authentication.Phone/AndroidImpl.uno @@ -164,7 +164,7 @@ namespace Firebase.Authentication.Phone if (task.isSuccessful()) @{ValidateUser:Of(_this).Resolve(string):Call(task.getResult().getUser().getIdToken(false).getResult().getToken())}; else - @{ValidateUser:Of(_this).Reject(string):Call("Firebase failed to create user")}; + @{ValidateUser:Of(_this).Reject(string):Call(task.getException().getLocalizedMessage())}; } }); @} @@ -178,7 +178,7 @@ namespace Firebase.Authentication.Phone void Reject(string reason) { AuthService.SignalError(-1, reason); - Reject(new Exception(reason)); + Reject(new Exception(reason)); } } diff --git a/src/Firebase.Authentication.Phone/iOSImpl.uno b/src/Firebase.Authentication.Phone/iOSImpl.uno index cf3013c..62dd3f8 100644 --- a/src/Firebase.Authentication.Phone/iOSImpl.uno +++ b/src/Firebase.Authentication.Phone/iOSImpl.uno @@ -98,6 +98,7 @@ namespace Firebase.Authentication.Phone void Reject(string reason) { AuthService.SignalError(-1, reason); + Reject(new Exception(reason)); } } From 706860d5d4083afb7d1e722281b3d82f6164cd5f Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Mon, 4 Jun 2018 12:18:42 +0530 Subject: [PATCH 45/47] Set proper message when we enter wrong country code and mobile number --- src/Firebase.Authentication.Phone/AndroidImpl.uno | 4 ++++ src/Firebase.Authentication.Phone/iOSImpl.uno | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Firebase.Authentication.Phone/AndroidImpl.uno b/src/Firebase.Authentication.Phone/AndroidImpl.uno index 74427e1..9c87223 100644 --- a/src/Firebase.Authentication.Phone/AndroidImpl.uno +++ b/src/Firebase.Authentication.Phone/AndroidImpl.uno @@ -74,6 +74,8 @@ namespace Firebase.Authentication.Phone if (e instanceof FirebaseAuthInvalidCredentialsException) { // Invalid request // ... + @{CreateUser:Of(_this).Reject(string):Call("The country code or mobile number may be incorrect")}; + return; } else if (e instanceof FirebaseTooManyRequestsException) { // The SMS quota for the project has been exceeded // ... @@ -243,6 +245,8 @@ namespace Firebase.Authentication.Phone if (e instanceof FirebaseAuthInvalidCredentialsException) { // Invalid request // ... + @{CreateUser:Of(_this).Reject(string):Call("The country code or mobile number may be incorrect")}; + return; } else if (e instanceof FirebaseTooManyRequestsException) { // The SMS quota for the project has been exceeded // ... diff --git a/src/Firebase.Authentication.Phone/iOSImpl.uno b/src/Firebase.Authentication.Phone/iOSImpl.uno index 62dd3f8..22c7c62 100644 --- a/src/Firebase.Authentication.Phone/iOSImpl.uno +++ b/src/Firebase.Authentication.Phone/iOSImpl.uno @@ -28,8 +28,12 @@ namespace Firebase.Authentication.Phone UIDelegate:nil completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { if (error) { - NSLog(@"%@", error.localizedDescription); - @{CreateUser:Of(_this).Reject(string):Call(error.localizedDescription)}; + if (error.code == FIRAuthErrorCodeInvalidPhoneNumber) { + @{CreateUser:Of(_this).Reject(string):Call(@"The country code or mobile number may be incorrect")}; + }else { + NSLog(@"%@", error.localizedDescription); + @{CreateUser:Of(_this).Reject(string):Call(error.localizedDescription)}; + } } else { // Sign in using the verificationID and the code sent to the user From d76000e6a4a0d91bbedf7432cd31fe753ed3a498 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Fri, 22 Jun 2018 12:46:01 +0530 Subject: [PATCH 46/47] Update error message for Phone and Email auth --- .../AndroidImpl.uno | 22 ++++++++++++++----- .../AndroidImpl.uno | 4 ++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Firebase.Authentication.Email/AndroidImpl.uno b/src/Firebase.Authentication.Email/AndroidImpl.uno index 670d17e..9922af7 100644 --- a/src/Firebase.Authentication.Email/AndroidImpl.uno +++ b/src/Firebase.Authentication.Email/AndroidImpl.uno @@ -36,8 +36,13 @@ namespace Firebase.Authentication.Email { if (task.isSuccessful()) @{CreateUser:Of(_this).Resolve(string):Call("success")}; - else - @{CreateUser:Of(_this).Reject(string):Call("Firebase failed to create user")}; + else { + try { + @{CreateUser:Of(_this).Reject(string):Call(task.getException().getLocalizedMessage())}; + } catch (Exception e) { + @{CreateUser:Of(_this).Reject(string):Call("Firebase failed to create user")}; + } + } } }); @} @@ -76,10 +81,15 @@ namespace Firebase.Authentication.Email .addOnCompleteListener(com.fuse.Activity.getRootActivity(), new OnCompleteListener() { public void onComplete(Task task) { - if (task.isSuccessful()) - @{SignInUser:Of(_this).Resolve(string):Call("success")}; - else - @{SignInUser:Of(_this).Reject(string):Call("Firebase failed to signin user")}; + if (task.isSuccessful()) + @{SignInUser:Of(_this).Resolve(string):Call("success")}; + else { + try { + @{CreateUser:Of(_this).Reject(string):Call(task.getException().getLocalizedMessage())}; + } catch (Exception e) { + @{CreateUser:Of(_this).Reject(string):Call("Firebase failed to signin user")}; + } + } } }); @} diff --git a/src/Firebase.Authentication.Phone/AndroidImpl.uno b/src/Firebase.Authentication.Phone/AndroidImpl.uno index 9c87223..987338f 100644 --- a/src/Firebase.Authentication.Phone/AndroidImpl.uno +++ b/src/Firebase.Authentication.Phone/AndroidImpl.uno @@ -60,7 +60,7 @@ namespace Firebase.Authentication.Phone } else { Log.d("Log ", " " + task.getException().toString()); - @{CreateUser:Of(_this).Reject(string):Call(task.getException().toString())}; + @{CreateUser:Of(_this).Reject(string):Call(task.getException().getLocalizedMessage())}; } }}); } @@ -231,7 +231,7 @@ namespace Firebase.Authentication.Phone } else { Log.d("Log ", " " + task.getException().toString()); - @{ResendCodeValidation:Of(_this).Reject(string):Call(task.getException().toString())}; + @{ResendCodeValidation:Of(_this).Reject(string):Call(task.getException().getLocalizedMessage())}; } }}); } From 6a074778c63c6daf65054e27881c4d41b1fb7929 Mon Sep 17 00:00:00 2001 From: Dhvl-Golakiya Date: Fri, 22 Jun 2018 14:41:16 +0530 Subject: [PATCH 47/47] Minor class name callback changes --- src/Firebase.Authentication.Email/AndroidImpl.uno | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Firebase.Authentication.Email/AndroidImpl.uno b/src/Firebase.Authentication.Email/AndroidImpl.uno index 9922af7..e6e5f88 100644 --- a/src/Firebase.Authentication.Email/AndroidImpl.uno +++ b/src/Firebase.Authentication.Email/AndroidImpl.uno @@ -85,9 +85,9 @@ namespace Firebase.Authentication.Email @{SignInUser:Of(_this).Resolve(string):Call("success")}; else { try { - @{CreateUser:Of(_this).Reject(string):Call(task.getException().getLocalizedMessage())}; + @{SignInUser:Of(_this).Reject(string):Call(task.getException().getLocalizedMessage())}; } catch (Exception e) { - @{CreateUser:Of(_this).Reject(string):Call("Firebase failed to signin user")}; + @{SignInUser:Of(_this).Reject(string):Call("Firebase failed to signin user")}; } } }