usePushNotifications.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // app/hooks/usePushNotifications.ts
  2. import { useEffect, useState, useRef } from 'react';
  3. import * as Notifications from 'expo-notifications';
  4. import * as Device from 'expo-device';
  5. import Constants from 'expo-constants';
  6. import { Platform } from 'react-native';
  7. import { useTranslation } from '../../util/hooks/useTranslation';
  8. export interface PushNotificationState {
  9. notification?: Notifications.Notification;
  10. expoPushToken?: Notifications.ExpoPushToken;
  11. }
  12. export const usePushNotifications = (): PushNotificationState => {
  13. const [expoPushToken, setExpoPushToken] = useState<Notifications.ExpoPushToken | undefined>();
  14. const [notification, setNotification] = useState<Notifications.Notification | undefined>();
  15. const { t } = useTranslation();
  16. const notificationListener = useRef<Notifications.Subscription | undefined>(undefined);
  17. const responseListener = useRef<Notifications.Subscription | undefined>(undefined);
  18. useEffect(() => {
  19. Notifications.setNotificationHandler({
  20. handleNotification: async () => ({
  21. shouldPlaySound: true,
  22. shouldShowAlert: true,
  23. shouldSetBadge: true,
  24. vibrate: true,
  25. shouldShowWhenInForeground: true
  26. } as any)
  27. });
  28. registerForPushNotificationAsync(t).then((token) => {
  29. setExpoPushToken(token);
  30. });
  31. notificationListener.current = Notifications.addNotificationReceivedListener((notification) => {
  32. setNotification(notification);
  33. });
  34. responseListener.current = Notifications.addNotificationResponseReceivedListener((response) => {
  35. });
  36. return () => {
  37. notificationListener.current?.remove()
  38. responseListener.current?.remove()
  39. };
  40. }, []);
  41. return {
  42. expoPushToken,
  43. notification
  44. };
  45. };
  46. async function registerForPushNotificationAsync(t: Function) {
  47. let token;
  48. // Check if the device is a physical device, because this only works for physical devices not simulators
  49. if (Device.isDevice) {
  50. const { status: existingStatus } = await Notifications.getPermissionsAsync();
  51. let finalStatus = existingStatus;
  52. if (existingStatus !== 'granted') {
  53. const { status } = await Notifications.requestPermissionsAsync();
  54. finalStatus = status;
  55. }
  56. if (finalStatus !== 'granted') {
  57. alert(t('notifications.permission_required'));
  58. return;
  59. }
  60. //if we have permission, then get the token
  61. token = await Notifications.getExpoPushTokenAsync({
  62. projectId: Constants.expoConfig?.extra?.eas?.projectId
  63. });
  64. if (Platform.OS === 'android') {
  65. Notifications.setNotificationChannelAsync('default', {
  66. name: 'default',
  67. importance: Notifications.AndroidImportance.MAX,
  68. vibrationPattern: [0, 250, 250, 250],
  69. lightColor: '#FF231F7C'
  70. });
  71. }
  72. return token;
  73. } else {
  74. }
  75. }