react-native-push-notification / ios

React Native Push Notification API for iOS.
MIT License
732 stars 281 forks source link

IOS notifications are removed automatically when the app goes in foreground #382

Open mohammad-goldast opened 1 year ago

mohammad-goldast commented 1 year ago

When I have some notifications of my app in the Notification Center of IOS, they are removed automatically when I open my app even if I don't tap on one of them. This is incorrect behavior and this strange behavior only happens on IOS but not on Android.

Someone tells it causes because of using PushNotificationIOS.setApplicationIconBadgeNumber(0), but I don't do this in my code. It may run and be set automatically in the react-native-push-notification/ios package, IDK.

Someone fixed this problem for a flutter package by removing two lines of the code that he mentioned here.

Also, when I send 3-4 notifications to my real device through Firebase messaging panel, I see them in the Notification Center. All of them will be removed/disappear when I tap one of them and it is not the right behavior. Just that notification I tapped should be removed not all of them.


What I need and I think is correct and normal behavior:

    • When users touch the app icon, no notification should disappear from Notification Center.
    • When users touch a notification in the Notification Center, only that notification should be removed or disappear from there.

Versions: "react-native": "^0.64.0" "@react-native-community/push-notification-ios": "^1.10.1" "react-native-push-notification": "^8.1.1"

mohammad-goldast commented 1 year ago

Solution ?

ShuuNae commented 1 year ago

do you call removeAllDeliveredNotifications somewhere ?

mohammad-goldast commented 1 year ago

@ShuuNae No, I didn't use removeAllDeliveredNotifications anywhere.

import ...

class PushNotifHelper {
  constructor() {
    this.developmentMode = __DEV__;
    this.unReadNotifications = [];

    this.createNotifChannel();
  }

  setup() {
    this.developmentMode && this.subscribe('development');
    this.subscribe('all');
    this.checkPermission();
    this.getUnreadNotifications();
  }

  getUnreadNotifications() {
    PushNotification.getDeliveredNotifications((notifications) => {
      this.unReadNotifications = notifications;
    });
  }

  createNotifChannel() {
    PushNotification.createChannel({
      channelId: 'scheduled-notifications',
      channelName: 'IFSGuide Notifications',
      soundName: 'default',
      importance: Importance.HIGH,
      vibrate: true,
    });
  }

  setBadgeCount(count) {
    Platform.OS === 'ios'
      ? PushNotificationIOS.setApplicationIconBadgeNumber(count)
      : PushNotification.setApplicationIconBadgeNumber(count);
  }

  subscribe(to) {
    return new Promise((resolve, reject) => {
      messaging()
        .subscribeToTopic(to)
        .then(() => resolve('Subscribed to topic!'))
        .catch((err) => reject(err));
    });
  }

  unsubscribe(from) {
    return new Promise((resolve, reject) => {
      messaging()
        .unsubscribeFromTopic(from)
        .then(() => resolve('Unsubscribed from topic!'))
        .catch((err) => reject(err));
    });
  }

  checkPermission() {
    messaging()
      .hasPermission()
      .then((permission) => {
        analytics.setUserProfileProperty(
          stringHelper.analytics.userProperties.notifPermission,
          !!permission,
        );
        marketingHelper.setUserProfileProperty(
          stringHelper.analytics.userProperties.notifPermission,
          !!permission,
        );
      })
      .catch((err) => {
        logger(err, 'checkPermission()');
      });
  }

  requestPermission = () => messaging().requestPermission();

  hasPermission = async () => !!(await messaging().hasPermission());

  scheduleNotif(
    fireDate,
    title,
    body,
    notifId,
    extraData = {},
    hasRepeat,
    repeatsOptions,
  ) {
    return new Promise(() => {
      let options = {
        id: String(notifId),
        title: title,
        userInfo: extraData,
      };

      if (Platform.OS === 'android') {
        options = {
          ...options,
          // date: new Date(Date.now() + 5 * 1000), // in 5sc
          date: new Date(fireDate),
          message: body,
          soundName: 'default',
          number: this.unReadNotifications.length + 1,
          channelId: 'scheduled-notifications',
          bigText: body,
          largeIcon: 'ic_launcher_ifs',
          smallIcon: 'ic_launcher_ifs',
          vibration: 300,
          importance: Importance.HIGH,
          allowWhileIdle: true,
          priority: 'high',
        };
      } else {
        options = {
          ...options,
          // fireDate: new Date(Date.now() + 5 * 1000), // in 5sc
          fireDate: fireDate,
          body: body,
          badge: this.unReadNotifications.length + 1,
          category: JSON.stringify(extraData),
        };
      }

      if (hasRepeat) {
        if (Platform.OS === 'android') {
          options.repeatType = repeatsOptions.type;
          options.repeatTime = repeatsOptions.interval;
        } else {
          options.repeats = true;

          switch (repeatsOptions.type) {
            case 'day':
              options.repeatsComponent = {
                hour: true,
                minute: true,
              };

              break;

            case 'week':
              options.repeatsComponent = {
                dayOfWeek: true,
                hour: true,
                minute: true,
              };

              break;

            case 'month':
              options.repeatsComponent = {
                day: true,
                hour: true,
                minute: true,
              };

              break;
          }
        }
      }

      if (Platform.OS === 'android') {
        PushNotification.localNotificationSchedule(options);
      } else {
        PushNotificationIOS.addNotificationRequest(options);
      }
    }).catch((err) => {
      logger(err, 'scheduleNotif()');
    });
  }

  deleteNotif(notifId) {
    return new Promise((resolve, reject) => {
      const notifIdString = String(notifId);

      if (Platform.OS === 'ios') {
        PushNotificationIOS.removePendingNotificationRequests([notifIdString]);
      } else {
        PushNotification.cancelLocalNotification(notifIdString);
      }

      resolve();
    }).catch((err) => {
      logger(err, 'deleteNotif()');
    });
  }

  cancelAllLocalNotifs() {
    return new Promise((resolve, reject) => {
      if (Platform.OS === 'ios') {
        PushNotificationIOS.removeAllPendingNotificationRequests();
      } else {
        PushNotification.cancelAllLocalNotifications();
      }

      resolve();
    }).catch((err) => {
      logger(err, 'cancelAllLocalNotifs()');
    });
  }

  registerToken() {
    messaging()
      .getToken()
      .then((token) => {
        store.dispatch(userActions.userUpdateToken(token));
        this.refreshToken();
      })
      .catch((err) => {
        logger(err, 'registerToken()');
      });
  }

  refreshToken() {
    messaging().onTokenRefresh((token) => {
      store.dispatch(userActions.userUpdateToken(token));
    });
  }

  deleteToken() {
    return new Promise((resolve, reject) => {
      messaging()
        .deleteToken()
        .then(() => {
          store.dispatch(userActions.userUpdateToken('')).then(() => {
            resolve();
          });
        })
        .catch((err) => {
          logger(err, 'deleteToken()');
          resolve();
        });
    });
  }

  updateRemoteNotifData(notification) {
....
  }

  handleNotifData(notifData = undefined) {
  ....
  }

  handleNotifButtons = (actionType, actionValue, data, goBack = true) => {
...
  };
}

export const pushNotifHelper = new PushNotifHelper();
mohammad-goldast commented 1 year ago

Solution?

mohammad-goldast commented 1 year ago

Thanks for the support. :joy:

pankajkmr036 commented 1 year ago

Make sure you provide a unique id to all the notifications. That should solve your problem.