From 26f65182700f6b5d3c5f7eb1ddf457355611ec60 Mon Sep 17 00:00:00 2001 From: Arnaud Vergnet Date: Sat, 17 Jul 2021 09:57:26 +0200 Subject: [PATCH] Fix proxiwash notifications --- App.tsx | 5 +- src/utils/Notifications.ts | 131 ++++++++++++++++++++++++++----------- 2 files changed, 96 insertions(+), 40 deletions(-) diff --git a/App.tsx b/App.tsx index bcea3ee..da8a0da 100644 --- a/App.tsx +++ b/App.tsx @@ -49,11 +49,15 @@ import { import MainApp from './src/screens/MainApp'; import LoginProvider from './src/components/providers/LoginProvider'; import { retrieveLoginToken } from './src/utils/loginToken'; +import { setupNotifications } from './src/utils/Notifications'; // Native optimizations https://reactnavigation.org/docs/react-native-screens // Crashes app when navigating away from webview on android 9+ // enableScreens(true); +initLocales(); +setupNotifications(); + LogBox.ignoreLogs([ // collapsible headers cause this warning, just ignore as it is not an issue 'Non-serializable values were found in the navigation state', @@ -92,7 +96,6 @@ export default class App extends React.Component<{}, StateType> { }, loginToken: undefined, }; - initLocales(); this.navigatorRef = React.createRef(); this.defaultHomeRoute = undefined; this.defaultHomeData = undefined; diff --git a/src/utils/Notifications.ts b/src/utils/Notifications.ts index 3ef0f26..ac99e65 100644 --- a/src/utils/Notifications.ts +++ b/src/utils/Notifications.ts @@ -19,56 +19,107 @@ import i18n from 'i18n-js'; import PushNotificationIOS from '@react-native-community/push-notification-ios'; -import PushNotification from 'react-native-push-notification'; +import PushNotification, { + Importance, + PushNotificationObject, +} from 'react-native-push-notification'; import { Platform } from 'react-native'; +import Update from '../constants/Update'; // Used to multiply the normal notification id to create the reminder one. It allows to find it back easily const reminderIdFactor = 100; +// Allows the channel to be updated when the app updates +const channelId = 'reminders' + Update.number; -PushNotification.createChannel( - { - channelId: 'reminders', // (required) - channelName: 'Reminders', // (required) - channelDescription: 'Get laundry reminders', // (optional) default: undefined. - playSound: true, // (optional) default: true - soundName: 'default', // (optional) See `soundName` parameter of `localNotification` function - importance: 4, // (optional) default: 4. Int value of the Android notification importance - vibrate: true, // (optional) default: true. Creates the default vibration patten if true. - }, - (created) => console.log(`createChannel returned '${created}'`) // (optional) callback returns whether the channel was created, false means it already existed. -); +/** + * Clean channels before creating a new one + */ +function cleanChannels() { + PushNotification.getChannels((idList) => { + idList.forEach((i) => { + if (i !== channelId) { + PushNotification.deleteChannel(i); + } + }); + }); +} -PushNotification.configure({ - // (required) Called when a remote is received or opened, or local notification is opened - onNotification: function (notification) { - console.log('NOTIFICATION:', notification); - - // process the notification +export function setupNotifications() { + cleanChannels(); + PushNotification.channelExists(channelId, (exists) => { + if (!exists) { + PushNotification.createChannel( + { + channelId: channelId, // (required) + channelName: i18n.t('screens.proxiwash.notifications.channel.title'), // (required) + channelDescription: i18n.t( + 'screens.proxiwash.notifications.channel.description' + ), // (optional) default: undefined. + playSound: true, // (optional) default: true + soundName: 'default', // (optional) See `soundName` parameter of `localNotification` function + importance: Importance.HIGH, // (optional) default: Importance.HIGH. Int value of the Android notification importance + vibrate: true, // (optional) default: true. Creates the default vibration patten if true. + }, + (created) => console.log(`createChannel returned '${created}'`) // (optional) callback returns whether the channel was created, false means it already existed. + ); + } + }); + PushNotification.configure({ // (required) Called when a remote is received or opened, or local notification is opened - notification.finish(PushNotificationIOS.FetchResult.NoData); - }, + onNotification: function (notification) { + console.log('NOTIFICATION:', notification); - // IOS ONLY (optional): default: all - Permissions to register. - permissions: { - alert: true, - badge: true, - sound: true, - }, + // process the notification - // Should the initial notification be popped automatically - // default: true - popInitialNotification: true, + // (required) Called when a remote is received or opened, or local notification is opened + notification.finish(PushNotificationIOS.FetchResult.NoData); + }, - /** - * (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: Platform.OS === 'ios', -}); + // 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, + + /** + * (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: Platform.OS === 'ios', + }); +} + +const DEFAULT_NOTIFICATIONS_OPTIONS: Partial = { + /* Android Only Properties */ + channelId: channelId, // (required) channelId, if the channel doesn't exist, notification will not trigger. + showWhen: true, // (optional) default: true + autoCancel: true, // (optional) default: true + vibrate: true, // (optional) default: true + vibration: 300, // vibration length in milliseconds, ignored if vibrate=false, default: 1000 + priority: 'high', // (optional) set notification priority, default: high + visibility: 'public', // (optional) set notification visibility, default: private + ignoreInForeground: false, // (optional) if true, the notification will not be visible when the app is in the foreground (useful for parity with how iOS notifications appear). should be used in combine with `com.dieam.reactnativepushnotification.notification_foreground` setting + onlyAlertOnce: false, // (optional) alert will open only once with sound and notify, default: false + + when: null, // (optional) Add a timestamp (Unix timestamp value in milliseconds) pertaining to the notification (usually the time the event occurred). For apps targeting Build.VERSION_CODES.N and above, this time is not shown anymore by default and must be opted into by using `showWhen`, default: null. + usesChronometer: false, // (optional) Show the `when` field as a stopwatch. Instead of presenting `when` as a timestamp, the notification will show an automatically updating display of the minutes and seconds since when. Useful when showing an elapsed time (like an ongoing phone call), default: false. + timeoutAfter: null, // (optional) Specifies a duration in milliseconds after which this notification should be canceled, if it is not already canceled, default: null + + invokeApp: true, // (optional) This enable click on actions to bring back the application to foreground or stay in background, default: true + + /* iOS and Android properties */ + playSound: true, // (optional) default: true + soundName: 'default', // (optional) Sound to play when the notification is shown. Value of 'default' plays the default sound. It can be set to a custom sound such as 'android.resource://com.xyz/raw/my_sound'. It will look for the 'my_sound' audio file in 'res/raw' directory and play it. default: 'default' (default sound is played) +}; /** * Creates a notification for the given machine id at the given date. @@ -84,6 +135,7 @@ function createNotifications(machineID: string, date: Date, reminder?: number) { const reminderDate = new Date(date); reminderDate.setMinutes(reminderDate.getMinutes() - reminder); PushNotification.localNotificationSchedule({ + ...DEFAULT_NOTIFICATIONS_OPTIONS, title: i18n.t('screens.proxiwash.notifications.machineRunningTitle', { time: reminder, }), @@ -96,6 +148,7 @@ function createNotifications(machineID: string, date: Date, reminder?: number) { } PushNotification.localNotificationSchedule({ + ...DEFAULT_NOTIFICATIONS_OPTIONS, title: i18n.t('screens.proxiwash.notifications.machineFinishedTitle'), message: i18n.t('screens.proxiwash.notifications.machineFinishedBody', { number: machineID,