mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-26 08:55:56 +01:00
wip
This commit is contained in:
parent
ae15a4a77f
commit
28e325afa5
4 changed files with 102 additions and 20 deletions
blue_modules
components
loc
screen/settings
|
@ -1,8 +1,8 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import PushNotificationIOS from '@react-native-community/push-notification-ios';
|
||||
import { findNodeHandle, Platform } from 'react-native';
|
||||
import { AppState, findNodeHandle, Platform } from 'react-native';
|
||||
import { getApplicationName, getSystemName, getSystemVersion, getVersion, hasGmsSync, hasHmsSync } from 'react-native-device-info';
|
||||
import { requestNotifications } from 'react-native-permissions';
|
||||
import { checkNotifications, requestNotifications } from 'react-native-permissions';
|
||||
import PushNotification from 'react-native-push-notification';
|
||||
|
||||
import loc from '../loc';
|
||||
|
@ -16,6 +16,37 @@ const NOTIFICATIONS_NO_AND_DONT_ASK_FLAG = 'NOTIFICATIONS_NO_AND_DONT_ASK_FLAG';
|
|||
let alreadyConfigured = false;
|
||||
let baseURI = groundControlUri;
|
||||
|
||||
// Function to check notification permission status at the system level
|
||||
export const checkNotificationPermissionStatus = async () => {
|
||||
try {
|
||||
const { status } = await checkNotifications();
|
||||
return status;
|
||||
} catch (error) {
|
||||
console.error('Failed to check notification permissions:', error);
|
||||
return 'unavailable'; // Return 'unavailable' if the status cannot be retrieved
|
||||
}
|
||||
};
|
||||
|
||||
// Listener to monitor notification permission status changes while app is running
|
||||
let currentPermissionStatus = 'unavailable';
|
||||
const handleAppStateChange = async nextAppState => {
|
||||
if (nextAppState === 'active') {
|
||||
const newPermissionStatus = await checkNotificationPermissionStatus();
|
||||
if (newPermissionStatus !== currentPermissionStatus) {
|
||||
currentPermissionStatus = newPermissionStatus;
|
||||
if (newPermissionStatus === 'granted') {
|
||||
// Re-initialize notifications if permissions are granted
|
||||
await initializeNotifications();
|
||||
} else {
|
||||
// Optionally, handle the case where permissions are revoked (e.g., disable in-app notifications)
|
||||
console.warn('Notifications have been disabled at the system level.');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AppState.addEventListener('change', handleAppStateChange);
|
||||
|
||||
export const cleanUserOptOutFlag = async () => {
|
||||
return AsyncStorage.removeItem(NOTIFICATIONS_NO_AND_DONT_ASK_FLAG);
|
||||
};
|
||||
|
@ -265,7 +296,7 @@ export const configureNotifications = async onProcessNotifications => {
|
|||
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.debug('got push notification', payload);
|
||||
console.debug('Received Push Notification Payload: ', payload);
|
||||
|
||||
await addNotification(payload);
|
||||
|
||||
|
@ -311,7 +342,7 @@ export const configureNotifications = async onProcessNotifications => {
|
|||
* - if you are not using remote notification or do not have Firebase installed, use this:
|
||||
* requestPermissions: Platform.OS === 'ios'
|
||||
*/
|
||||
requestPermissions: true,
|
||||
requestPermissions: Platform.OS === 'ios',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -520,7 +551,6 @@ export const getStoredNotifications = async () => {
|
|||
|
||||
// on app launch (load module):
|
||||
export const initializeNotifications = async onProcessNotifications => {
|
||||
// Fetch custom GroundControl URI
|
||||
try {
|
||||
const baseUriStored = await AsyncStorage.getItem(GROUNDCONTROL_BASE_URI);
|
||||
baseURI = baseUriStored || groundControlUri;
|
||||
|
@ -530,13 +560,15 @@ export const initializeNotifications = async onProcessNotifications => {
|
|||
await AsyncStorage.setItem(GROUNDCONTROL_BASE_URI, groundControlUri).catch(err => console.error('Failed to reset URI:', err));
|
||||
}
|
||||
|
||||
// Set the application icon badge to 0
|
||||
setApplicationIconBadgeNumber(0);
|
||||
|
||||
try {
|
||||
if (await getPushToken()) {
|
||||
currentPermissionStatus = await checkNotificationPermissionStatus();
|
||||
if (currentPermissionStatus === 'granted' && (await getPushToken())) {
|
||||
await configureNotifications(onProcessNotifications);
|
||||
await postTokenConfig();
|
||||
} else {
|
||||
console.warn('Notifications are disabled at the system level.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize notifications:', error);
|
||||
|
|
|
@ -57,7 +57,7 @@ const CompanionDelegates = () => {
|
|||
const deliveredNotifications = await getDeliveredNotifications();
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
await removeAllDeliveredNotifications();
|
||||
removeAllDeliveredNotifications();
|
||||
} catch (error) {
|
||||
console.error('Failed to remove delivered notifications:', error);
|
||||
}
|
||||
|
|
|
@ -320,7 +320,8 @@
|
|||
"would_you_like_to_receive_notifications": "Would you like to receive notifications when you get incoming payments?",
|
||||
"notifications_subtitle": "Incoming payments and transaction confirmations",
|
||||
"no_and_dont_ask": "No, and do not ask me again.",
|
||||
"ask_me_later": "Ask me later."
|
||||
"ask_me_later": "Ask me later.",
|
||||
"permission_denied_message": "You have denied permission to send you notifications. If you would like to receive notifications, please enable them in your device settings."
|
||||
},
|
||||
"transactions": {
|
||||
"cancel_explain": "We will replace this transaction with one that pays you and has higher fees. This effectively cancels the current transaction. This is called RBF—Replace by Fee.",
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { I18nManager, Linking, ScrollView, StyleSheet, TextInput, View, Pressable } from 'react-native';
|
||||
import { I18nManager, Linking, ScrollView, StyleSheet, TextInput, View, Pressable, AppState } from 'react-native';
|
||||
import { Button as ButtonRNElements } from '@rneui/themed';
|
||||
// @ts-ignore: no declaration file
|
||||
import {
|
||||
getDefaultUri,
|
||||
getPushToken,
|
||||
|
@ -14,6 +13,7 @@ import {
|
|||
cleanUserOptOutFlag,
|
||||
isGroundControlUriValid,
|
||||
checkPermissions,
|
||||
checkNotificationPermissionStatus,
|
||||
} from '../../blue_modules/notifications';
|
||||
import { BlueCard, BlueSpacing20, BlueSpacing40, BlueText } from '../../BlueComponents';
|
||||
import presentAlert from '../../components/Alert';
|
||||
|
@ -53,21 +53,51 @@ const NotificationSettings: React.FC = () => {
|
|||
setTapCount(prevCount => prevCount + 1);
|
||||
};
|
||||
|
||||
const showNotificationPermissionAlert = () => {
|
||||
presentAlert({
|
||||
title: loc.settings.notifications,
|
||||
message: loc.notifications.permission_denied_message,
|
||||
buttons: [
|
||||
{
|
||||
text: loc._.ok,
|
||||
style: 'cancel',
|
||||
},
|
||||
{
|
||||
text: loc.settings.header,
|
||||
onPress: onSystemSettings,
|
||||
style: 'default',
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
const onNotificationsSwitch = async (value: boolean) => {
|
||||
if (value) {
|
||||
// User is trying to enable notifications
|
||||
const currentStatus = await checkNotificationPermissionStatus();
|
||||
if (currentStatus !== 'granted') {
|
||||
// If notifications are not granted at the system level, show an alert and prevent toggle from enabling
|
||||
showNotificationPermissionAlert();
|
||||
setNotificationsEnabledState(false); // Keep the switch off
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
setNotificationsEnabledState(value);
|
||||
if (value) {
|
||||
// User is enabling notifications
|
||||
await cleanUserOptOutFlag();
|
||||
if (await getPushToken()) {
|
||||
// we already have a token, so we just need to reenable ALL level on groundcontrol:
|
||||
await setLevels(true);
|
||||
const permissionsGranted = await tryToObtainPermissions();
|
||||
if (permissionsGranted) {
|
||||
if (await getPushToken()) {
|
||||
await setLevels(true);
|
||||
}
|
||||
} else {
|
||||
// ok, we dont have a token. we need to try to obtain permissions, configure callbacks and save token locally:
|
||||
await tryToObtainPermissions();
|
||||
// If permissions are denied, show alert and reset the toggle
|
||||
showNotificationPermissionAlert();
|
||||
setNotificationsEnabledState(false); // Reset the toggle to reflect the denied status
|
||||
}
|
||||
} else {
|
||||
// User is disabling notifications
|
||||
await setLevels(false);
|
||||
}
|
||||
|
||||
|
@ -78,12 +108,21 @@ const NotificationSettings: React.FC = () => {
|
|||
}
|
||||
};
|
||||
|
||||
// Function to check and update notification permission status
|
||||
const updateNotificationStatus = async () => {
|
||||
const currentStatus = await checkNotificationPermissionStatus();
|
||||
if (currentStatus !== 'granted') {
|
||||
setNotificationsEnabledState(false); // Automatically toggle switch off if permissions are disabled
|
||||
} else {
|
||||
setNotificationsEnabledState(true);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
setNotificationsEnabledState(await isNotificationsEnabled());
|
||||
setURI((await getSavedUri()) ?? getDefaultUri());
|
||||
// @ts-ignore: refactor later
|
||||
setTokenInfo(
|
||||
'token: ' +
|
||||
JSON.stringify(await getPushToken()) +
|
||||
|
@ -99,13 +138,23 @@ const NotificationSettings: React.FC = () => {
|
|||
setIsLoading(false);
|
||||
}
|
||||
})();
|
||||
|
||||
// Add AppState listener to check permission status when app is active
|
||||
const appStateListener = AppState.addEventListener('change', nextAppState => {
|
||||
if (nextAppState === 'active') {
|
||||
updateNotificationStatus();
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
appStateListener.remove();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const save = useCallback(async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
if (URI) {
|
||||
// validating only if its not empty. empty means use default
|
||||
if (await isGroundControlUriValid(URI)) {
|
||||
await saveUri(URI);
|
||||
presentAlert({ message: loc.settings.saved });
|
||||
|
|
Loading…
Add table
Reference in a new issue