Live video on the AT Protocol
1import { TriangleAlert } from "lucide-react-native";
2import { useEffect, useRef } from "react";
3import { Platform } from "react-native";
4import { StreamplaceAgent } from "streamplace";
5import { useToast } from "../components/ui/toast";
6import { useUrl } from "../streamplace-store/streamplace-store";
7import { checkClockDrift, syncTimeWithServer } from "./time-sync";
8
9export function useTimeSync() {
10 const url = useUrl();
11 const t = useToast();
12 const hasShownWarning = useRef(false);
13
14 useEffect(() => {
15 const checkTime = async () => {
16 if (Platform.OS !== "web") {
17 return;
18 }
19 try {
20 const agent = new StreamplaceAgent(url);
21 const start = new Date().getTime();
22 const response = await agent.place.stream.server.getServerTime();
23 const roundTripLatency = new Date().getTime() - start;
24 const serverTime = response.data.serverTime;
25
26 // always sync with server time
27 syncTimeWithServer(serverTime, roundTripLatency / 2);
28
29 const driftInfo = checkClockDrift(serverTime);
30
31 // only show warning if drift is significant
32 if (driftInfo.hasDrift && !hasShownWarning.current) {
33 hasShownWarning.current = true;
34 t.show(
35 "Clock drift detected!",
36 `Your device clock is ${driftInfo.driftSeconds}s off from server time. Please sync your system clock to avoid issues.`,
37 {
38 variant: "info",
39 iconLeft: TriangleAlert,
40 duration: 25,
41 },
42 );
43 console.log(
44 `time sync applied: offset ${driftInfo.driftMs}ms. Date() calls will now use server time.`,
45 );
46 }
47 } catch (error) {
48 console.error("failed to sync time with server:", error);
49 }
50 };
51
52 checkTime();
53
54 const interval = setInterval(checkTime, 1800000); // every 30m
55
56 return () => clearInterval(interval);
57 }, [url, t]);
58}