From 034d03e1b83afe95e3ca72c946c59301412f2409 Mon Sep 17 00:00:00 2001 From: marcosrdz Date: Mon, 28 Dec 2020 21:55:28 -0500 Subject: [PATCH 1/3] ADD: Process notifications when app state changees to foreground --- App.js | 34 ++++++++++++++++--- ...{ActionSheet.android.js => ActionSheet.js} | 0 2 files changed, 30 insertions(+), 4 deletions(-) rename screen/{ActionSheet.android.js => ActionSheet.js} (100%) diff --git a/App.js b/App.js index 66f46209a..36c246fa1 100644 --- a/App.js +++ b/App.js @@ -36,6 +36,7 @@ import WalletImport from './class/wallet-import'; import Biometric from './class/biometrics'; import WidgetCommunication from './blue_modules/WidgetCommunication'; import changeNavigationBarColor from 'react-native-navigation-bar-color'; +const PushNotification = require('react-native-push-notification'); const A = require('./blue_modules/analytics'); const eventEmitter = new NativeEventEmitter(NativeModules.EventEmitter); @@ -65,6 +66,7 @@ const App = () => { }); const fetchWalletTransactionsInReceivedNotification = notification => { + console.log('Received notification that has NOT been acted upon, fetch TXs...'); const payload = Object.assign({}, notification, notification.data); if (notification.data && notification.data.data) Object.assign(payload, notification.data.data); delete payload.data; @@ -186,6 +188,12 @@ const App = () => { ); }; + const getDeliveredNotifications = () => { + return new Promise(resolve => { + PushNotification.getDeliveredNotifications(notifications => resolve(notifications)); + }); + }; + /** * Processes push notifications stored in AsyncStorage. Might navigate to some screen. * @@ -193,11 +201,18 @@ const App = () => { * @private */ const processPushNotifications = async () => { - Notifications.setApplicationIconBadgeNumber(0); 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(); - for (const payload of notifications2process) { + /* notifications2process uses AsyncStorage and it might be empty. deliveredNotifications will + return notifications that are still in the Notification Center and have not processed. + Useful for when app comes back from background. + */ + const deliveredNotifications = await getDeliveredNotifications(); + // Set will remove duplicates. + const notificationsSet = Array.from(new Set(notifications2process.concat(deliveredNotifications))); + console.log(notificationsSet); + for (const payload of notificationsSet) { const wasTapped = payload.foreground === false || (payload.foreground === true && payload.userInteraction === true); console.log('processing push notification:', payload); @@ -227,13 +242,24 @@ const App = () => { }, }), ); + try { + PushNotification.removeDeliveredNotifications([payload.identifier]); + } catch (e) { + PushNotification.removeAllDeliveredNotifications(); + } + Notifications.setApplicationIconBadgeNumber(0); } - - // no delay (1ms) as we dont need to wait for transaction propagation. 500ms is a delay to wait for the navigation + // no delay (1ms) as we don't 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'); + try { + PushNotification.removeDeliveredNotifications([payload.identifier]); + } catch (e) { + PushNotification.removeAllDeliveredNotifications(); + Notifications.setApplicationIconBadgeNumber(0); + } } } diff --git a/screen/ActionSheet.android.js b/screen/ActionSheet.js similarity index 100% rename from screen/ActionSheet.android.js rename to screen/ActionSheet.js From 964db9f656ad63a667ccae7ea1109da61933432f Mon Sep 17 00:00:00 2001 From: marcosrdz Date: Tue, 29 Dec 2020 17:54:56 -0500 Subject: [PATCH 2/3] REF: Move calls to notification module --- App.js | 17 +++++------------ blue_modules/notifications.js | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/App.js b/App.js index 36c246fa1..964a20f2a 100644 --- a/App.js +++ b/App.js @@ -36,7 +36,6 @@ import WalletImport from './class/wallet-import'; import Biometric from './class/biometrics'; import WidgetCommunication from './blue_modules/WidgetCommunication'; import changeNavigationBarColor from 'react-native-navigation-bar-color'; -const PushNotification = require('react-native-push-notification'); const A = require('./blue_modules/analytics'); const eventEmitter = new NativeEventEmitter(NativeModules.EventEmitter); @@ -188,12 +187,6 @@ const App = () => { ); }; - const getDeliveredNotifications = () => { - return new Promise(resolve => { - PushNotification.getDeliveredNotifications(notifications => resolve(notifications)); - }); - }; - /** * Processes push notifications stored in AsyncStorage. Might navigate to some screen. * @@ -208,7 +201,7 @@ const App = () => { return notifications that are still in the Notification Center and have not processed. Useful for when app comes back from background. */ - const deliveredNotifications = await getDeliveredNotifications(); + const deliveredNotifications = await Notifications.getDeliveredNotifications(); // Set will remove duplicates. const notificationsSet = Array.from(new Set(notifications2process.concat(deliveredNotifications))); console.log(notificationsSet); @@ -243,9 +236,9 @@ const App = () => { }), ); try { - PushNotification.removeDeliveredNotifications([payload.identifier]); + Notifications.removeDeliveredNotifications([payload.identifier]); } catch (e) { - PushNotification.removeAllDeliveredNotifications(); + Notifications.removeAllDeliveredNotifications(); } Notifications.setApplicationIconBadgeNumber(0); } @@ -255,9 +248,9 @@ const App = () => { } else { console.log('could not find wallet while processing push notification tap, NOP'); try { - PushNotification.removeDeliveredNotifications([payload.identifier]); + Notifications.removeDeliveredNotifications([payload.identifier]); } catch (e) { - PushNotification.removeAllDeliveredNotifications(); + Notifications.removeAllDeliveredNotifications(); Notifications.setApplicationIconBadgeNumber(0); } } diff --git a/blue_modules/notifications.js b/blue_modules/notifications.js index 250f2b2e2..e61db05b2 100644 --- a/blue_modules/notifications.js +++ b/blue_modules/notifications.js @@ -387,10 +387,24 @@ function Notifications(props) { } catch (_) {} }; + Notifications.getDeliveredNotifications = () => { + return new Promise(resolve => { + PushNotification.getDeliveredNotifications(notifications => resolve(notifications)); + }); + }; + + Notifications.removeDeliveredNotifications = (identifiers = []) => { + PushNotification.removeDeliveredNotifications(identifiers); + }; + Notifications.setApplicationIconBadgeNumber = function (badges) { PushNotification.setApplicationIconBadgeNumber(badges); }; + Notifications.removeAllDeliveredNotifications = () => { + PushNotification.removeAllDeliveredNotifications(); + }; + // on app launch (load module): (async () => { // first, fetching to see if app uses custom GroundControl server, not the default one From 34ac5da03ba5e2080c635618f2200fe2834be4a7 Mon Sep 17 00:00:00 2001 From: marcosrdz Date: Tue, 29 Dec 2020 21:13:56 -0500 Subject: [PATCH 3/3] Update App.js --- App.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/App.js b/App.js index 964a20f2a..9e266a212 100644 --- a/App.js +++ b/App.js @@ -52,7 +52,9 @@ const ClipboardContentType = Object.freeze({ }); const App = () => { - const { walletsInitialized, wallets, addWallet, saveToDisk, fetchAndSaveWalletTransactions } = useContext(BlueStorageContext); + const { walletsInitialized, wallets, addWallet, saveToDisk, fetchAndSaveWalletTransactions, refreshAllWalletTransactions } = useContext( + BlueStorageContext, + ); const appState = useRef(AppState.currentState); const [isClipboardContentModalVisible, setIsClipboardContentModalVisible] = useState(false); const [clipboardContentType, setClipboardContentType] = useState(); @@ -259,6 +261,10 @@ const App = () => { // 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 + if (notificationsSet.length > 0) { + // notification object is missing userInfo. We know we received a notification but don't have sufficient data to refresh 1 wallet. let's refresh all. + refreshAllWalletTransactions(); + } await Notifications.clearStoredNotifications(); return false; };