This commit is contained in:
Salakar 2018-05-06 00:55:37 +01:00
commit e5233c9af3
20 changed files with 1711 additions and 846 deletions

51
.github/ISSUE_TEMPLATE/Bug_report.md vendored Normal file
View File

@ -0,0 +1,51 @@
---
name: ⚠️ Bug/Issue report
about: Please provide as much detail as possible to help us with a bug or issue. Issues
will be closed if they do not follow the template.
---
<!---
BEFORE YOU MAKE AN ISSUE
The issue list of this repo is exclusively for bug reports.
1) For feature requests, please use our Canny board: https://react-native-firebase.canny.io/feature-requests
2) For questions and support please use our Discord chat: https://discord.gg/C9aK28N or Stack Overflow: https://stackoverflow.com/questions/tagged/react-native-firebase
3) If this is a setup issue then please make sure you've correctly followed the setup guides, most setup issues such as 'duplicate dex files', 'default app has not been initialized' etc are all down to an incorrect setup as the guides haven't been correctly followed.
-->
### Issue
<!--- Please write your issue here, provide as much detail as you can, code snippets, key files which will help us to debug such as your `Podfile` and/or `app/build.gradle` file). -->
### Environment
<!--- (e.g. iOS, Android, Both) --->
1. Application Target Platform:
<!--- (e.g. macOS Sierra, Windows 10) --->
2. Development Operating System:
<!--- (Xcode or Android Studio version, iOS or Android SDK version - if relevant) --->
3. Build Tools:
<!--- (e.g. 0.45.1) --->
4. React Native version:
<!--- (e.g. 2.1.3) --->
5. RNFirebase Version:
<!--- (e.g. database, auth, messaging, analytics etc - or N/A if not applicable) --->
6. Firebase Module:
<!-- Love react-native-firebase? Please consider supporting our collective:
👉 https://opencollective.com/react-native-firebase/donate -->

View File

@ -0,0 +1,7 @@
---
name: 🎁 Feature request
about: Please create feature requests on our canny board: [https://react-native-firebase.canny.io/feature-requests](https://react-native-firebase.canny.io/feature-requests)
---
[https://react-native-firebase.canny.io/feature-requests](https://react-native-firebase.canny.io/feature-requests)

41
.github/ISSUE_TEMPLATE/Support_us.md vendored Normal file
View File

@ -0,0 +1,41 @@
---
name: 🤝 Support React Native Firebase
about: Please help to keep RNFirebase supported and maintained 🤘
---
## Supporting RNFirebase
RNFirebase is an Apache-2.0 licensed open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome [sponsors](#sponsors) and [backers](#backers). If you'd like to join them, please consider:
* [Become a backer or sponsor on Open Collective](https://opencollective.com/react-native-firebase).
### Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/react-native-firebase#sponsor)]
<a href="https://opencollective.com/react-native-firebase/sponsor/0/website" target="_blank"><img src="https://opencollective.com/react-native-firebase/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/react-native-firebase/sponsor/1/website" target="_blank"><img src="https://opencollective.com/react-native-firebase/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/react-native-firebase/sponsor/2/website" target="_blank"><img src="https://opencollective.com/react-native-firebase/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/react-native-firebase/sponsor/3/website" target="_blank"><img src="https://opencollective.com/react-native-firebase/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/react-native-firebase/sponsor/4/website" target="_blank"><img src="https://opencollective.com/react-native-firebase/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/react-native-firebase/sponsor/5/website" target="_blank"><img src="https://opencollective.com/react-native-firebase/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/react-native-firebase/sponsor/6/website" target="_blank"><img src="https://opencollective.com/react-native-firebase/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/react-native-firebase/sponsor/7/website" target="_blank"><img src="https://opencollective.com/react-native-firebase/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/react-native-firebase/sponsor/8/website" target="_blank"><img src="https://opencollective.com/react-native-firebase/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/react-native-firebase/sponsor/9/website" target="_blank"><img src="https://opencollective.com/react-native-firebase/sponsor/9/avatar.svg"></a>
### Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/react-native-firebase#backer)]
<a href="https://opencollective.com/react-native-firebase#backers" target="_blank"><img src="https://opencollective.com/react-native-firebase/backers.svg?width=890"></a>
### Contributing
Please make sure to read the [Contributing Guide](CONTRIBUTING.md) before making a pull request.
Thank you to all the people who have already contributed to RNFirebase!
<a href="graphs/contributors"><img src="https://opencollective.com/react-native-firebase/contributors.svg?width=890" /></a>
<hr>

View File

@ -1,5 +1,6 @@
package io.invertase.firebase.firestore;
import android.util.Base64;
import android.util.Log;
import com.facebook.react.bridge.Arguments;
@ -8,6 +9,7 @@ import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.google.firebase.firestore.Blob;
import com.google.firebase.firestore.DocumentChange;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
@ -209,6 +211,9 @@ public class FirestoreSerialize {
} else if (value instanceof Date) {
typeMap.putString("type", "date");
typeMap.putDouble("value", ((Date) value).getTime());
} else if (value instanceof Blob) {
typeMap.putString("type", "blob");
typeMap.putString("value", Base64.encodeToString(((Blob) value).toBytes(), Base64.NO_WRAP));
} else {
Log.e(TAG, "buildTypeMap: Cannot convert object of type " + value.getClass());
typeMap.putString("type", "null");
@ -261,6 +266,9 @@ public class FirestoreSerialize {
} else if ("geopoint".equals(type)) {
ReadableMap geoPoint = typeMap.getMap("value");
return new GeoPoint(geoPoint.getDouble("latitude"), geoPoint.getDouble("longitude"));
} else if ("blob".equals(type)) {
String base64String = typeMap.getString("value");
return Blob.fromBytes(Base64.decode(base64String, Base64.NO_WRAP));
} else if ("date".equals(type)) {
Double time = typeMap.getDouble("value");
return new Date(time.longValue());

View File

@ -0,0 +1,407 @@
package io.invertase.firebase.notifications;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.RemoteInput;
import android.util.Log;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import io.invertase.firebase.Utils;
public class DisplayNotificationTask extends AsyncTask<Void, Void, Void> {
private static final String TAG = "DisplayNotificationTask";
private final Context context;
private final Bundle notification;
private final NotificationManager notificationManager;
private final Promise promise;
private ReactApplicationContext reactContext;
public DisplayNotificationTask(Context context, ReactApplicationContext reactContext,
NotificationManager notificationManager,
Bundle notification, Promise promise) {
this.context = context;
this.notification = notification;
this.notificationManager = notificationManager;
this.promise = promise;
this.reactContext = reactContext;
}
@Override
protected Void doInBackground(Void... voids) {
try {
Class intentClass = getMainActivityClass();
if (intentClass == null) {
if (promise != null) {
promise.reject("notification/display_notification_error", "Could not find main activity class");
}
return null;
}
Bundle android = notification.getBundle("android");
String channelId = android.getString("channelId");
String notificationId = notification.getString("notificationId");
NotificationCompat.Builder nb;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
nb = new NotificationCompat.Builder(context, channelId);
} else {
nb = new NotificationCompat.Builder(context);
}
if (notification.containsKey("body")) {
nb = nb.setContentText(notification.getString("body"));
}
if (notification.containsKey("data")) {
nb = nb.setExtras(notification.getBundle("data"));
}
if (notification.containsKey("sound")) {
Uri sound = RNFirebaseNotificationManager.getSound(context, notification.getString("sound"));
nb = nb.setSound(sound);
}
if (notification.containsKey("subtitle")) {
nb = nb.setSubText(notification.getString("subtitle"));
}
if (notification.containsKey("title")) {
nb = nb.setContentTitle(notification.getString("title"));
}
if (android.containsKey("autoCancel")) {
nb = nb.setAutoCancel(android.getBoolean("autoCancel"));
}
if (android.containsKey("badgeIconType")) {
Double badgeIconType = android.getDouble("badgeIconType");
nb = nb.setBadgeIconType(badgeIconType.intValue());
}
if (android.containsKey("bigPicture")) {
Bundle bigPicture = android.getBundle("bigPicture");
NotificationCompat.BigPictureStyle bp = new NotificationCompat.BigPictureStyle();
Bitmap picture = getBitmap(bigPicture.getString("picture"));
if (picture != null) {
bp = bp.bigPicture(picture);
}
if (bigPicture.containsKey("largeIcon")) {
Bitmap largeIcon = getBitmap(bigPicture.getString("largeIcon"));
if (largeIcon != null) {
bp = bp.bigLargeIcon(largeIcon);
}
}
if (bigPicture.containsKey("contentTitle")) {
bp = bp.setBigContentTitle(bigPicture.getString("contentTitle"));
}
if (bigPicture.containsKey("summaryText")) {
bp = bp.setSummaryText(bigPicture.getString("summaryText"));
}
nb = nb.setStyle(bp);
}
if (android.containsKey("bigText")) {
Bundle bigText = android.getBundle("bigText");
NotificationCompat.BigTextStyle bt = new NotificationCompat.BigTextStyle();
bt.bigText(bigText.getString("text"));
if (bigText.containsKey("contentTitle")) {
bt = bt.setBigContentTitle(bigText.getString("contentTitle"));
}
if (bigText.containsKey("summaryText")) {
bt = bt.setSummaryText(bigText.getString("summaryText"));
}
nb = nb.setStyle(bt);
}
if (android.containsKey("category")) {
nb = nb.setCategory(android.getString("category"));
}
if (android.containsKey("color")) {
String color = android.getString("color");
nb = nb.setColor(Color.parseColor(color));
}
if (android.containsKey("colorized")) {
nb = nb.setColorized(android.getBoolean("colorized"));
}
if (android.containsKey("contentInfo")) {
nb = nb.setContentInfo(android.getString("contentInfo"));
}
if (notification.containsKey("defaults")) {
double[] defaultsArray = android.getDoubleArray("defaults");
int defaults = 0;
for (Double d : defaultsArray) {
defaults |= d.intValue();
}
nb = nb.setDefaults(defaults);
}
if (android.containsKey("group")) {
nb = nb.setGroup(android.getString("group"));
}
if (android.containsKey("groupAlertBehaviour")) {
Double groupAlertBehaviour = android.getDouble("groupAlertBehaviour");
nb = nb.setGroupAlertBehavior(groupAlertBehaviour.intValue());
}
if (android.containsKey("groupSummary")) {
nb = nb.setGroupSummary(android.getBoolean("groupSummary"));
}
if (android.containsKey("largeIcon")) {
Bitmap largeIcon = getBitmap(android.getString("largeIcon"));
if (largeIcon != null) {
nb = nb.setLargeIcon(largeIcon);
}
}
if (android.containsKey("lights")) {
Bundle lights = android.getBundle("lights");
Double argb = lights.getDouble("argb");
Double onMs = lights.getDouble("onMs");
Double offMs = lights.getDouble("offMs");
nb = nb.setLights(argb.intValue(), onMs.intValue(), offMs.intValue());
}
if (android.containsKey("localOnly")) {
nb = nb.setLocalOnly(android.getBoolean("localOnly"));
}
if (android.containsKey("number")) {
Double number = android.getDouble("number");
nb = nb.setNumber(number.intValue());
}
if (android.containsKey("ongoing")) {
nb = nb.setOngoing(android.getBoolean("ongoing"));
}
if (android.containsKey("onlyAlertOnce")) {
nb = nb.setOngoing(android.getBoolean("onlyAlertOnce"));
}
if (android.containsKey("people")) {
List<String> people = android.getStringArrayList("people");
if (people != null) {
for (String person : people) {
nb = nb.addPerson(person);
}
}
}
if (android.containsKey("priority")) {
Double priority = android.getDouble("priority");
nb = nb.setPriority(priority.intValue());
}
if (android.containsKey("progress")) {
Bundle progress = android.getBundle("lights");
Double max = progress.getDouble("max");
Double progressI = progress.getDouble("progress");
nb = nb.setProgress(max.intValue(), progressI.intValue(), progress.getBoolean("indeterminate"));
}
// TODO: Public version of notification
/* if (android.containsKey("publicVersion")) {
nb = nb.setPublicVersion();
} */
if (android.containsKey("remoteInputHistory")) {
nb = nb.setRemoteInputHistory(android.getStringArray("remoteInputHistory"));
}
if (android.containsKey("shortcutId")) {
nb = nb.setShortcutId(android.getString("shortcutId"));
}
if (android.containsKey("showWhen")) {
nb = nb.setShowWhen(android.getBoolean("showWhen"));
}
if (android.containsKey("smallIcon")) {
Bundle smallIcon = android.getBundle("smallIcon");
int smallIconResourceId = getIcon(smallIcon.getString("icon"));
if (smallIconResourceId != 0) {
if (smallIcon.containsKey("level")) {
Double level = smallIcon.getDouble("level");
nb = nb.setSmallIcon(smallIconResourceId, level.intValue());
} else {
nb = nb.setSmallIcon(smallIconResourceId);
}
}
}
if (android.containsKey("sortKey")) {
nb = nb.setSortKey(android.getString("sortKey"));
}
if (android.containsKey("ticker")) {
nb = nb.setTicker(android.getString("ticker"));
}
if (android.containsKey("timeoutAfter")) {
Double timeoutAfter = android.getDouble("timeoutAfter");
nb = nb.setTimeoutAfter(timeoutAfter.longValue());
}
if (android.containsKey("usesChronometer")) {
nb = nb.setUsesChronometer(android.getBoolean("usesChronometer"));
}
if (android.containsKey("vibrate")) {
ArrayList<Integer> vibrate = android.getIntegerArrayList("vibrate");
if(vibrate != null) {
long[] vibrateArray = new long[vibrate.size()];
for (int i = 0; i < vibrate.size(); i++) {
vibrateArray[i] = vibrate.get(i).longValue();
}
nb = nb.setVibrate(vibrateArray);
}
}
if (android.containsKey("visibility")) {
Double visibility = android.getDouble("visibility");
nb = nb.setVisibility(visibility.intValue());
}
if (android.containsKey("when")) {
Double when = android.getDouble("when");
nb = nb.setWhen(when.longValue());
}
// Build any actions
if (android.containsKey("actions")) {
List<Bundle> actions = (List) android.getSerializable("actions");
for (Bundle a : actions) {
NotificationCompat.Action action = createAction(a, intentClass, notification);
nb = nb.addAction(action);
}
}
// Create the notification intent
PendingIntent contentIntent = createIntent(intentClass, notification, android.getString("clickAction"));
nb = nb.setContentIntent(contentIntent);
// Build the notification and send it
Notification builtNotification = nb.build();
notificationManager.notify(notificationId.hashCode(), builtNotification);
if (reactContext != null) {
Utils.sendEvent(reactContext, "notifications_notification_displayed", Arguments.fromBundle(notification));
}
} catch (Exception e) {
Log.e(TAG, "Failed to send notification", e);
if (promise != null) {
promise.reject("notification/display_notification_error", "Could not send notification", e);
}
}
return null;
}
private NotificationCompat.Action createAction(Bundle action, Class intentClass, Bundle notification) {
String actionKey = action.getString("action");
PendingIntent actionIntent = createIntent(intentClass, notification, actionKey);
int icon = getIcon(action.getString("icon"));
String title = action.getString("title");
NotificationCompat.Action.Builder ab = new NotificationCompat.Action.Builder(icon, title, actionIntent);
if (action.containsKey("allowGeneratedReplies")) {
ab = ab.setAllowGeneratedReplies(action.getBoolean("allowGeneratedReplies"));
}
if (action.containsKey("remoteInputs")) {
List<Bundle> remoteInputs = (List) action.getSerializable("remoteInputs");
for (Bundle ri : remoteInputs) {
RemoteInput remoteInput = createRemoteInput(ri);
ab = ab.addRemoteInput(remoteInput);
}
}
// TODO: SemanticAction and ShowsUserInterface only available on v28?
// if (action.containsKey("semanticAction")) {
// Double semanticAction = action.getDouble("semanticAction");
// ab = ab.setSemanticAction(semanticAction.intValue());
// }
// if (action.containsKey("showsUserInterface")) {
// ab = ab.setShowsUserInterface(action.getBoolean("showsUserInterface"));
// }
return ab.build();
}
private PendingIntent createIntent(Class intentClass, Bundle notification, String action) {
Intent intent = new Intent(context, intentClass);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtras(notification);
if (action != null) {
intent.setAction(action);
}
String notificationId = notification.getString("notificationId");
return PendingIntent.getActivity(context, notificationId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
private RemoteInput createRemoteInput(Bundle remoteInput) {
String resultKey = remoteInput.getString("resultKey");
RemoteInput.Builder rb = new RemoteInput.Builder(resultKey);
if (remoteInput.containsKey("allowedDataTypes")) {
List<Bundle> allowedDataTypes = (List) remoteInput.getSerializable("allowedDataTypes");
for (Bundle adt : allowedDataTypes) {
rb.setAllowDataType(adt.getString("mimeType"), adt.getBoolean("allow"));
}
}
if (remoteInput.containsKey("allowFreeFormInput")) {
rb.setAllowFreeFormInput(remoteInput.getBoolean("allowFreeFormInput"));
}
if (remoteInput.containsKey("choices")) {
List<String> choices = remoteInput.getStringArrayList("choices");
rb.setChoices(choices.toArray(new String[choices.size()]));
}
if (remoteInput.containsKey("label")) {
rb.setLabel(remoteInput.getString("label"));
}
return rb.build();
}
private Bitmap getBitmap(String image) {
if (image.startsWith("http://") || image.startsWith("https://")) {
return getBitmapFromUrl(image);
} else if (image.startsWith("file://")) {
return BitmapFactory.decodeFile(image.replace("file://", ""));
} else {
int largeIconResId = RNFirebaseNotificationManager.getResourceId(context,"mipmap", image);
return BitmapFactory.decodeResource(context.getResources(), largeIconResId);
}
}
private Bitmap getBitmapFromUrl(String imageUrl) {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(imageUrl).openConnection();
connection.setDoInput(true);
connection.connect();
return BitmapFactory.decodeStream(connection.getInputStream());
} catch (IOException e) {
Log.e(TAG, "Failed to get bitmap for url: " + imageUrl, e);
return null;
}
}
private int getIcon(String icon) {
int smallIconResourceId = RNFirebaseNotificationManager.getResourceId(context,"mipmap", icon);
if (smallIconResourceId == 0) {
smallIconResourceId = RNFirebaseNotificationManager.getResourceId(context,"drawable", icon);
}
return smallIconResourceId;
}
private Class getMainActivityClass() {
String packageName = context.getPackageName();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
try {
return Class.forName(launchIntent.getComponent().getClassName());
} catch (ClassNotFoundException e) {
Log.e(TAG, "Failed to get main activity class", e);
return null;
}
}
}

View File

@ -202,365 +202,14 @@ public class RNFirebaseNotificationManager {
}
private void displayNotification(Bundle notification, Promise promise) {
try {
Class intentClass = getMainActivityClass();
if (intentClass == null) {
if (promise != null) {
promise.reject("notification/display_notification_error", "Could not find main activity class");
}
return;
}
Bundle android = notification.getBundle("android");
String channelId = android.getString("channelId");
String notificationId = notification.getString("notificationId");
NotificationCompat.Builder nb;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
nb = new NotificationCompat.Builder(context, channelId);
} else {
nb = new NotificationCompat.Builder(context);
}
if (notification.containsKey("body")) {
nb = nb.setContentText(notification.getString("body"));
}
if (notification.containsKey("data")) {
nb = nb.setExtras(notification.getBundle("data"));
}
if (notification.containsKey("sound")) {
Uri sound = getSound(notification.getString("sound"));
nb = nb.setSound(sound);
}
if (notification.containsKey("subtitle")) {
nb = nb.setSubText(notification.getString("subtitle"));
}
if (notification.containsKey("title")) {
nb = nb.setContentTitle(notification.getString("title"));
}
if (android.containsKey("autoCancel")) {
nb = nb.setAutoCancel(android.getBoolean("autoCancel"));
}
if (android.containsKey("badgeIconType")) {
Double badgeIconType = android.getDouble("badgeIconType");
nb = nb.setBadgeIconType(badgeIconType.intValue());
}
if (android.containsKey("bigPicture")) {
Bundle bigPicture = android.getBundle("bigPicture");
NotificationCompat.BigPictureStyle bp = new NotificationCompat.BigPictureStyle();
Bitmap picture = getBitmap(bigPicture.getString("picture"));
if (picture != null) {
bp = bp.bigPicture(picture);
}
if (bigPicture.containsKey("largeIcon")) {
Bitmap largeIcon = getBitmap(bigPicture.getString("largeIcon"));
if (largeIcon != null) {
bp = bp.bigLargeIcon(largeIcon);
}
}
if (bigPicture.containsKey("contentTitle")) {
bp = bp.setBigContentTitle(bigPicture.getString("contentTitle"));
}
if (bigPicture.containsKey("summaryText")) {
bp = bp.setSummaryText(bigPicture.getString("summaryText"));
}
nb = nb.setStyle(bp);
}
if (android.containsKey("bigText")) {
Bundle bigText = android.getBundle("bigText");
NotificationCompat.BigTextStyle bt = new NotificationCompat.BigTextStyle();
bt.bigText(bigText.getString("text"));
if (bigText.containsKey("contentTitle")) {
bt = bt.setBigContentTitle(bigText.getString("contentTitle"));
}
if (bigText.containsKey("summaryText")) {
bt = bt.setSummaryText(bigText.getString("summaryText"));
}
nb = nb.setStyle(bt);
}
if (android.containsKey("category")) {
nb = nb.setCategory(android.getString("category"));
}
if (android.containsKey("color")) {
String color = android.getString("color");
nb = nb.setColor(Color.parseColor(color));
}
if (android.containsKey("colorized")) {
nb = nb.setColorized(android.getBoolean("colorized"));
}
if (android.containsKey("contentInfo")) {
nb = nb.setContentInfo(android.getString("contentInfo"));
}
if (notification.containsKey("defaults")) {
double[] defaultsArray = android.getDoubleArray("defaults");
int defaults = 0;
for (Double d : defaultsArray) {
defaults |= d.intValue();
}
nb = nb.setDefaults(defaults);
}
if (android.containsKey("group")) {
nb = nb.setGroup(android.getString("group"));
}
if (android.containsKey("groupAlertBehaviour")) {
Double groupAlertBehaviour = android.getDouble("groupAlertBehaviour");
nb = nb.setGroupAlertBehavior(groupAlertBehaviour.intValue());
}
if (android.containsKey("groupSummary")) {
nb = nb.setGroupSummary(android.getBoolean("groupSummary"));
}
if (android.containsKey("largeIcon")) {
Bitmap largeIcon = getBitmap(android.getString("largeIcon"));
if (largeIcon != null) {
nb = nb.setLargeIcon(largeIcon);
}
}
if (android.containsKey("lights")) {
Bundle lights = android.getBundle("lights");
Double argb = lights.getDouble("argb");
Double onMs = lights.getDouble("onMs");
Double offMs = lights.getDouble("offMs");
nb = nb.setLights(argb.intValue(), onMs.intValue(), offMs.intValue());
}
if (android.containsKey("localOnly")) {
nb = nb.setLocalOnly(android.getBoolean("localOnly"));
}
if (android.containsKey("number")) {
Double number = android.getDouble("number");
nb = nb.setNumber(number.intValue());
}
if (android.containsKey("ongoing")) {
nb = nb.setOngoing(android.getBoolean("ongoing"));
}
if (android.containsKey("onlyAlertOnce")) {
nb = nb.setOngoing(android.getBoolean("onlyAlertOnce"));
}
if (android.containsKey("people")) {
List<String> people = android.getStringArrayList("people");
if (people != null) {
for (String person : people) {
nb = nb.addPerson(person);
}
}
}
if (android.containsKey("priority")) {
Double priority = android.getDouble("priority");
nb = nb.setPriority(priority.intValue());
}
if (android.containsKey("progress")) {
Bundle progress = android.getBundle("lights");
Double max = progress.getDouble("max");
Double progressI = progress.getDouble("progress");
nb = nb.setProgress(max.intValue(), progressI.intValue(), progress.getBoolean("indeterminate"));
}
// TODO: Public version of notification
/* if (android.containsKey("publicVersion")) {
nb = nb.setPublicVersion();
} */
if (android.containsKey("remoteInputHistory")) {
nb = nb.setRemoteInputHistory(android.getStringArray("remoteInputHistory"));
}
if (android.containsKey("shortcutId")) {
nb = nb.setShortcutId(android.getString("shortcutId"));
}
if (android.containsKey("showWhen")) {
nb = nb.setShowWhen(android.getBoolean("showWhen"));
}
if (android.containsKey("smallIcon")) {
Bundle smallIcon = android.getBundle("smallIcon");
int smallIconResourceId = getIcon(smallIcon.getString("icon"));
if (smallIconResourceId != 0) {
if (smallIcon.containsKey("level")) {
Double level = smallIcon.getDouble("level");
nb = nb.setSmallIcon(smallIconResourceId, level.intValue());
} else {
nb = nb.setSmallIcon(smallIconResourceId);
}
}
}
if (android.containsKey("sortKey")) {
nb = nb.setSortKey(android.getString("sortKey"));
}
if (android.containsKey("ticker")) {
nb = nb.setTicker(android.getString("ticker"));
}
if (android.containsKey("timeoutAfter")) {
Double timeoutAfter = android.getDouble("timeoutAfter");
nb = nb.setTimeoutAfter(timeoutAfter.longValue());
}
if (android.containsKey("usesChronometer")) {
nb = nb.setUsesChronometer(android.getBoolean("usesChronometer"));
}
if (android.containsKey("vibrate")) {
ArrayList<Integer> vibrate = android.getIntegerArrayList("vibrate");
if(vibrate != null) {
long[] vibrateArray = new long[vibrate.size()];
for (int i = 0; i < vibrate.size(); i++) {
vibrateArray[i] = vibrate.get(i).longValue();
}
nb = nb.setVibrate(vibrateArray);
}
}
if (android.containsKey("visibility")) {
Double visibility = android.getDouble("visibility");
nb = nb.setVisibility(visibility.intValue());
}
if (android.containsKey("when")) {
Double when = android.getDouble("when");
nb = nb.setWhen(when.longValue());
}
// Build any actions
if (android.containsKey("actions")) {
List<Bundle> actions = (List) android.getSerializable("actions");
for (Bundle a : actions) {
NotificationCompat.Action action = createAction(a, intentClass, notification);
nb = nb.addAction(action);
}
}
// Create the notification intent
PendingIntent contentIntent = createIntent(intentClass, notification, android.getString("clickAction"));
nb = nb.setContentIntent(contentIntent);
// Build the notification and send it
Notification builtNotification = nb.build();
notificationManager.notify(notificationId.hashCode(), builtNotification);
if (reactContext != null) {
Utils.sendEvent(reactContext, "notifications_notification_displayed", Arguments.fromBundle(notification));
}
} catch (Exception e) {
Log.e(TAG, "Failed to send notification", e);
if (promise != null) {
promise.reject("notification/display_notification_error", "Could not send notification", e);
}
}
new DisplayNotificationTask(context, reactContext, notificationManager, notification, promise).execute();
}
private NotificationCompat.Action createAction(Bundle action, Class intentClass, Bundle notification) {
String actionKey = action.getString("action");
PendingIntent actionIntent = createIntent(intentClass, notification, actionKey);
int icon = getIcon(action.getString("icon"));
String title = action.getString("title");
NotificationCompat.Action.Builder ab = new NotificationCompat.Action.Builder(icon, title, actionIntent);
if (action.containsKey("allowGeneratedReplies")) {
ab = ab.setAllowGeneratedReplies(action.getBoolean("allowGeneratedReplies"));
}
if (action.containsKey("remoteInputs")) {
List<Bundle> remoteInputs = (List) action.getSerializable("remoteInputs");
for (Bundle ri : remoteInputs) {
RemoteInput remoteInput = createRemoteInput(ri);
ab = ab.addRemoteInput(remoteInput);
}
}
// TODO: SemanticAction and ShowsUserInterface only available on v28?
// if (action.containsKey("semanticAction")) {
// Double semanticAction = action.getDouble("semanticAction");
// ab = ab.setSemanticAction(semanticAction.intValue());
// }
// if (action.containsKey("showsUserInterface")) {
// ab = ab.setShowsUserInterface(action.getBoolean("showsUserInterface"));
// }
return ab.build();
}
private PendingIntent createIntent(Class intentClass, Bundle notification, String action) {
Intent intent = new Intent(context, intentClass);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtras(notification);
if (action != null) {
intent.setAction(action);
}
String notificationId = notification.getString("notificationId");
return PendingIntent.getActivity(context, notificationId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
private RemoteInput createRemoteInput(Bundle remoteInput) {
String resultKey = remoteInput.getString("resultKey");
RemoteInput.Builder rb = new RemoteInput.Builder(resultKey);
if (remoteInput.containsKey("allowedDataTypes")) {
List<Bundle> allowedDataTypes = (List) remoteInput.getSerializable("allowedDataTypes");
for (Bundle adt : allowedDataTypes) {
rb.setAllowDataType(adt.getString("mimeType"), adt.getBoolean("allow"));
}
}
if (remoteInput.containsKey("allowFreeFormInput")) {
rb.setAllowFreeFormInput(remoteInput.getBoolean("allowFreeFormInput"));
}
if (remoteInput.containsKey("choices")) {
List<String> choices = remoteInput.getStringArrayList("choices");
rb.setChoices(choices.toArray(new String[choices.size()]));
}
if (remoteInput.containsKey("label")) {
rb.setLabel(remoteInput.getString("label"));
}
return rb.build();
}
private Bitmap getBitmap(String image) {
if (image.startsWith("http://") || image.startsWith("https://")) {
return getBitmapFromUrl(image);
} else if (image.startsWith("file://")) {
return BitmapFactory.decodeFile(image.replace("file://", ""));
} else {
int largeIconResId = getResourceId("mipmap", image);
return BitmapFactory.decodeResource(context.getResources(), largeIconResId);
}
}
private Bitmap getBitmapFromUrl(String imageUrl) {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(imageUrl).openConnection();
connection.setDoInput(true);
connection.connect();
return BitmapFactory.decodeStream(connection.getInputStream());
} catch (IOException e) {
Log.e(TAG, "Failed to get bitmap for url: " + imageUrl, e);
return null;
}
}
private int getIcon(String icon) {
int smallIconResourceId = getResourceId("mipmap", icon);
if (smallIconResourceId == 0) {
smallIconResourceId = getResourceId("drawable", icon);
}
return smallIconResourceId;
}
private Class getMainActivityClass() {
String packageName = context.getPackageName();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
try {
return Class.forName(launchIntent.getComponent().getClassName());
} catch (ClassNotFoundException e) {
Log.e(TAG, "Failed to get main activity class", e);
return null;
}
}
private int getResourceId(String type, String image) {
public static int getResourceId(Context context, String type, String image) {
return context.getResources().getIdentifier(image, type, context.getPackageName());
}
private Uri getSound(String sound) {
public static Uri getSound(Context context, String sound) {
if (sound == null) {
return null;
} else if (sound.contains("://")) {
@ -568,9 +217,9 @@ public class RNFirebaseNotificationManager {
} else if (sound.equalsIgnoreCase("default")) {
return RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
} else {
int soundResourceId = getResourceId("raw", sound);
int soundResourceId = getResourceId(context,"raw", sound);
if (soundResourceId == 0) {
soundResourceId = getResourceId("raw", sound.substring(0, sound.lastIndexOf('.')));
soundResourceId = getResourceId(context,"raw", sound.substring(0, sound.lastIndexOf('.')));
}
return Uri.parse("android.resource://" + context.getPackageName() + "/" + soundResourceId);
}
@ -616,7 +265,7 @@ public class RNFirebaseNotificationManager {
channel.setShowBadge(channelMap.getBoolean("showBadge"));
}
if (channelMap.hasKey("sound")) {
Uri sound = getSound(channelMap.getString("sound"));
Uri sound = getSound(context, channelMap.getString("sound"));
channel.setSound(sound, null);
}
if (channelMap.hasKey("vibrationEnabled")) {

View File

@ -0,0 +1,156 @@
const testObject = { hello: 'world', testRunId };
const testString = JSON.stringify(testObject);
const testBuffer = Buffer.from(testString);
const testBase64 = testBuffer.toString('base64');
const testObjectLarge = new Array(5000).fill(testObject);
const testStringLarge = JSON.stringify(testObjectLarge);
const testBufferLarge = Buffer.from(testStringLarge);
const testBase64Large = testBufferLarge.toString('base64');
/** ----------------
* CLASS TESTS
* -----------------*/
describe('firestore', () => {
it('should export Blob class on statics', async () => {
const { Blob } = firebase.firestore;
should.exist(Blob);
});
describe('Blob', () => {
it('.constructor() -> returns new instance of Blob', async () => {
const { Blob } = firebase.firestore;
const myBlob = new Blob(testStringLarge);
myBlob.should.be.instanceOf(Blob);
myBlob._binaryString.should.equal(testStringLarge);
myBlob.toBase64().should.equal(testBase64Large);
});
it('.fromBase64String() -> returns new instance of Blob', async () => {
const { Blob } = firebase.firestore;
const myBlob = Blob.fromBase64String(testBase64);
myBlob.should.be.instanceOf(Blob);
myBlob._binaryString.should.equal(testString);
should.deepEqual(
JSON.parse(myBlob._binaryString),
testObject,
'Expected Blob _binaryString internals to serialize to json and match test object'
);
});
it('.fromBase64String() -> throws if arg not typeof string and length > 0', async () => {
const { Blob } = firebase.firestore;
const myBlob = Blob.fromBase64String(testBase64);
myBlob.should.be.instanceOf(Blob);
(() => Blob.fromBase64String(1234)).should.throwError();
(() => Blob.fromBase64String('')).should.throwError();
});
it('.fromUint8Array() -> returns new instance of Blob', async () => {
const testUInt8Array = new Uint8Array(testBuffer);
const { Blob } = firebase.firestore;
const myBlob = Blob.fromUint8Array(testUInt8Array);
myBlob.should.be.instanceOf(Blob);
const json = JSON.parse(myBlob._binaryString);
json.hello.should.equal('world');
});
it('.fromUint8Array() -> throws if arg not instanceof Uint8Array', async () => {
const testUInt8Array = new Uint8Array(testBuffer);
const { Blob } = firebase.firestore;
const myBlob = Blob.fromUint8Array(testUInt8Array);
myBlob.should.be.instanceOf(Blob);
(() => Blob.fromUint8Array('derp')).should.throwError();
});
});
describe('Blob instance', () => {
it('.toString() -> returns string representation of blob instance', async () => {
const { Blob } = firebase.firestore;
const myBlob = Blob.fromBase64String(testBase64);
myBlob.should.be.instanceOf(Blob);
should.equal(
myBlob.toString().includes(testBase64),
true,
'toString() should return a string that includes the base64'
);
});
it('.isEqual() -> returns true or false', async () => {
const { Blob } = firebase.firestore;
const myBlob = Blob.fromBase64String(testBase64);
const myBlob2 = Blob.fromBase64String(testBase64Large);
myBlob.isEqual(myBlob).should.equal(true);
myBlob2.isEqual(myBlob).should.equal(false);
});
it('.isEqual() -> throws if arg not instanceof Blob', async () => {
const { Blob } = firebase.firestore;
const myBlob = Blob.fromBase64String(testBase64);
const myBlob2 = Blob.fromBase64String(testBase64Large);
myBlob.isEqual(myBlob).should.equal(true);
(() => myBlob2.isEqual('derp')).should.throwError();
});
it('.toBase64() -> returns base64 string', async () => {
const { Blob } = firebase.firestore;
const myBlob = Blob.fromBase64String(testBase64);
myBlob.should.be.instanceOf(Blob);
myBlob.toBase64().should.equal(testBase64);
});
it('.toUint8Array() -> returns Uint8Array', async () => {
const { Blob } = firebase.firestore;
const myBlob = Blob.fromBase64String(testBase64);
const testUInt8Array = new Uint8Array(testBuffer);
const testUInt8Array2 = new Uint8Array();
myBlob.should.be.instanceOf(Blob);
should.deepEqual(myBlob.toUint8Array(), testUInt8Array);
should.notDeepEqual(myBlob.toUint8Array(), testUInt8Array2);
});
});
});
/** ----------------
* USAGE TESTS
* -----------------*/
describe('firestore', () => {
describe('Blob', () => {
it('reads and writes small blobs', async () => {
const { Blob } = firebase.firestore;
await firebase
.firestore()
.doc('blob-tests/small')
.set({ blobby: Blob.fromBase64String(testBase64) });
const snapshot = await firebase
.firestore()
.doc('blob-tests/small')
.get();
const blob = snapshot.data().blobby;
blob._binaryString.should.equal(testString);
blob.toBase64().should.equal(testBase64);
});
it('reads and writes large blobs', async () => {
const { Blob } = firebase.firestore;
await firebase
.firestore()
.doc('blob-tests/large')
.set({ blobby: Blob.fromBase64String(testBase64Large) });
const snapshot = await firebase
.firestore()
.doc('blob-tests/large')
.get();
const blob = snapshot.data().blobby;
blob._binaryString.should.equal(testStringLarge);
blob.toBase64().should.equal(testBase64Large);
});
});
});

View File

@ -9,6 +9,38 @@ Object.defineProperty(global, 'firebase', {
},
});
// TODO move as part of bridge
const { Uint8Array } = global;
Object.defineProperty(global, 'Uint8Array', {
get() {
const { stack } = new Error();
if (
(stack.includes('Context.it') || stack.includes('Context.beforeEach')) &&
global.bridge &&
global.bridge.context
) {
return bridge.context.window.Uint8Array;
}
return Uint8Array;
},
});
// TODO move as part of bridge
const { Array } = global;
Object.defineProperty(global, 'Array', {
get() {
const { stack } = new Error();
if (
(stack.includes('Context.it') || stack.includes('Context.beforeEach')) &&
global.bridge &&
global.bridge.context
) {
return bridge.context.window.Array;
}
return Array;
},
});
global.isObject = function isObject(item) {
return item
? typeof item === 'object' && !Array.isArray(item) && item !== null
@ -30,11 +62,17 @@ global.randomString = (length, chars) => {
}
return result;
};
global.firebaseAdmin = require('firebase-admin');
global.testRunId = randomString(4, 'aA#');
/** ------------------
* Init WEB SDK
---------------------*/
/** ------------------
* Init ADMIN SDK
---------------------*/
global.firebaseAdmin = require('firebase-admin');
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(require('./service-account')),
databaseURL: 'https://rnfirebase-b9ad4.firebaseio.com',

View File

@ -16,4 +16,5 @@ Pod::Spec.new do |s|
s.platform = :ios, "9.0"
s.source_files = 'RNFirebase/**/*.{h,m}'
s.dependency 'React'
s.dependency 'Firebase/Core'
end

View File

@ -208,6 +208,10 @@ static NSMutableDictionary *_listeners;
typeMap[@"type"] = @"number";
}
typeMap[@"value"] = value;
} else if ([value isKindOfClass:[NSData class]]) {
typeMap[@"type"] = @"blob";
NSData *blob = (NSData *)value;
typeMap[@"value"] = [blob base64EncodedStringWithOptions:0];
} else {
// TODO: Log an error
typeMap[@"type"] = @"null";
@ -248,6 +252,8 @@ static NSMutableDictionary *_listeners;
return [RNFirebaseFirestoreDocumentReference parseJSMap:firestore jsMap:value];
} else if ([type isEqualToString:@"reference"]) {
return [firestore documentWithPath:value];
} else if ([type isEqualToString:@"blob"]) {
return [[NSData alloc] initWithBase64EncodedString:(NSString *) value options:0];
} else if ([type isEqualToString:@"geopoint"]) {
NSDictionary *geopoint = (NSDictionary*)value;
NSNumber *latitude = geopoint[@"latitude"];

1284
lib/index.d.ts vendored

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
import Base64 from './../../utils/Base64';
export default class Blob {
_binaryString: string;
constructor(binaryString: string) {
this._binaryString = binaryString;
}
/**
* Creates a new Blob from the given Base64 string
*
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#.fromBase64String
* @param base64 string
*/
static fromBase64String(base64: string): Blob {
if (typeof base64 !== 'string' || base64.length < 1) {
throw new Error(
'firestore.Blob.fromBase64String expects a string of at least 1 character in length'
);
}
return new Blob(Base64.atob(base64));
}
/**
* Creates a new Blob from the given Uint8Array.
*
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#.fromUint8Array
* @param array Array
*/
static fromUint8Array(array: Uint8Array): Blob {
if (!(array instanceof Uint8Array)) {
throw new Error(
'firestore.Blob.fromUint8Array expects an instance of Uint8Array'
);
}
return new Blob(
Array.prototype.map
.call(array, (char: number) => String.fromCharCode(char))
.join('')
);
}
/**
* Returns 'true' if this Blob is equal to the provided one.
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#isEqual
* @param {*} blob Blob The Blob to compare against. Value must not be null.
* @returns boolean 'true' if this Blob is equal to the provided one.
*/
isEqual(blob: Blob): boolean {
if (!(blob instanceof Blob)) {
throw new Error('firestore.Blob.isEqual expects an instance of Blob');
}
return this._binaryString === blob._binaryString;
}
/**
* Returns the bytes of a Blob as a Base64-encoded string.
*
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#toBase64
* @returns string The Base64-encoded string created from the Blob object.
*/
toBase64(): string {
return Base64.btoa(this._binaryString);
}
/**
* Returns the bytes of a Blob in a new Uint8Array.
*
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#toUint8Array
* @returns non-null Uint8Array The Uint8Array created from the Blob object.
*/
toUint8Array(): Uint8Array {
return new Uint8Array(
this._binaryString.split('').map(c => c.charCodeAt(0))
);
}
/**
* Returns a string representation of this blob instance
*
* @returns {string}
* @memberof Blob
*/
toString(): string {
return `firestore.Blob(base64: ${this.toBase64()})`;
}
}

View File

@ -11,6 +11,7 @@ import DocumentReference from './DocumentReference';
import FieldPath from './FieldPath';
import FieldValue from './FieldValue';
import GeoPoint from './GeoPoint';
import Blob from './Blob';
import Path from './Path';
import WriteBatch from './WriteBatch';
import TransactionHandler from './TransactionHandler';
@ -255,6 +256,7 @@ export default class Firestore extends ModuleBase {
}
export const statics = {
Blob,
FieldPath,
FieldValue,
GeoPoint,

View File

@ -42,6 +42,7 @@ export type NativeTypeMap = {
| 'array'
| 'boolean'
| 'date'
| 'blob'
| 'documentid'
| 'fieldvalue'
| 'geopoint'

View File

@ -3,6 +3,7 @@
*/
import DocumentReference from '../DocumentReference';
import Blob from '../Blob';
import { DOCUMENT_ID } from '../FieldPath';
import {
DELETE_FIELD_VALUE,
@ -98,6 +99,11 @@ export const buildTypeMap = (value: any): NativeTypeMap | null => {
type: 'date',
value: value.getTime(),
};
} else if (value instanceof Blob) {
return {
type: 'blob',
value: value.toBase64(),
};
}
return {
type: 'object',
@ -156,6 +162,8 @@ const parseTypeMap = (firestore: Firestore, typeMap: NativeTypeMap): any => {
return new GeoPoint(value.latitude, value.longitude);
} else if (type === 'date') {
return new Date(value);
} else if (type === 'blob') {
return Blob.fromBase64String(value);
}
console.warn(`Unknown data type received ${type}`);
return value;

View File

@ -103,9 +103,9 @@ export const fromNativeAndroidRemoteInput = (
nativeRemoteInput: NativeAndroidRemoteInput
): AndroidRemoteInput => {
const remoteInput = new AndroidRemoteInput(nativeRemoteInput.resultKey);
if (nativeRemoteInput.allowDataType) {
for (let i = 0; i < nativeRemoteInput.allowDataType.length; i++) {
const allowDataType = nativeRemoteInput.allowDataType[i];
if (nativeRemoteInput.allowedDataTypes) {
for (let i = 0; i < nativeRemoteInput.allowedDataTypes.length; i++) {
const allowDataType = nativeRemoteInput.allowedDataTypes[i];
remoteInput.setAllowDataType(allowDataType.mimeType, allowDataType.allow);
}
}

68
lib/utils/Base64.js Normal file
View File

@ -0,0 +1,68 @@
// @flow
/* eslint-disable */
const CHARS =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
export default {
/**
* window.btoa
*/
btoa(input: string = ''): string {
let map;
let i = 0;
let block = 0;
let output = '';
// eslint-disable-next-line
for (
block = 0, i = 0, map = CHARS;
input.charAt(i | 0) || ((map = '='), i % 1);
output += map.charAt(63 & (block >> (8 - (i % 1) * 8)))
) {
const charCode = input.charCodeAt((i += 3 / 4));
if (charCode > 0xff) {
throw new Error(
"'RNFirebase.utils.btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
);
}
block = (block << 8) | charCode;
}
return output;
},
/**
* window.atob
*/
atob(input: string = ''): string {
let i = 0;
let bc = 0;
let bs = 0;
let buffer;
let output = '';
const str = input.replace(/=+$/, '');
if (str.length % 4 === 1) {
throw new Error(
"'RNFirebase.utils.atob' failed: The string to be decoded is not correctly encoded."
);
}
// eslint-disable-next-line
for (
bc = 0, bs = 0, i = 0;
(buffer = str.charAt(i++));
~buffer && ((bs = bc % 4 ? bs * 64 + buffer : buffer), bc++ % 4)
? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6))))
: 0
) {
buffer = CHARS.indexOf(buffer);
}
return output;
},
};

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "react-native-firebase",
"version": "4.0.6",
"version": "4.0.7",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "react-native-firebase",
"version": "4.0.6",
"version": "4.0.7",
"author": "Invertase <contact@invertase.io> (http://invertase.io)",
"description": "A well tested, feature rich Firebase implementation for React Native, supporting iOS & Android. Individual module support for Admob, Analytics, Auth, Crash Reporting, Cloud Firestore, Database, Dynamic Links, Messaging (FCM), Remote Config, Storage and Performance.",
"main": "dist/index.js",

View File

@ -47,6 +47,7 @@ const notifications = async () => {
RNfirebase.notifications().onNotificationDisplayed(notification => {
console.log('onNotificationDisplayed: ', notification);
});
// RNfirebase.iid().delete();
const channel = new RNfirebase.notifications.Android.Channel(
'test',
@ -77,7 +78,13 @@ const notifications = async () => {
.android.addAction(action)
.android.setChannelId('test')
.android.setClickAction('action')
.android.setPriority(RNfirebase.notifications.Android.Priority.Max);
.android.setPriority(RNfirebase.notifications.Android.Priority.Max)
.android.setBigPicture(
'https://image.winudf.com/v2/image/Y29tLmFsZmFwaXhlbC5tYWhhZGV2aGR3YWxscGFwZXJfc2NyZWVuXzFfbGtzbzJwZGc/screen-1.jpg?h=355&fakeurl=1&type=.jpg',
'https://www.google.co.in/images/branding/product/ico/googleg_lodp.ico',
'test title 1',
'test title 2'
);
const date = new Date();
date.setMinutes(date.getMinutes() + 1);