[NEW] Push notification data privacy (#2213)
* [WIP] Notification Service * [WIP] Android push notification privacy * [WIP] Retry request when it fails (iOS) * [WIP] Override notification bundle * [CHORE] Remove unnecessary import * [WIP] Check notification Type (iOS) * [WIP] Change to notification endpoint * eof * fix unwrap conditional value * turn run request synchronous * fix bundle info * eof * remove extra tab * undo unnecessary change * remove not working code for a while * fix notification title * change endpoint and received/sent data * message-id-only working properly on android * notification privacy working on ios * invalidate circleCI yarn cache * Fix provisioning profiles * fix notification service version * fix unwrap nil * compatibility older servers android * show received notification when cant fetch content from server * undo some android changes * prevent group & reply fallback notifications * dont show more than one fallback notification by server Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
parent
72ec569029
commit
b68b0b84df
|
@ -0,0 +1,10 @@
|
|||
package chat.rocket.reactnative;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class Callback {
|
||||
public void call(@Nullable Bundle bundle) {
|
||||
|
||||
}
|
||||
}
|
|
@ -14,8 +14,9 @@ import android.graphics.drawable.Icon;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.app.Person;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.Gson;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
@ -33,15 +34,18 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
|
||||
import static com.wix.reactnativenotifications.Defs.NOTIFICATION_RECEIVED_EVENT_NAME;
|
||||
|
||||
public class CustomPushNotification extends PushNotification {
|
||||
public static ReactApplicationContext reactApplicationContext;
|
||||
final NotificationManager notificationManager;
|
||||
|
||||
public CustomPushNotification(Context context, Bundle bundle, AppLifecycleFacade appLifecycleFacade, AppLaunchHelper appLaunchHelper, JsIOHelper jsIoHelper) {
|
||||
super(context, bundle, appLifecycleFacade, appLaunchHelper, jsIoHelper);
|
||||
reactApplicationContext = new ReactApplicationContext(context);
|
||||
notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
|
||||
private static Map<String, List<Bundle>> notificationMessages = new HashMap<String, List<Bundle>>();
|
||||
|
@ -54,29 +58,39 @@ public class CustomPushNotification extends PushNotification {
|
|||
|
||||
@Override
|
||||
public void onReceived() throws InvalidNotificationException {
|
||||
final Bundle bundle = mNotificationProps.asBundle();
|
||||
Bundle received = mNotificationProps.asBundle();
|
||||
Ejson receivedEjson = new Gson().fromJson(received.getString("ejson", "{}"), Ejson.class);
|
||||
|
||||
if (receivedEjson.notificationType != null && receivedEjson.notificationType.equals("message-id-only")) {
|
||||
notificationLoad(receivedEjson.serverURL(), receivedEjson.messageId, new Callback() {
|
||||
@Override
|
||||
public void call(@Nullable Bundle bundle) {
|
||||
if (bundle != null) {
|
||||
mNotificationProps = createProps(bundle);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// We should re-read these values since that can be changed by notificationLoad
|
||||
Bundle bundle = mNotificationProps.asBundle();
|
||||
Ejson loadedEjson = new Gson().fromJson(bundle.getString("ejson", "{}"), Ejson.class);
|
||||
String notId = bundle.getString("notId", "1");
|
||||
String title = bundle.getString("title");
|
||||
|
||||
if (notificationMessages.get(notId) == null) {
|
||||
notificationMessages.put(notId, new ArrayList<Bundle>());
|
||||
}
|
||||
|
||||
Gson gson = new Gson();
|
||||
Ejson ejson = gson.fromJson(bundle.getString("ejson", "{}"), Ejson.class);
|
||||
|
||||
boolean hasSender = ejson.sender != null;
|
||||
boolean hasSender = loadedEjson.sender != null;
|
||||
String title = bundle.getString("title");
|
||||
|
||||
bundle.putLong("time", new Date().getTime());
|
||||
bundle.putString("username", hasSender ? ejson.sender.username : title);
|
||||
bundle.putString("senderId", hasSender ? ejson.sender._id : "1");
|
||||
bundle.putString("avatarUri", ejson.getAvatarUri());
|
||||
bundle.putString("username", hasSender ? loadedEjson.sender.username : title);
|
||||
bundle.putString("senderId", hasSender ? loadedEjson.sender._id : "1");
|
||||
bundle.putString("avatarUri", loadedEjson.getAvatarUri());
|
||||
|
||||
notificationMessages.get(notId).add(bundle);
|
||||
|
||||
super.postNotification(Integer.parseInt(notId));
|
||||
|
||||
postNotification(Integer.parseInt(notId));
|
||||
notifyReceivedToJS();
|
||||
}
|
||||
|
||||
|
@ -96,6 +110,8 @@ public class CustomPushNotification extends PushNotification {
|
|||
String notId = bundle.getString("notId", "1");
|
||||
String title = bundle.getString("title");
|
||||
String message = bundle.getString("message");
|
||||
Boolean notificationLoaded = bundle.getBoolean("notificationLoaded", false);
|
||||
Ejson ejson = new Gson().fromJson(bundle.getString("ejson", "{}"), Ejson.class);
|
||||
|
||||
notification
|
||||
.setContentTitle(title)
|
||||
|
@ -109,9 +125,33 @@ public class CustomPushNotification extends PushNotification {
|
|||
notificationColor(notification);
|
||||
notificationChannel(notification);
|
||||
notificationIcons(notification, bundle);
|
||||
notificationDismiss(notification, notificationId);
|
||||
|
||||
// if notificationType is null (RC < 3.5) or notificationType is different of message-id-only or notification was loaded successfully
|
||||
if (ejson.notificationType == null || !ejson.notificationType.equals("message-id-only") || notificationLoaded) {
|
||||
notificationStyle(notification, notificationId, bundle);
|
||||
notificationReply(notification, notificationId, bundle);
|
||||
notificationDismiss(notification, notificationId);
|
||||
|
||||
// message couldn't be loaded from server (Fallback notification)
|
||||
} else {
|
||||
Gson gson = new Gson();
|
||||
// iterate over the current notification ids to dismiss fallback notifications from same server
|
||||
for (Map.Entry<String, List<Bundle>> bundleList : notificationMessages.entrySet()) {
|
||||
// iterate over the notifications with this id (same host + rid)
|
||||
Iterator iterator = bundleList.getValue().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Bundle not = (Bundle) iterator.next();
|
||||
// get the notification info
|
||||
Ejson notEjson = gson.fromJson(not.getString("ejson", "{}"), Ejson.class);
|
||||
// if already has a notification from same server
|
||||
if (ejson.serverURL().equals(notEjson.serverURL())) {
|
||||
String id = not.getString("notId");
|
||||
// cancel this notification
|
||||
notificationManager.cancel(Integer.parseInt(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
@ -300,4 +340,7 @@ public class CustomPushNotification extends PushNotification {
|
|||
notification.setDeleteIntent(dismissPendingIntent);
|
||||
}
|
||||
|
||||
private void notificationLoad(String server, String messageId, Callback callback) {
|
||||
LoadNotification.load(reactApplicationContext, server, messageId, callback);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ public class Ejson {
|
|||
String rid;
|
||||
String type;
|
||||
Sender sender;
|
||||
String messageId;
|
||||
String notificationType;
|
||||
|
||||
private String TOKEN_KEY = "reactnativemeteor_usertoken-";
|
||||
private SharedPreferences sharedPreferences = RNUserDefaultsModule.getPreferences(CustomPushNotification.reactApplicationContext);
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
package chat.rocket.reactnative;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.Interceptor;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
|
||||
import chat.rocket.userdefaults.RNUserDefaultsModule;
|
||||
|
||||
class JsonResponse {
|
||||
Data data;
|
||||
|
||||
class Data {
|
||||
Notification notification;
|
||||
|
||||
class Notification {
|
||||
String notId;
|
||||
String title;
|
||||
String text;
|
||||
Payload payload;
|
||||
|
||||
class Payload {
|
||||
String host;
|
||||
String rid;
|
||||
String type;
|
||||
Sender sender;
|
||||
String messageId;
|
||||
String notificationType;
|
||||
|
||||
class Sender {
|
||||
String username;
|
||||
String _id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LoadNotification {
|
||||
private static int RETRY_COUNT = 0;
|
||||
private static int[] TIMEOUT = new int[]{ 0, 1, 3, 5, 10 };
|
||||
private static String TOKEN_KEY = "reactnativemeteor_usertoken-";
|
||||
private static SharedPreferences sharedPreferences = RNUserDefaultsModule.getPreferences(CustomPushNotification.reactApplicationContext);
|
||||
|
||||
public static void load(ReactApplicationContext reactApplicationContext, final String host, final String msgId, Callback callback) {
|
||||
final OkHttpClient client = new OkHttpClient();
|
||||
HttpUrl.Builder url = HttpUrl.parse(host.concat("/api/v1/push.get")).newBuilder();
|
||||
|
||||
String userId = sharedPreferences.getString(TOKEN_KEY.concat(host), "");
|
||||
String token = sharedPreferences.getString(TOKEN_KEY.concat(userId), "");
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.header("x-user-id", userId)
|
||||
.header("x-auth-token", token)
|
||||
.url(url.addQueryParameter("id", msgId).build())
|
||||
.build();
|
||||
|
||||
runRequest(client, request, callback);
|
||||
}
|
||||
|
||||
private static void runRequest(OkHttpClient client, Request request, Callback callback) {
|
||||
try {
|
||||
Thread.sleep(TIMEOUT[RETRY_COUNT] * 1000);
|
||||
|
||||
Response response = client.newCall(request).execute();
|
||||
String body = response.body().string();
|
||||
if (!response.isSuccessful()) {
|
||||
throw new Exception("Error");
|
||||
}
|
||||
|
||||
Gson gson = new Gson();
|
||||
JsonResponse json = gson.fromJson(body, JsonResponse.class);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("notId", json.data.notification.notId);
|
||||
bundle.putString("title", json.data.notification.title);
|
||||
bundle.putString("message", json.data.notification.text);
|
||||
bundle.putString("ejson", gson.toJson(json.data.notification.payload));
|
||||
bundle.putBoolean("notificationLoaded", true);
|
||||
|
||||
callback.call(bundle);
|
||||
|
||||
} catch (Exception e) {
|
||||
if (RETRY_COUNT <= TIMEOUT.length) {
|
||||
RETRY_COUNT++;
|
||||
runRequest(client, request, callback);
|
||||
} else {
|
||||
callback.call(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AppGroup</key>
|
||||
<string>group.ios.chat.rocket</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>NotificationService</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.usernotifications.service</string>
|
||||
<key>NSExtensionPrincipalClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.ios.chat.rocket</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,154 @@
|
|||
import CoreLocation
|
||||
import UserNotifications
|
||||
|
||||
struct PushResponse: Decodable {
|
||||
let success: Bool
|
||||
let data: Data
|
||||
|
||||
struct Data: Decodable {
|
||||
let notification: Notification
|
||||
|
||||
struct Notification: Decodable {
|
||||
let notId: Int
|
||||
let title: String
|
||||
let text: String
|
||||
let payload: Payload
|
||||
|
||||
struct Payload: Decodable, Encodable {
|
||||
let host: String
|
||||
let rid: String?
|
||||
let type: String?
|
||||
let sender: Sender?
|
||||
let messageId: String
|
||||
let notificationType: String?
|
||||
let name: String?
|
||||
|
||||
struct Sender: Decodable, Encodable {
|
||||
let _id: String
|
||||
let username: String
|
||||
let name: String
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NotificationService: UNNotificationServiceExtension {
|
||||
|
||||
var contentHandler: ((UNNotificationContent) -> Void)?
|
||||
var bestAttemptContent: UNMutableNotificationContent?
|
||||
|
||||
var retryCount = 0
|
||||
var retryTimeout = [1.0, 3.0, 5.0, 10.0]
|
||||
|
||||
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
||||
self.contentHandler = contentHandler
|
||||
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
|
||||
|
||||
if let bestAttemptContent = bestAttemptContent {
|
||||
let ejson = (bestAttemptContent.userInfo["ejson"] as? String ?? "").data(using: .utf8)!
|
||||
guard let data = try? (JSONDecoder().decode(PushResponse.Data.Notification.Payload.self, from: ejson)) else {
|
||||
return
|
||||
}
|
||||
|
||||
let notificationType = data.notificationType ?? ""
|
||||
|
||||
// If the notification have the content at her payload, show it
|
||||
if notificationType != "message-id-only" {
|
||||
contentHandler(bestAttemptContent)
|
||||
return
|
||||
}
|
||||
|
||||
let suiteName = Bundle.main.object(forInfoDictionaryKey: "AppGroup") as! String
|
||||
let userDefaults = UserDefaults(suiteName: suiteName)
|
||||
|
||||
var server = data.host
|
||||
if (server.last == "/") {
|
||||
server.removeLast()
|
||||
}
|
||||
let msgId = data.messageId
|
||||
|
||||
let userId = userDefaults?.string(forKey: "reactnativemeteor_usertoken-\(server)") ?? ""
|
||||
let token = userDefaults?.string(forKey: "reactnativemeteor_usertoken-\(userId)") ?? ""
|
||||
|
||||
if userId.isEmpty || token.isEmpty {
|
||||
contentHandler(bestAttemptContent)
|
||||
return
|
||||
}
|
||||
|
||||
var urlComponents = URLComponents(string: "\(server)/api/v1/push.get")!
|
||||
let queryItems = [URLQueryItem(name: "id", value: msgId)]
|
||||
urlComponents.queryItems = queryItems
|
||||
|
||||
var request = URLRequest(url: urlComponents.url!)
|
||||
request.httpMethod = "GET"
|
||||
request.addValue(userId, forHTTPHeaderField: "x-user-id")
|
||||
request.addValue(token, forHTTPHeaderField: "x-auth-token")
|
||||
|
||||
runRequest(request: request, bestAttemptContent: bestAttemptContent, contentHandler: contentHandler)
|
||||
}
|
||||
}
|
||||
|
||||
func runRequest(request: URLRequest, bestAttemptContent: UNMutableNotificationContent, contentHandler: @escaping (UNNotificationContent) -> Void) {
|
||||
let task = URLSession.shared.dataTask(with: request) {(data, response, error) in
|
||||
|
||||
func retryRequest() {
|
||||
// if we can try again
|
||||
if self.retryCount < self.retryTimeout.count {
|
||||
// Try again after X seconds
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + self.retryTimeout[self.retryCount], execute: {
|
||||
self.runRequest(request: request, bestAttemptContent: bestAttemptContent, contentHandler: contentHandler)
|
||||
self.retryCount += 1
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// If some error happened
|
||||
if error != nil {
|
||||
retryRequest()
|
||||
|
||||
// Check if the request did successfully
|
||||
} else if let response = response as? HTTPURLResponse {
|
||||
// if it not was successfully
|
||||
if response.statusCode != 200 {
|
||||
retryRequest()
|
||||
|
||||
// If the response status is 200
|
||||
} else {
|
||||
// Process data
|
||||
if let data = data {
|
||||
// Parse data of response
|
||||
let push = try? (JSONDecoder().decode(PushResponse.self, from: data))
|
||||
if let push = push {
|
||||
if push.success {
|
||||
bestAttemptContent.title = push.data.notification.title
|
||||
bestAttemptContent.body = push.data.notification.text
|
||||
|
||||
let payload = try? (JSONEncoder().encode(push.data.notification.payload))
|
||||
if let payload = payload {
|
||||
bestAttemptContent.userInfo["ejson"] = String(data: payload, encoding: .utf8) ?? "{}"
|
||||
}
|
||||
|
||||
// Show notification with the content modified
|
||||
contentHandler(bestAttemptContent)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
retryRequest()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task.resume()
|
||||
}
|
||||
|
||||
override func serviceExtensionTimeWillExpire() {
|
||||
// Called just before the extension will be terminated by the system.
|
||||
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
|
||||
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
|
||||
contentHandler(bestAttemptContent)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -28,6 +28,8 @@
|
|||
1EC6ACF622CBA01500A41C61 /* ShareRocketChatRN.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EC6ACF522CBA01500A41C61 /* ShareRocketChatRN.m */; };
|
||||
1ED59D4C22CBA77D00C54289 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1ED59D4B22CBA77D00C54289 /* GoogleService-Info.plist */; };
|
||||
1EDDE57A22DFAD8E0078F69D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1EDDE57922DFAD8E0078F69D /* Images.xcassets */; };
|
||||
1EFEB5982493B6640072EDC0 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EFEB5972493B6640072EDC0 /* NotificationService.swift */; };
|
||||
1EFEB59C2493B6640072EDC0 /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 1EFEB5952493B6640072EDC0 /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 06BB44DD4855498082A744AD /* libz.tbd */; };
|
||||
50046CB6BDA69B9232CF66D9 /* libPods-RocketChatRN.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C235DC7B31A4D1578EDEF219 /* libPods-RocketChatRN.a */; };
|
||||
7A006F14229C83B600803143 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7A006F13229C83B600803143 /* GoogleService-Info.plist */; };
|
||||
|
@ -48,6 +50,13 @@
|
|||
remoteGlobalIDString = 1EC6ACAF22CB9FC300A41C61;
|
||||
remoteInfo = ShareRocketChatRN;
|
||||
};
|
||||
1EFEB59A2493B6640072EDC0 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 1EFEB5942493B6640072EDC0;
|
||||
remoteInfo = NotificationService;
|
||||
};
|
||||
7AAA749A23043AD300F1ADE9 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 290E43E48AD8418287FA99D6 /* WatermelonDB.xcodeproj */;
|
||||
|
@ -65,6 +74,7 @@
|
|||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
1EC6ACBB22CB9FC300A41C61 /* ShareRocketChatRN.appex in Embed App Extensions */,
|
||||
1EFEB59C2493B6640072EDC0 /* NotificationService.appex in Embed App Extensions */,
|
||||
);
|
||||
name = "Embed App Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -98,6 +108,10 @@
|
|||
1EC6AD6022CBA20C00A41C61 /* ShareRocketChatRN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareRocketChatRN.entitlements; sourceTree = "<group>"; };
|
||||
1ED59D4B22CBA77D00C54289 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; };
|
||||
1EDDE57922DFAD8E0078F69D /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
1EFEB5952493B6640072EDC0 /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1EFEB5972493B6640072EDC0 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
|
||||
1EFEB5992493B6640072EDC0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
1EFEB5A12493B67D0072EDC0 /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = "<group>"; };
|
||||
290E43E48AD8418287FA99D6 /* WatermelonDB.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = WatermelonDB.xcodeproj; path = "../node_modules/@nozbe/watermelondb/native/ios/WatermelonDB.xcodeproj"; sourceTree = "<group>"; };
|
||||
60B2A6A31FC4588700BD58E5 /* RocketChatRN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = RocketChatRN.entitlements; path = RocketChatRN/RocketChatRN.entitlements; sourceTree = "<group>"; };
|
||||
66D6B1D0567051BE541450C9 /* Pods-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RocketChatRN.release.xcconfig"; path = "Pods/Target Support Files/Pods-RocketChatRN/Pods-RocketChatRN.release.xcconfig"; sourceTree = "<group>"; };
|
||||
|
@ -146,6 +160,13 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
1EFEB5922493B6640072EDC0 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
|
@ -180,6 +201,16 @@
|
|||
path = ShareRocketChatRN;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1EFEB5962493B6640072EDC0 /* NotificationService */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1EFEB5A12493B67D0072EDC0 /* NotificationService.entitlements */,
|
||||
1EFEB5972493B6640072EDC0 /* NotificationService.swift */,
|
||||
1EFEB5992493B6640072EDC0 /* Info.plist */,
|
||||
);
|
||||
path = NotificationService;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
22CA7F59107E0C79C2506C7C /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -213,6 +244,7 @@
|
|||
13B07FAE1A68108700A75B9A /* RocketChatRN */,
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
1EC6ACB122CB9FC300A41C61 /* ShareRocketChatRN */,
|
||||
1EFEB5962493B6640072EDC0 /* NotificationService */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
BB4B591B5FC44CD9986DB2A6 /* Frameworks */,
|
||||
AF5E16F0398347E6A80C8CBE /* Resources */,
|
||||
|
@ -228,6 +260,7 @@
|
|||
children = (
|
||||
13B07F961A680F5B00A75B9A /* RocketChatRN.app */,
|
||||
1EC6ACB022CB9FC300A41C61 /* ShareRocketChatRN.appex */,
|
||||
1EFEB5952493B6640072EDC0 /* NotificationService.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -293,6 +326,7 @@
|
|||
);
|
||||
dependencies = (
|
||||
1EC6ACBA22CB9FC300A41C61 /* PBXTargetDependency */,
|
||||
1EFEB59B2493B6640072EDC0 /* PBXTargetDependency */,
|
||||
);
|
||||
name = RocketChatRN;
|
||||
productName = "Hello World";
|
||||
|
@ -321,6 +355,23 @@
|
|||
productReference = 1EC6ACB022CB9FC300A41C61 /* ShareRocketChatRN.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
1EFEB5942493B6640072EDC0 /* NotificationService */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 1EFEB5A02493B6640072EDC0 /* Build configuration list for PBXNativeTarget "NotificationService" */;
|
||||
buildPhases = (
|
||||
1EFEB5912493B6640072EDC0 /* Sources */,
|
||||
1EFEB5922493B6640072EDC0 /* Frameworks */,
|
||||
1EFEB5932493B6640072EDC0 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = NotificationService;
|
||||
productName = NotificationService;
|
||||
productReference = 1EFEB5952493B6640072EDC0 /* NotificationService.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
|
@ -328,6 +379,7 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
DefaultBuildSystemTypeForWorkspace = Original;
|
||||
LastSwiftUpdateCheck = 1150;
|
||||
LastUpgradeCheck = 1130;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
|
@ -360,6 +412,11 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
1EFEB5942493B6640072EDC0 = {
|
||||
CreatedOnToolsVersion = 11.5;
|
||||
DevelopmentTeam = S6UPZG7ZR3;
|
||||
ProvisioningStyle = Manual;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "RocketChatRN" */;
|
||||
|
@ -384,6 +441,7 @@
|
|||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* RocketChatRN */,
|
||||
1EC6ACAF22CB9FC300A41C61 /* ShareRocketChatRN */,
|
||||
1EFEB5942493B6640072EDC0 /* NotificationService */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
@ -421,6 +479,13 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
1EFEB5932493B6640072EDC0 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
|
@ -720,6 +785,14 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
1EFEB5912493B6640072EDC0 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1EFEB5982493B6640072EDC0 /* NotificationService.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
|
@ -728,6 +801,11 @@
|
|||
target = 1EC6ACAF22CB9FC300A41C61 /* ShareRocketChatRN */;
|
||||
targetProxy = 1EC6ACB922CB9FC300A41C61 /* PBXContainerItemProxy */;
|
||||
};
|
||||
1EFEB59B2493B6640072EDC0 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 1EFEB5942493B6640072EDC0 /* NotificationService */;
|
||||
targetProxy = 1EFEB59A2493B6640072EDC0 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
|
@ -978,6 +1056,68 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
1EFEB59D2493B6640072EDC0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = S6UPZG7ZR3;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = NotificationService/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.10.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.reactnative.NotificationService;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "chat.rocket.reactnative.NotificationService Development";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1EFEB59E2493B6640072EDC0 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = S6UPZG7ZR3;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = NotificationService/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 4.10.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.reactnative.NotificationService;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "chat.rocket.reactnative.NotificationService AppStore";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
@ -1101,6 +1241,15 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
1EFEB5A02493B6640072EDC0 /* Build configuration list for PBXNativeTarget "NotificationService" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1EFEB59D2493B6640072EDC0 /* Debug */,
|
||||
1EFEB59E2493B6640072EDC0 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "RocketChatRN" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1150"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "1EFEB5942493B6640072EDC0"
|
||||
BuildableName = "NotificationService.appex"
|
||||
BlueprintName = "NotificationService"
|
||||
ReferencedContainer = "container:RocketChatRN.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "RocketChatRN.app"
|
||||
BlueprintName = "RocketChatRN"
|
||||
ReferencedContainer = "container:RocketChatRN.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = ""
|
||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||
launchStyle = "0"
|
||||
askForAppToLaunch = "Yes"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<RemoteRunnable
|
||||
runnableDebuggingMode = "1"
|
||||
BundleIdentifier = "com.apple.mobileslideshow"
|
||||
RemotePath = "/Applications/MobileSlideShow.app">
|
||||
</RemoteRunnable>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "RocketChatRN.app"
|
||||
BlueprintName = "RocketChatRN"
|
||||
ReferencedContainer = "container:RocketChatRN.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "RocketChatRN.app"
|
||||
BlueprintName = "RocketChatRN"
|
||||
ReferencedContainer = "container:RocketChatRN.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -49,6 +49,7 @@ platform :ios do
|
|||
type: "appstore"
|
||||
) # more information: https://codesigning.guide
|
||||
get_provisioning_profile(app_identifier: "chat.rocket.reactnative.ShareExtension")
|
||||
get_provisioning_profile(app_identifier: "chat.rocket.reactnative.NotificationService")
|
||||
pem()
|
||||
gym(scheme: "RocketChatRN", workspace: "RocketChatRN.xcworkspace") # Build your app - more options available
|
||||
# frameit
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
"react-native-modal": "11.5.6",
|
||||
"react-native-navigation-bar-color": "2.0.1",
|
||||
"react-native-notifications": "2.1.7",
|
||||
"react-native-notifier": "^1.3.1",
|
||||
"react-native-notifier": "1.3.1",
|
||||
"react-native-orientation-locker": "1.1.8",
|
||||
"react-native-picker-select": "7.0.0",
|
||||
"react-native-platform-touchable": "^1.1.1",
|
||||
|
|
|
@ -104,6 +104,19 @@ index edc4fd4..7cd77f6 100644
|
|||
}
|
||||
|
||||
@end
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java
|
||||
index 524ff07..70f22d5 100644
|
||||
--- a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java
|
||||
+++ b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java
|
||||
@@ -31,7 +31,7 @@ public class PushNotification implements IPushNotification {
|
||||
final protected AppLifecycleFacade mAppLifecycleFacade;
|
||||
final protected AppLaunchHelper mAppLaunchHelper;
|
||||
final protected JsIOHelper mJsIOHelper;
|
||||
- final protected PushNotificationProps mNotificationProps;
|
||||
+ protected PushNotificationProps mNotificationProps;
|
||||
final protected AppVisibilityListener mAppVisibilityListener = new AppVisibilityListener() {
|
||||
@Override
|
||||
public void onAppVisible() {
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/reactNative59/java/com/wix/reactnativenotifications/NotificationManagerCompatFacade.java b/node_modules/react-native-notifications/android/app/src/reactNative59/java/com/wix/reactnativenotifications/NotificationManagerCompatFacade.java
|
||||
index f9c858b..94ea188 100644
|
||||
--- a/node_modules/react-native-notifications/android/app/src/reactNative59/java/com/wix/reactnativenotifications/NotificationManagerCompatFacade.java
|
||||
|
|
|
@ -12845,7 +12845,7 @@ react-native-notifications@2.1.7:
|
|||
core-js "^1.0.0"
|
||||
uuid "^2.0.3"
|
||||
|
||||
react-native-notifier@^1.3.1:
|
||||
react-native-notifier@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/react-native-notifier/-/react-native-notifier-1.3.1.tgz#a878c82c8ee99b04d57818401b1f084232729afd"
|
||||
integrity sha512-w7KOTF5WOYzbhCXQHz6p9tbosOVxhOW+Sh7VAdIuW6r7PSoryRNkF4P6Bzq1+2NPtMK7L6xnojCdKJ+nVnwh+A==
|
||||
|
|
Loading…
Reference in New Issue