chore: add push notif
This commit is contained in:
+11
-3
@@ -25,9 +25,8 @@
|
|||||||
"predictiveBackGestureEnabled": false,
|
"predictiveBackGestureEnabled": false,
|
||||||
"package": "com.uberstup.clientpanel",
|
"package": "com.uberstup.clientpanel",
|
||||||
"versionCode": 1,
|
"versionCode": 1,
|
||||||
"permissions": [
|
"permissions": ["android.permission.VIBRATE"],
|
||||||
"android.permission.VIBRATE"
|
"googleServicesFile": "./google-services.json"
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"web": {
|
"web": {
|
||||||
"favicon": "./assets/icon.png"
|
"favicon": "./assets/icon.png"
|
||||||
@@ -35,6 +34,15 @@
|
|||||||
"plugins": [
|
"plugins": [
|
||||||
"expo-font",
|
"expo-font",
|
||||||
"expo-router",
|
"expo-router",
|
||||||
|
[
|
||||||
|
"expo-notifications",
|
||||||
|
{
|
||||||
|
"icon": "./assets/icon.png",
|
||||||
|
"color": "#ffffff",
|
||||||
|
"androidMode": "default",
|
||||||
|
"androidCollapsedTitle": "#{unread_notifications} nouvelles notifications"
|
||||||
|
}
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"expo-build-properties",
|
"expo-build-properties",
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "607244438046",
|
||||||
|
"project_id": "frontend-client-f3354",
|
||||||
|
"storage_bucket": "frontend-client-f3354.firebasestorage.app"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:607244438046:android:ce55d750fd0f1b98ac3c0f",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.uberstup.clientpanel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyA2-og1AoVmwXXY4KTX-J-bt6E5cjiQvmM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration_version": "1"
|
||||||
|
}
|
||||||
@@ -777,6 +777,22 @@ export const getPublicSettings = async (): Promise<PublicSettings> => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const registerPushToken = async (token: string): Promise<void> => {
|
||||||
|
try {
|
||||||
|
await apiClient.post(`${V1}/push-token`, { token });
|
||||||
|
} catch {
|
||||||
|
// silencieux
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const unregisterPushToken = async (): Promise<void> => {
|
||||||
|
try {
|
||||||
|
await apiClient.delete(`${V1}/push-token`);
|
||||||
|
} catch {
|
||||||
|
// silencieux
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const calculateOrderTotal = (order: any): number => {
|
export const calculateOrderTotal = (order: any): number => {
|
||||||
if (typeof order.total === "number" && order.total > 0) return order.total;
|
if (typeof order.total === "number" && order.total > 0) return order.total;
|
||||||
if (typeof order.total_prix === "number" && order.total_prix > 0)
|
if (typeof order.total_prix === "number" && order.total_prix > 0)
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ import React, {
|
|||||||
useCallback,
|
useCallback,
|
||||||
type ReactNode,
|
type ReactNode,
|
||||||
} from "react";
|
} from "react";
|
||||||
|
import * as Notifications from "expo-notifications";
|
||||||
import { getClientNotifications, markNotificationsRead } from "../api/api";
|
import { getClientNotifications, markNotificationsRead } from "../api/api";
|
||||||
import type { ClientNotification } from "../api/api";
|
import type { ClientNotification } from "../api/api";
|
||||||
import { getToken } from "../auth/tokenStorage";
|
import { getToken } from "../auth/tokenStorage";
|
||||||
|
import { registerForPushNotifications } from "../services/pushNotifications";
|
||||||
|
|
||||||
interface ToastData {
|
interface ToastData {
|
||||||
message: string;
|
message: string;
|
||||||
@@ -128,6 +130,30 @@ export function NotificationProvider({ children }: { children: ReactNode }) {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Enregistrement push token + listeners (pattern doc Expo)
|
||||||
|
useEffect(() => {
|
||||||
|
registerForPushNotifications().catch(console.error);
|
||||||
|
|
||||||
|
const notificationListener = Notifications.addNotificationReceivedListener((notif) => {
|
||||||
|
const body = notif.request.content.body ?? "";
|
||||||
|
const data = notif.request.content.data as any;
|
||||||
|
showToast(body, getToastType(data?.type ?? ""));
|
||||||
|
fetchNotifications();
|
||||||
|
});
|
||||||
|
|
||||||
|
const responseListener = Notifications.addNotificationResponseReceivedListener((response) => {
|
||||||
|
const data = response.notification.request.content.data as any;
|
||||||
|
if (data?.command_id) {
|
||||||
|
setNavigateToOrder(data.command_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
notificationListener.remove();
|
||||||
|
responseListener.remove();
|
||||||
|
};
|
||||||
|
}, [fetchNotifications, showToast]);
|
||||||
|
|
||||||
// Polling toutes les 15 secondes
|
// Polling toutes les 15 secondes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchNotifications();
|
fetchNotifications();
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import * as Notifications from "expo-notifications";
|
||||||
|
import * as Device from "expo-device";
|
||||||
|
import Constants from "expo-constants";
|
||||||
|
import { Platform, Alert } from "react-native";
|
||||||
|
import { registerPushToken } from "../api/api";
|
||||||
|
|
||||||
|
// Comportement des notifs reçues en foreground
|
||||||
|
Notifications.setNotificationHandler({
|
||||||
|
handleNotification: async () => ({
|
||||||
|
shouldPlaySound: true,
|
||||||
|
shouldSetBadge: true,
|
||||||
|
shouldShowBanner: true,
|
||||||
|
shouldShowList: true,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleRegistrationError(errorMessage: string) {
|
||||||
|
console.error("[PUSH]", errorMessage);
|
||||||
|
Alert.alert("Push Notification Error", errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function registerForPushNotifications(): Promise<string | undefined> {
|
||||||
|
if (Platform.OS === "android") {
|
||||||
|
await Notifications.setNotificationChannelAsync("default", {
|
||||||
|
name: "default",
|
||||||
|
importance: Notifications.AndroidImportance.MAX,
|
||||||
|
vibrationPattern: [0, 250, 250, 250],
|
||||||
|
lightColor: "#FF231F7C",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Device.isDevice) {
|
||||||
|
const { status: existingStatus } = await Notifications.getPermissionsAsync();
|
||||||
|
let finalStatus = existingStatus;
|
||||||
|
if (existingStatus !== "granted") {
|
||||||
|
const { status } = await Notifications.requestPermissionsAsync();
|
||||||
|
finalStatus = status;
|
||||||
|
}
|
||||||
|
if (finalStatus !== "granted") {
|
||||||
|
handleRegistrationError("Permission not granted to get push token for push notification!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const projectId =
|
||||||
|
Constants?.expoConfig?.extra?.eas?.projectId ??
|
||||||
|
Constants?.easConfig?.projectId;
|
||||||
|
if (!projectId) {
|
||||||
|
handleRegistrationError("Project ID not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const pushTokenString = (
|
||||||
|
await Notifications.getExpoPushTokenAsync({ projectId })
|
||||||
|
).data;
|
||||||
|
console.log("[PUSH] Token obtenu:", pushTokenString);
|
||||||
|
await registerPushToken(pushTokenString);
|
||||||
|
return pushTokenString;
|
||||||
|
} catch (e: unknown) {
|
||||||
|
handleRegistrationError(`${e}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleRegistrationError("Must use physical device for push notifications");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user