1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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);
|