mirror of
https://github.com/urosran/cally.git
synced 2025-11-26 00:24:53 +00:00
Notifications
This commit is contained in:
@ -5,6 +5,11 @@ import {useRouter} from "expo-router";
|
||||
import firestore from "@react-native-firebase/firestore";
|
||||
import {UserProfile} from "@/hooks/firebase/types/profileTypes";
|
||||
|
||||
import * as Notifications from 'expo-notifications';
|
||||
import * as Device from 'expo-device';
|
||||
import Constants from 'expo-constants';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
export enum ProfileType {
|
||||
"PARENT" = "parent",
|
||||
"CHILD" = "child",
|
||||
@ -19,28 +24,89 @@ interface IAuthContext {
|
||||
refreshProfileData: () => Promise<void>
|
||||
}
|
||||
|
||||
Notifications.setNotificationHandler({
|
||||
handleNotification: async () => ({
|
||||
shouldShowAlert: true,
|
||||
shouldPlaySound: true,
|
||||
shouldSetBadge: true,
|
||||
}),
|
||||
});
|
||||
|
||||
Notifications.addNotificationReceivedListener(notification => {
|
||||
console.log('Notification received:', notification);
|
||||
});
|
||||
|
||||
async function registerForPushNotificationsAsync() {
|
||||
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') {
|
||||
alert('Failed to get push token for push notification!');
|
||||
return;
|
||||
}
|
||||
|
||||
const projectId =
|
||||
Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
|
||||
|
||||
if (!projectId) {
|
||||
alert('Project ID not found');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const token = (await Notifications.getExpoPushTokenAsync({ projectId })).data;
|
||||
console.log('Push Token:', token);
|
||||
return token;
|
||||
} catch (error) {
|
||||
alert(`Error getting push token: ${error}`);
|
||||
throw error;
|
||||
}
|
||||
} else {
|
||||
alert('Must use a physical device for push notifications');
|
||||
}
|
||||
}
|
||||
|
||||
const AuthContext = createContext<IAuthContext>(undefined!)
|
||||
|
||||
export const AuthContextProvider: FC<{ children: ReactNode }> = ({children}) => {
|
||||
const [user, setUser] = useState<FirebaseAuthTypes.User | null>(null)
|
||||
const [user, setUser] = useState<FirebaseAuthTypes.User | null>(null);
|
||||
const [initializing, setInitializing] = useState(true);
|
||||
const [profileType, setProfileType] = useState<ProfileType | undefined>(undefined);
|
||||
const [profileData, setProfileData] = useState<UserProfile | undefined>(undefined);
|
||||
|
||||
const {replace} = useRouter()
|
||||
const ready = !initializing
|
||||
const {replace} = useRouter();
|
||||
const ready = !initializing;
|
||||
|
||||
const onAuthStateChangedHandler = async (authUser: FirebaseAuthTypes.User | null) => {
|
||||
setUser(authUser);
|
||||
|
||||
if (authUser) {
|
||||
await refreshProfileData(authUser);
|
||||
const pushToken = await registerForPushNotificationsAsync();
|
||||
if (pushToken) {
|
||||
await savePushTokenToFirestore(authUser.uid, pushToken);
|
||||
}
|
||||
}
|
||||
|
||||
if (initializing) setInitializing(false);
|
||||
}
|
||||
};
|
||||
|
||||
const refreshProfileData = async (authUser: FirebaseAuthTypes.User) => {
|
||||
const refreshProfileData = async (user?: FirebaseAuthTypes.User) => {
|
||||
const authUser = user ?? auth().currentUser
|
||||
if (authUser) {
|
||||
try {
|
||||
const documentSnapshot = await firestore()
|
||||
@ -58,6 +124,16 @@ export const AuthContextProvider: FC<{ children: ReactNode }> = ({children}) =>
|
||||
}
|
||||
};
|
||||
|
||||
const savePushTokenToFirestore = async (uid: string, token: string) => {
|
||||
try {
|
||||
await firestore().collection("Profiles").doc(uid).update({
|
||||
pushToken: token,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error saving push token to Firestore:', error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const subscriber = auth().onAuthStateChanged(onAuthStateChangedHandler);
|
||||
return subscriber;
|
||||
@ -71,9 +147,9 @@ export const AuthContextProvider: FC<{ children: ReactNode }> = ({children}) =>
|
||||
|
||||
useEffect(() => {
|
||||
if (ready && user) {
|
||||
replace({pathname: "/(auth)/calendar"})
|
||||
replace({pathname: "/(auth)/calendar"});
|
||||
} else if (ready && !user) {
|
||||
replace({pathname: "/(unauth)"})
|
||||
replace({pathname: "/(unauth)"});
|
||||
}
|
||||
}, [user, ready]);
|
||||
|
||||
@ -85,7 +161,8 @@ export const AuthContextProvider: FC<{ children: ReactNode }> = ({children}) =>
|
||||
<AuthContext.Provider value={{user, profileType, profileData, setProfileData, refreshProfileData}}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export const useAuthContext = () => useContext(AuthContext)!;
|
||||
|
||||
@ -3,7 +3,7 @@ import React, { createContext, useContext, useState, ReactNode } from "react";
|
||||
|
||||
// Define the CalendarEvent interface
|
||||
export interface CalendarEvent {
|
||||
id?: number; // Unique identifier for the event
|
||||
id?: number | string; // Unique identifier for the event
|
||||
user?: string;
|
||||
title: string; // Event title or name
|
||||
description?: string; // Optional description for the event
|
||||
|
||||
Reference in New Issue
Block a user