"use client"; import { useState, useEffect, useCallback, createContext, useContext, ReactNode } from "react"; import io, { Socket } from "socket.io-client"; import { toast } from "sonner"; interface LocationType { latitude: number; longitude: number; accuracy: number; timestamp: number; } interface SocketContextType { socket: Socket | null; isConnected: boolean; location: LocationType | null; startSharing: (token: string) => void; stopSharing: () => void; joinLocationView: (token: string) => void; updateLocation: (location: LocationType) => void; } const SocketContext = createContext({ socket: null, isConnected: false, location: null, startSharing: () => {}, stopSharing: () => {}, joinLocationView: () => {}, updateLocation: () => {}, }); export const SocketProvider = ({ children }: { children: ReactNode }) => { const [socket, setSocket] = useState(null); const [isConnected, setIsConnected] = useState(false); const [location, setLocation] = useState(null); useEffect(() => { // Initialize socket connection const socketInstance = io(process.env.NEXT_PUBLIC_SOCKET_URL || "http://localhost:3001", { transports: ["websocket"], autoConnect: true, }); socketInstance.on("connect", () => { setIsConnected(true); console.log("Connected to socket server"); }); socketInstance.on("disconnect", () => { setIsConnected(false); console.log("Disconnected from socket server"); }); socketInstance.on("location-update", (data: LocationType) => { setLocation(data); }); socketInstance.on("error", (error: string) => { toast.error(error); }); setSocket(socketInstance); return () => { socketInstance.disconnect(); }; }, []); const startSharing = useCallback((token: string) => { if (socket && isConnected) { socket.emit("start-sharing", { token }); toast.success("Started sharing your location"); } else { toast.error("Socket connection not available"); } }, [socket, isConnected]); const stopSharing = useCallback(() => { if (socket && isConnected) { socket.emit("stop-sharing"); toast.success("Stopped sharing your location"); } }, [socket, isConnected]); const joinLocationView = useCallback((token: string) => { if (socket && isConnected) { socket.emit("join-location", { token }); } else { // If socket isn't connected yet, we'll attempt to connect when it becomes available const checkInterval = setInterval(() => { if (socket && isConnected) { socket.emit("join-location", { token }); clearInterval(checkInterval); } }, 1000); // Clean up interval after 10 seconds if still not connected setTimeout(() => clearInterval(checkInterval), 10000); } }, [socket, isConnected]); const updateLocation = useCallback((locationData: LocationType) => { if (socket && isConnected) { socket.emit("update-location", locationData); } }, [socket, isConnected]); return ( {children} ); }; export const useSocket = () => useContext(SocketContext);