aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/hooks/useSocket.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/hooks/useSocket.tsx')
-rw-r--r--app/src/hooks/useSocket.tsx127
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