From fcb2dc56364c9f26bbfe40f17600d83cf1d4d40b Mon Sep 17 00:00:00 2001 From: Murenzi Paterne Date: Sat, 20 Jul 2024 23:11:13 +0200 Subject: [PATCH] fix: device notification on notification creation --- app/(app)/ActionMenu/NotificationScreen.tsx | 47 ++-- components/UI/NotificationListing.tsx | 66 +++++- ctx/NotificationsContext.tsx | 46 +++- package-lock.json | 241 ++++++++++++++++++++ package.json | 3 +- 5 files changed, 362 insertions(+), 41 deletions(-) diff --git a/app/(app)/ActionMenu/NotificationScreen.tsx b/app/(app)/ActionMenu/NotificationScreen.tsx index 750e587..1bee84f 100644 --- a/app/(app)/ActionMenu/NotificationScreen.tsx +++ b/app/(app)/ActionMenu/NotificationScreen.tsx @@ -1,33 +1,48 @@ import React from "react"; -import { FlatList } from "react-native"; +import { FlatList, View } from "react-native"; import { ThemeContext } from "@/ctx/ThemeContext"; import { useContext } from "react"; import { useNotifications } from "@/ctx/NotificationsContext"; import NotificationListing from "@/components/UI/NotificationListing"; +import { ScrollView } from "react-native"; +import { Colors } from "@/constants/Colors"; function NotificationScreen() { const { theme, changeTheme } = useContext(ThemeContext); const { notifications } = useNotifications(); return ( - ( - - )} - /> + > + ( + + )} + keyExtractor={(item) => item.id.toString()} // Ensure each item has a unique identifier + initialNumToRender={10} + maxToRenderPerBatch={10} + windowSize={5} + /> + ); } diff --git a/components/UI/NotificationListing.tsx b/components/UI/NotificationListing.tsx index ba2c2ef..dda6a0d 100644 --- a/components/UI/NotificationListing.tsx +++ b/components/UI/NotificationListing.tsx @@ -1,5 +1,5 @@ import { View, Text } from "react-native"; -import React from "react"; +import React, { useContext } from "react"; import Typography from "@/constants/Typography"; import { Colors } from "@/constants/Colors"; import { SvgXml } from "react-native-svg"; @@ -8,6 +8,7 @@ import { calendar2 } from "@/assets/icons/calendar2"; import { service } from "@/assets/icons/service"; import { wallet } from "@/assets/icons/wallet"; import { close } from "@/assets/icons/close"; +import { ThemeContext } from "@/ctx/ThemeContext"; interface Props { title: string; @@ -20,6 +21,7 @@ interface Props { | "new_service" | "payment_setup" | "account_setup"; + viewed?: boolean; } export const icons = { @@ -85,10 +87,12 @@ export default function NotificationListing({ description, createdAt, type, + viewed, }: Props) { + const { theme } = useContext(ThemeContext); return ( <> - + @@ -111,14 +115,27 @@ export default function NotificationListing({ }} > {title} {createdAt @@ -138,15 +155,40 @@ export default function NotificationListing({ .replace(" ", "")} - - - - - {description} - + {viewed && ( + + + New + + + )} + + {description.trim()} + ); diff --git a/ctx/NotificationsContext.tsx b/ctx/NotificationsContext.tsx index 0dc39b7..db9774d 100644 --- a/ctx/NotificationsContext.tsx +++ b/ctx/NotificationsContext.tsx @@ -2,6 +2,15 @@ import { supabase } from "@/lib/supabase"; import React, { createContext, useContext, useEffect, useState } from "react"; import { useAuth } from "./AuthContext"; import { Alert } from "react-native"; +import * as Notifications from "expo-notifications"; + +Notifications.setNotificationHandler({ + handleNotification: async () => ({ + shouldShowAlert: true, + shouldPlaySound: true, + shouldSetBadge: true, + }), +}); export interface NotificationsType { notifications: NotificationType[]; @@ -62,7 +71,8 @@ export default function NotificationsProvider({ children }: Props) { const { data, error } = await supabase .from("notifications") .select("*") - .eq("patient_id", patientId); + .eq("patient_id", patientId) + .order("created_at", { ascending: false }); if (error) error; @@ -96,19 +106,31 @@ export default function NotificationsProvider({ children }: Props) { const newNotification = payload.new; if (newNotification.patient_id === patientId) { - setNotifications((prevNotifications) => [ - ...prevNotifications, - { - id: newNotification.id, - createdAt: newNotification.created_at, + Notifications.scheduleNotificationAsync({ + content: { title: newNotification.title, - description: newNotification.description, - patientId: newNotification.patient_id, - viewed: newNotification.viewed, - doctorId: newNotification.doctor_id, - type: newNotification.type, + body: newNotification.description, }, - ]); + trigger: null, + }); + + setNotifications((prevNotifications) => { + const updatedNotifications = [ + { + id: newNotification.id, + createdAt: newNotification.created_at, + title: newNotification.title, + description: newNotification.description, + patientId: newNotification.patient_id, + viewed: newNotification.viewed, + doctorId: newNotification.doctor_id, + type: newNotification.type, + }, + ...prevNotifications, + ]; + + return updatedNotifications; + }); } } ) diff --git a/package-lock.json b/package-lock.json index 46f55c0..6d79de1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,6 +50,7 @@ "expo-local-authentication": "~14.0.1", "expo-media-library": "~16.0.4", "expo-navigation-bar": "~3.0.7", + "expo-notifications": "~0.28.10", "expo-random": "~14.0.1", "expo-router": "~3.5.18", "expo-secure-store": "~13.0.2", @@ -6706,6 +6707,12 @@ "dev": true, "license": "ISC" }, + "node_modules/@ide/backoff": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@ide/backoff/-/backoff-1.0.0.tgz", + "integrity": "sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g==", + "license": "MIT" + }, "node_modules/@inquirer/figures": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.3.tgz", @@ -12571,6 +12578,19 @@ "safer-buffer": "~2.1.0" } }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, "node_modules/assert-plus": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", @@ -12580,6 +12600,19 @@ "node": ">=0.8" } }, + "node_modules/assert/node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/ast-types": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", @@ -13060,6 +13093,12 @@ "@babel/core": "^7.0.0" } }, + "node_modules/badgin": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/badgin/-/badgin-1.2.3.tgz", + "integrity": "sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw==", + "license": "MIT" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -17798,6 +17837,176 @@ "expo": "*" } }, + "node_modules/expo-notifications": { + "version": "0.28.10", + "resolved": "https://registry.npmjs.org/expo-notifications/-/expo-notifications-0.28.10.tgz", + "integrity": "sha512-DK+Edc7lQajsD7//0ivP68bCijyQV7QEk7mCaORXMltM9Ec516CrWKP1v3rRX6RvXVP1s5t6K/aEooiz6AhM+A==", + "license": "MIT", + "dependencies": { + "@expo/image-utils": "^0.5.0", + "@ide/backoff": "^1.0.0", + "abort-controller": "^3.0.0", + "assert": "^2.0.0", + "badgin": "^1.1.5", + "expo-application": "~5.9.0", + "expo-constants": "~16.0.0", + "fs-extra": "^9.1.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-notifications/node_modules/@expo/image-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.5.1.tgz", + "integrity": "sha512-U/GsFfFox88lXULmFJ9Shfl2aQGcwoKPF7fawSCLixIKtMCpsI+1r0h+5i0nQnmt9tHuzXZDL8+Dg1z6OhkI9A==", + "license": "MIT", + "dependencies": { + "@expo/spawn-async": "^1.7.2", + "chalk": "^4.0.0", + "fs-extra": "9.0.0", + "getenv": "^1.0.0", + "jimp-compact": "0.16.1", + "node-fetch": "^2.6.0", + "parse-png": "^2.1.0", + "resolve-from": "^5.0.0", + "semver": "^7.6.0", + "tempy": "0.3.0" + } + }, + "node_modules/expo-notifications/node_modules/@expo/image-utils/node_modules/fs-extra": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo-notifications/node_modules/@expo/image-utils/node_modules/universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/expo-notifications/node_modules/@expo/spawn-async": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.7.2.tgz", + "integrity": "sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/expo-notifications/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/expo-notifications/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/expo-notifications/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/expo-notifications/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/expo-notifications/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo-notifications/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/expo-notifications/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo-notifications/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/expo-random": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/expo-random/-/expo-random-14.0.1.tgz", @@ -21057,6 +21266,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -29486,6 +29711,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", diff --git a/package.json b/package.json index 0667c1e..175fdc4 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,8 @@ "start": "^5.1.0", "stream-chat-expo": "^5.33.0", "uuid": "^10.0.0", - "vector-icons": "^0.1.0" + "vector-icons": "^0.1.0", + "expo-notifications": "~0.28.10" }, "devDependencies": { "@babel/core": "^7.24.0",