diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index feb5e9c0b..fe62704a1 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -8,6 +8,8 @@
+
+
{
+ if (status === 'granted') {
+ PushNotification.configure({
+ // (optional) Called when Token is generated (iOS and Android)
+ onRegister: async function (token) {
+ console.log('TOKEN:', token);
+ alreadyConfigured = true;
+ await _setPushToken(token);
+ resolve(true);
+ },
- // (required) Called when a remote is received or opened, or local notification is opened
- onNotification: async function (notification) {
- // since we do not know whether we:
- // 1) received notification while app is in background (and storage is not decrypted so wallets are not loaded)
- // 2) opening this notification right now but storage is still unencrypted
- // 3) any of the above but the storage is decrypted, and app wallets are loaded
- //
- // ...we save notification in internal notifications queue thats gona be processed later (on unsuspend with decrypted storage)
+ // (required) Called when a remote is received or opened, or local notification is opened
+ onNotification: async function (notification) {
+ // since we do not know whether we:
+ // 1) received notification while app is in background (and storage is not decrypted so wallets are not loaded)
+ // 2) opening this notification right now but storage is still unencrypted
+ // 3) any of the above but the storage is decrypted, and app wallets are loaded
+ //
+ // ...we save notification in internal notifications queue thats gona be processed later (on unsuspend with decrypted storage)
- const payload = Object.assign({}, notification, notification.data);
- if (notification.data && notification.data.data) Object.assign(payload, notification.data.data);
- delete payload.data;
- // ^^^ weird, but sometimes payload data is not in `data` but in root level
- console.log('got push notification', payload);
+ const payload = Object.assign({}, notification, notification.data);
+ if (notification.data && notification.data.data) Object.assign(payload, notification.data.data);
+ delete payload.data;
+ // ^^^ weird, but sometimes payload data is not in `data` but in root level
+ console.log('got push notification', payload);
- await Notifications.addNotification(payload);
+ await Notifications.addNotification(payload);
- // (required) Called when a remote is received or opened, or local notification is opened
- notification.finish(PushNotificationIOS.FetchResult.NoData);
+ // (required) Called when a remote is received or opened, or local notification is opened
+ notification.finish(PushNotificationIOS.FetchResult.NoData);
- // if user is staring at the app when he receives the notification we process it instantly
- // so app refetches related wallet
- if (payload.foreground) props.onProcessNotifications();
- },
+ // if user is staring at the app when he receives the notification we process it instantly
+ // so app refetches related wallet
+ if (payload.foreground) props.onProcessNotifications();
+ },
- // (optional) Called when Registered Action is pressed and invokeApp is false, if true onNotification will be called (Android)
- onAction: function (notification) {
- console.log('ACTION:', notification.action);
- console.log('NOTIFICATION:', notification);
+ // (optional) Called when Registered Action is pressed and invokeApp is false, if true onNotification will be called (Android)
+ onAction: function (notification) {
+ console.log('ACTION:', notification.action);
+ console.log('NOTIFICATION:', notification);
- // process the action
- },
+ // process the action
+ },
- // (optional) Called when the user fails to register for remote notifications. Typically occurs when APNS is having issues, or the device is a simulator. (iOS)
- onRegistrationError: function (err) {
- console.error(err.message, err);
- resolve(false);
- },
+ // (optional) Called when the user fails to register for remote notifications. Typically occurs when APNS is having issues, or the device is a simulator. (iOS)
+ onRegistrationError: function (err) {
+ console.error(err.message, err);
+ resolve(false);
+ },
- // IOS ONLY (optional): default: all - Permissions to register.
- permissions: {
- alert: true,
- badge: true,
- sound: true,
- },
+ // IOS ONLY (optional): default: all - Permissions to register.
+ permissions: {
+ alert: true,
+ badge: true,
+ sound: true,
+ },
- // Should the initial notification be popped automatically
- // default: true
- popInitialNotification: true,
+ // Should the initial notification be popped automatically
+ // default: true
+ popInitialNotification: true,
- /**
- * (optional) default: true
- * - Specified if permissions (ios) and token (android and ios) will requested or not,
- * - if not, you must call PushNotificationsHandler.requestPermissions() later
- * - if you are not using remote notification or do not have Firebase installed, use this:
- * requestPermissions: Platform.OS === 'ios'
- */
- requestPermissions: true,
+ /**
+ * (optional) default: true
+ * - Specified if permissions (ios) and token (android and ios) will requested or not,
+ * - if not, you must call PushNotificationsHandler.requestPermissions() later
+ * - if you are not using remote notification or do not have Firebase installed, use this:
+ * requestPermissions: Platform.OS === 'ios'
+ */
+ requestPermissions: true,
+ });
+ }
});
});
+ // …
};
Notifications.cleanUserOptOutFlag = async function () {
@@ -227,8 +233,7 @@ function Notifications(props) {
if (!pushToken || !pushToken.token || !pushToken.os) return;
const api = new Frisbee({ baseURI });
-
- return await api.post(
+ const postCall = await api.post(
'/unsubscribe',
Object.assign({}, _getHeaders(), {
body: {
@@ -240,6 +245,8 @@ function Notifications(props) {
},
}),
);
+ Notifications.abandonPermissions();
+ return postCall;
};
Notifications.isNotificationsEnabled = async function () {
diff --git a/ios/BlueWallet.xcodeproj/xcuserdata/marcosrodriguez.xcuserdatad/xcschemes/xcschememanagement.plist b/ios/BlueWallet.xcodeproj/xcuserdata/marcosrodriguez.xcuserdatad/xcschemes/xcschememanagement.plist
index f35b236dc..b581aa931 100644
--- a/ios/BlueWallet.xcodeproj/xcuserdata/marcosrodriguez.xcuserdatad/xcschemes/xcschememanagement.plist
+++ b/ios/BlueWallet.xcodeproj/xcuserdata/marcosrodriguez.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -47,7 +47,7 @@
WidgetsExtension.xcscheme_^#shared#^_
orderHint
- 144
+ 99
SuppressBuildableAutocreation
diff --git a/ios/Podfile b/ios/Podfile
index 86affba85..d3632bc56 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -16,7 +16,7 @@ require_relative '../node_modules/@react-native-community/cli-platform-ios/nativ
workspace 'BlueWallet'
platform :ios, '13.0'
prepare_react_native_project!
-setup_permissions(['Camera'])
+setup_permissions(['Camera', 'Notifications'])
# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
#
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index a35833167..d7a5be25c 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -780,7 +780,7 @@ SPEC CHECKSUMS:
RNHandoff: d3b0754cca3a6bcd9b25f544f733f7f033ccf5fa
RNKeychain: a65256b6ca6ba6976132cc4124b238a5b13b3d9c
RNLocalize: dbea38dcb344bf80ff18a1757b1becf11f70cae4
- RNPermissions: eae8b97d8ab0587f082966ee608f47c97b2a349b
+ RNPermissions: e9e703e08dfe50cf4d2ca45852eb45c4ac98f7b7
RNPrivacySnapshot: 71919dde3c6a29dd332115409c2aec564afee8f4
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
RNRate: ef3bcff84f39bb1d1e41c5593d3eea4aab2bd73a
@@ -793,6 +793,6 @@ SPEC CHECKSUMS:
RNWatch: fd30ca40a5b5ef58dcbc195638e68219bc455236
Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9
-PODFILE CHECKSUM: 23bb5c319ccbedd7e109c44fe4273afce6efb48a
+PODFILE CHECKSUM: 27db07925dc3a89e9ecced7e377a50dba9deb58a
-COCOAPODS: 1.11.3
+COCOAPODS: 1.13.0
diff --git a/screen/send/create.js b/screen/send/create.js
index 9514b0aac..5175c8501 100644
--- a/screen/send/create.js
+++ b/screen/send/create.js
@@ -1,6 +1,6 @@
import React, { useCallback, useEffect } from 'react';
import PropTypes from 'prop-types';
-import { TextInput, FlatList, Linking, TouchableOpacity, StyleSheet, Text, View, Platform, PermissionsAndroid, Alert } from 'react-native';
+import { TextInput, FlatList, Linking, TouchableOpacity, StyleSheet, Text, View, Platform, Alert } from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';
import { Icon } from 'react-native-elements';
import Share from 'react-native-share';
@@ -15,6 +15,7 @@ import { DynamicQRCode } from '../../components/DynamicQRCode';
import { isDesktop } from '../../blue_modules/environment';
import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
import alert from '../../components/Alert';
+import { PERMISSIONS, RESULTS, request } from 'react-native-permissions';
const bitcoin = require('bitcoinjs-lib');
const currency = require('../../blue_modules/currency');
@@ -68,15 +69,8 @@ const SendCreate = () => {
RNFS.unlink(filePath);
});
} else if (Platform.OS === 'android') {
- const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, {
- title: loc.send.permission_storage_title,
- message: loc.send.permission_storage_message,
- buttonNeutral: loc.send.permission_storage_later,
- buttonNegative: loc._.cancel,
- buttonPositive: loc._.ok,
- });
-
- if (granted === PermissionsAndroid.RESULTS.GRANTED || Platform.Version >= 33) {
+ const granted = await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE);
+ if (granted === RESULTS.GRANTED) {
console.log('Storage Permission: Granted');
const filePath = RNFS.DownloadDirectoryPath + `/${fileName}`;
try {
diff --git a/screen/wallets/details.js b/screen/wallets/details.js
index 3ef9df003..2acc7f3c1 100644
--- a/screen/wallets/details.js
+++ b/screen/wallets/details.js
@@ -14,7 +14,6 @@ import {
StyleSheet,
StatusBar,
ScrollView,
- PermissionsAndroid,
InteractionManager,
ActivityIndicator,
I18nManager,
@@ -45,6 +44,7 @@ import { AbstractHDElectrumWallet } from '../../class/wallets/abstract-hd-electr
import alert from '../../components/Alert';
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
import { writeFileAndExport } from '../../blue_modules/fs';
+import { PERMISSIONS, RESULTS, request } from 'react-native-permissions';
const prompt = require('../../helpers/prompt');
@@ -364,15 +364,8 @@ const WalletDetails = () => {
RNFS.unlink(filePath);
});
} else if (Platform.OS === 'android') {
- const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, {
- title: loc.send.permission_storage_title,
- message: loc.send.permission_storage_message,
- buttonNeutral: loc.send.permission_storage_later,
- buttonNegative: loc._.cancel,
- buttonPositive: loc._.ok,
- });
-
- if (granted === PermissionsAndroid.RESULTS.GRANTED || Platform.Version >= 33) {
+ const granted = await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE);
+ if (granted === RESULTS.GRANTED) {
console.log('Storage Permission: Granted');
const filePath = RNFS.DownloadDirectoryPath + `/${fileName}`;
try {