diff options
Diffstat (limited to 'app/src/hooks/useSocket.tsx')
-rw-r--r-- | app/src/hooks/useSocket.tsx | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/app/src/hooks/useSocket.tsx b/app/src/hooks/useSocket.tsx new file mode 100644 index 0000000..ee710b8 --- /dev/null +++ b/app/src/hooks/useSocket.tsx @@ -0,0 +1,127 @@ +"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<SocketContextType>({ + socket: null, + isConnected: false, + location: null, + startSharing: () => {}, + stopSharing: () => {}, + joinLocationView: () => {}, + updateLocation: () => {}, +}); + +export const SocketProvider = ({ children }: { children: ReactNode }) => { + const [socket, setSocket] = useState<Socket | null>(null); + const [isConnected, setIsConnected] = useState(false); + const [location, setLocation] = useState<LocationType | null>(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 ( + <SocketContext.Provider + value={{ + socket, + isConnected, + location, + startSharing, + stopSharing, + joinLocationView, + updateLocation, + }} + > + {children} + </SocketContext.Provider> + ); +}; + +export const useSocket = () => useContext(SocketContext);
\ No newline at end of file |