invertase / notifee

⚛️ A feature rich notifications library for React Native.
https://notifee.app
Apache License 2.0
1.88k stars 228 forks source link

[Android] Summary text is not updated in some cases #926

Closed lucasbasquerotto closed 4 months ago

lucasbasquerotto commented 12 months ago

When adding notifications in a group and displaying a summary, the text (subtitle) is updated accordingly. If you add a listener of the dismiss event and update the subtitle, it's also updated accordingly.

But when dismissing notifications to remain only 1 notification, and then adding a new notification and updating the summary text, it's not updated correctly (I think it uses a cached text). The summary notification returned by getDisplayedNotifications() has the correct subtitle in the notification prop, but for some reason it's not updated in the screen.

If you dismiss all notifications, or until at least 2 remain, this issue doesn't happen. If you add 1 more notification to that group and update the summary, it's updated correctly again.

You can use the following code as a demo (there's a snack I created for it, but it won't work in expo go as it requires notifee):

import React from 'react';
import { KeyboardAvoidingView, Platform, Pressable, SafeAreaView, ScrollView, StyleSheet, Text, View } from 'react-native';
import notifee, { AndroidGroupAlertBehavior, EventType } from '@notifee/react-native';

const groupId = '1';
const summaryId = 'summary';

const nextId = (() => {
  let id = 0;
  return () => {
    id++;
    return id;
  };
})();

const getCurrentPushNotificationsInfo = async () => {
  const displayedNotifications = await notifee.getDisplayedNotifications();

  const notifications = displayedNotifications
    ?.map((n) => ({ ...n.notification, id: n.id }));

  const allSameGroupNotifications = groupId
    ? notifications?.filter((n) => n.android?.groupId === groupId)
    : undefined;

  const sameGroupNotifications = allSameGroupNotifications
    ?.filter((n) => !n.android?.groupSummary);

  return {
    displayedNotifications,
    notifications,
    allSameGroupNotifications,
    sameGroupNotifications,
  };
};

const getSummaryText = (amount) => {
  amount = amount ?? 0;
  return amount === 1 ? '1 new message' : (amount + ' new messages');
}

const add = async () => {
  const { sameGroupNotifications } = await getCurrentPushNotificationsInfo();
  const groupAmount = (sameGroupNotifications?.length ?? 0) + 1;
  const id = nextId();

  const channelId = await notifee.createChannel({
    id: 'default',
    name: 'Default Channel',
  });

  const pressAction = { id: 'default' };

  const notification = {
    id: 'notification-' + id,
    title: 'Message #' + id,
    body: '[' + id + '] lorem ipsum dolor sit amet...',
    android: {
      channelId,
      groupId,
      groupAlertBehavior: AndroidGroupAlertBehavior.SUMMARY,
      groupSummary: false,
      pressAction,
    },
    data: {},
  };

  const summary =
    groupAmount > 1
      ? {
          id: summaryId,
          title: 'New messages',
          subtitle: getSummaryText(groupAmount),
          android: {
            channelId,
            groupId,
            groupAlertBehavior: AndroidGroupAlertBehavior.SUMMARY,
            groupSummary: true,
            pressAction,
          },
          data: {},
        }
      : undefined;

    if (summary) {
      await notifee.displayNotification(summary);
    }

    await notifee.displayNotification(notification);
}

const remove = async (notification) => {
  const { notifications, sameGroupNotifications } = await getCurrentPushNotificationsInfo();

  const groupSummary = notification?.android?.groupSummary;

  if (notification && !groupSummary) {
      const groupAmount = sameGroupNotifications?.length;
      const summary = notifications?.find((n) => n.id === summaryId);

      if (summary) {
        if (groupAmount) {
          summary.subtitle = getSummaryText(groupAmount)
          await notifee.displayNotification(summary);
        } else {
          await notifee.cancelNotification(summaryId);
        }
      }
  }
}

export default function App() {
  const handlePushEvent = React.useCallback(
    async ({ type, detail }) => {
      switch (type) {
        case EventType.DISMISSED: {
          const notification = detail.notification;

          if (notification) {
            await remove(notification);
          }

          break;
        }
        default:
          break;
      }
    },
    [],
  );

  React.useEffect(() => {
    if (notifee) {
      notifee.onBackgroundEvent(handlePushEvent);
      const unsubscribeForeground = notifee.onForegroundEvent((event) => {
        void handlePushEvent(event);
      });

      return () => {
        unsubscribeForeground();
      };
    }
  }, [handlePushEvent]);

  return (
    <SafeAreaView style={styles.outer}>
      <KeyboardAvoidingView
        behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
        style={styles.outer}
      >
        <ScrollView 
          style={styles.scroll}
          keyboardShouldPersistTaps="handled"
        >
          <View style={styles.container}>
            <Pressable
              onPress={add}
              style={styles.btn}
            >
              <Text style={styles.btnText}>Add</Text>
            </Pressable>
          </View>
        </ScrollView>
      </KeyboardAvoidingView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  outer: { flex: 1 },
  scroll: {
    flexGrow: 1,
    flexShrink: 1,
    flexBasis: 'auto',
  },
  container: {
    flex: 1,
    gap: 15,
    marginVertical: 40,
    marginHorizontal: 20,
  },
  btn: {
    borderRadius: 3,
    padding: 15,
    backgroundColor: '#92f'
  },
  btnText: {
    textAlign: 'center',
    fontSize: 16,
    fontWeight: '600',
    color: '#fff'
  },
});

You can include the above code in App.js and test it directly (if using managed expo, you need to compile an apk or generate with EAS to have notifee).

Click the Add button 3 times, which will create 3 notifications with a summary.

Dismiss 2 of the 3 notifications.

For each action, the summary was updated accordingly.

Then add a new notification. The summary text will not be updated, instead showing 1 new message (you can see with console.log(), if you want, that the notification property of the summary notification is correct with 2 new messages in the subtitle).

Adding a new notification after that updates the summary correctly.

github-actions[bot] commented 11 months ago

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

lucasbasquerotto commented 11 months ago

not stale

github-actions[bot] commented 10 months ago

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

lucasbasquerotto commented 10 months ago

not stale

github-actions[bot] commented 9 months ago

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

lucasbasquerotto commented 9 months ago

not stale

github-actions[bot] commented 8 months ago

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

lucasbasquerotto commented 8 months ago

not stale

github-actions[bot] commented 7 months ago

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

lucasbasquerotto commented 7 months ago

not stale

github-actions[bot] commented 6 months ago

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

lucasbasquerotto commented 6 months ago

not stale

github-actions[bot] commented 5 months ago

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.