ADD: Use EventEmitter on notification willPresent.

This commit is contained in:
marcosrdz 2020-12-26 05:57:42 -05:00
parent 29d9ca3bb3
commit 289b9bf28c
6 changed files with 149 additions and 22 deletions

50
App.js
View File

@ -1,6 +1,17 @@
import 'react-native-gesture-handler'; // should be on top
import React, { useContext, useEffect, useRef, useState } from 'react';
import { AppState, DeviceEventEmitter, KeyboardAvoidingView, Linking, Platform, StyleSheet, useColorScheme, View } from 'react-native';
import {
AppState,
DeviceEventEmitter,
NativeModules,
NativeEventEmitter,
KeyboardAvoidingView,
Linking,
Platform,
StyleSheet,
useColorScheme,
View,
} from 'react-native';
import { NavigationContainer, CommonActions } from '@react-navigation/native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { navigationRef } from './NavigationService';
@ -27,6 +38,8 @@ import WidgetCommunication from './blue_modules/WidgetCommunication';
import changeNavigationBarColor from 'react-native-navigation-bar-color';
const A = require('./blue_modules/analytics');
const eventEmitter = new NativeEventEmitter(NativeModules.EventEmitter);
if (process.env.NODE_ENV !== 'development') {
Sentry.init({
dsn: 'https://23377936131848ca8003448a893cb622@sentry.io/1295736',
@ -51,6 +64,26 @@ const App = () => {
},
});
const fetchWalletTransactionsInReceivedNotification = payload => {
payload = payload.aps.content;
let wallet;
switch (+payload.type) {
case 2:
case 3:
wallet = wallets.find(w => w.weOwnAddress(payload.address));
break;
case 1:
case 4:
wallet = wallets.find(w => w.weOwnTransaction(payload.txid || payload.hash));
break;
}
if (wallet) {
const walletID = wallet.getID();
fetchAndSaveWalletTransactions(walletID);
}
};
useEffect(() => {
if (walletsInitialized) {
addListeners();
@ -62,6 +95,7 @@ const App = () => {
return () => {
Linking.removeEventListener('url', handleOpenURL);
AppState.removeEventListener('change', handleAppStateChange);
eventEmitter.removeAllListeners('onNotificationReceived');
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
@ -83,6 +117,7 @@ const App = () => {
DeviceEventEmitter.addListener('quickActionShortcut', walletQuickActions);
QuickActions.popInitialAction().then(popInitialAction);
handleAppStateChange(undefined);
eventEmitter.addListener('onNotificationReceived', fetchWalletTransactionsInReceivedNotification);
};
const popInitialAction = async data => {
@ -151,9 +186,8 @@ const App = () => {
await new Promise(resolve => setTimeout(resolve, 200));
// sleep needed as sometimes unsuspend is faster than notification module actually saves notifications to async storage
const notifications2process = await Notifications.getStoredNotifications();
let returnValue = false;
for (const payload of notifications2process) {
const wasTapped = payload.foreground === false || (payload.foreground === true && payload.userInteraction);
const wasTapped = payload.foreground === false || (payload.foreground === true && payload.userInteraction === true);
console.log('processing push notification:', payload);
let wallet;
@ -184,17 +218,19 @@ const App = () => {
);
}
// no delay (1ms) as we don't need to wait for transaction propagation. 500ms is a delay to wait for the navigation
returnValue = true;
// no delay (1ms) as we dont need to wait for transaction propagation. 500ms is a delay to wait for the navigation
await Notifications.clearStoredNotifications();
return true;
} else {
console.log('could not find wallet while processing push notification tap, NOP');
}
}
await Notifications.clearStoredNotifications();
// TODO: if we are here - we did not act upon any push, so we need to iterate over _not tapped_ pushes
// and refetch appropriate wallet and redraw screen
return returnValue;
await Notifications.clearStoredNotifications();
return false;
};
const handleAppStateChange = async nextAppState => {

View File

@ -30,6 +30,7 @@
6D2AA8092568B8F40090B089 /* FiatUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2AA8072568B8F40090B089 /* FiatUnit.swift */; };
6D2AA80A2568B8F40090B089 /* FiatUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2AA8072568B8F40090B089 /* FiatUnit.swift */; };
6D2AA80B2568B8F40090B089 /* FiatUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2AA8072568B8F40090B089 /* FiatUnit.swift */; };
6D32C5C62596CE3A008C077C /* EventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D32C5C52596CE3A008C077C /* EventEmitter.m */; };
6D641F18255226DA003792DF /* MarketView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D641F17255226DA003792DF /* MarketView.swift */; };
6D641F19255226DA003792DF /* MarketView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D641F17255226DA003792DF /* MarketView.swift */; };
6D641F2325525054003792DF /* WalletInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D641F2225525053003792DF /* WalletInformationView.swift */; };
@ -313,6 +314,8 @@
6D2A6465258BA92D0092292B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6D2AA7F92568B8750090B089 /* FiatUnits.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = FiatUnits.plist; sourceTree = "<group>"; };
6D2AA8072568B8F40090B089 /* FiatUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiatUnit.swift; sourceTree = "<group>"; };
6D32C5C42596CE2F008C077C /* EventEmitter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EventEmitter.h; sourceTree = "<group>"; };
6D32C5C52596CE3A008C077C /* EventEmitter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EventEmitter.m; sourceTree = "<group>"; };
6D333B3A252FE1A3004D72DF /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
6D333B3C252FE1A3004D72DF /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
6D641F17255226DA003792DF /* MarketView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketView.swift; sourceTree = "<group>"; };
@ -523,6 +526,8 @@
32B5A3292334450100F8D608 /* Bridge.swift */,
32B5A3282334450100F8D608 /* BlueWallet-Bridging-Header.h */,
6DF25A9E249DB97E001D06F5 /* LaunchScreen.storyboard */,
6D32C5C42596CE2F008C077C /* EventEmitter.h */,
6D32C5C52596CE3A008C077C /* EventEmitter.m */,
);
name = BlueWallet;
sourceTree = "<group>";
@ -1277,12 +1282,45 @@
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-BlueWallet/Pods-BlueWallet-resources-${CONFIGURATION}-input-files.xcfilelist",
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-BlueWallet/Pods-BlueWallet-resources.sh",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-BlueWallet/Pods-BlueWallet-resources-${CONFIGURATION}-output-files.xcfilelist",
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@ -1319,6 +1357,7 @@
buildActionMask = 2147483647;
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
6D32C5C62596CE3A008C077C /* EventEmitter.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
32B5A32A2334450100F8D608 /* Bridge.swift in Sources */,
);

View File

@ -6,13 +6,13 @@
*/
#import "AppDelegate.h"
#import <React/RCTLinkingManager.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import "RNQuickActionManager.h"
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
#import "EventEmitter.h"
#ifdef FB_SONARKIT_ENABLED
#if DEBUG
#import <FlipperKit/FlipperClient.h>
@ -38,10 +38,11 @@ static void InitializeFlipper(UIApplication *application) {
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef FB_SONARKIT_ENABLED
#if DEBUG
#if !TARGET_OS_MACCATALYST
InitializeFlipper(application);
#endif
#endif
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"BlueWallet"
@ -52,7 +53,6 @@ static void InitializeFlipper(UIApplication *application) {
} else {
rootView.backgroundColor = [UIColor clearColor];
}
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
@ -61,11 +61,9 @@ static void InitializeFlipper(UIApplication *application) {
UIView* launchScreenView = [[UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil] instantiateInitialViewController].view;
launchScreenView.frame = self.window.bounds;
rootView.loadingView = launchScreenView;
// Define UNUserNotificationCenter
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
return YES;
}
@ -95,10 +93,7 @@ static void InitializeFlipper(UIApplication *application) {
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSDictionary *userInfo = notification.request.content.userInfo;
//Foreground
NSLog(@"APP_PUSH from foreground %@", userInfo);
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo
fetchCompletionHandler:^void (UIBackgroundFetchResult result){}];
[EventEmitter.sharedInstance sendNotification:userInfo];
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}

17
ios/EventEmitter.h Normal file
View File

@ -0,0 +1,17 @@
//
// EventEmitter.h
// BlueWallet
//
// Created by Marcos Rodriguez on 12/25/20.
// Copyright © 2020 BlueWallet. All rights reserved.
//
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface EventEmitter : RCTEventEmitter <RCTBridgeModule>
+ (EventEmitter *)sharedInstance;
- (void)sendNotification:(NSDictionary *)userInfo;
@end

40
ios/EventEmitter.m Normal file
View File

@ -0,0 +1,40 @@
//
// EventEmitter.m
// BlueWallet
//
// Created by Marcos Rodriguez on 12/25/20.
// Copyright © 2020 BlueWallet. All rights reserved.
//
#import "EventEmitter.h"
static EventEmitter *sharedInstance;
@implementation EventEmitter
RCT_EXPORT_MODULE();
+ (BOOL)requiresMainQueueSetup {
return YES;
}
+ (EventEmitter *)sharedInstance {
return sharedInstance;
}
- (instancetype)init {
sharedInstance = [super init];
return sharedInstance;
}
- (NSArray<NSString *> *)supportedEvents {
return @[@"onNotificationReceived"];
}
- (void)sendNotification:(NSDictionary *)userInfo
{
[sharedInstance sendEventWithName:@"onNotificationReceived" body:userInfo];
}
@end

View File

@ -754,4 +754,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: b3a4c68ed1fc7dace2357d96ad07c3e104e0afe2
COCOAPODS: 1.9.3
COCOAPODS: 1.10.0