Live video on the AT Protocol
79
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v0.9.9 112 lines 3.0 kB view raw
1import { Platform } from "react-native"; 2 3let timeOffset = 0; 4let hasWarned = false; 5let OriginalDate: DateConstructor = Date; 6 7const CLOCK_DRIFT_THRESHOLD_MS = 5000; // 5 seconds 8 9export function getTimeOffset(): number { 10 return timeOffset; 11} 12 13export function setTimeOffset(offset: number): void { 14 timeOffset = offset; 15} 16 17export function checkClockDrift(serverTime: string): { 18 hasDrift: boolean; 19 driftMs: number; 20 driftSeconds: number; 21} { 22 const serverDate = new Date(serverTime); 23 const clientDate = new Date(); 24 const drift = Math.abs(serverDate.getTime() - clientDate.getTime()); 25 26 if (drift > CLOCK_DRIFT_THRESHOLD_MS) { 27 const driftSeconds = Math.round(drift / 1000); 28 if (!hasWarned) { 29 hasWarned = true; 30 console.warn( 31 `clock drift detected: ${driftSeconds}s difference from server time. ` + 32 `this may cause issues with time-sensitive operations. ` + 33 `please sync your system clock.`, 34 ); 35 } 36 return { hasDrift: true, driftMs: drift, driftSeconds }; 37 } else { 38 return { 39 hasDrift: false, 40 driftMs: drift, 41 driftSeconds: Math.round(drift / 1000), 42 }; 43 } 44} 45 46export function syncTimeWithServer( 47 serverTime: string, 48 networkLatencyMs: number, 49): void { 50 const serverDate = new OriginalDate(serverTime); 51 const clientDate = new OriginalDate(); 52 const offset = serverDate.getTime() - clientDate.getTime() - networkLatencyMs; 53 54 setTimeOffset(offset); 55} 56 57export function getSyncedDate(): Date { 58 const now = new Date(); 59 if (timeOffset !== 0) { 60 return new Date(now.getTime() + timeOffset); 61 } 62 return now; 63} 64 65export function getSystemDate(): Date { 66 return new OriginalDate(); 67} 68 69export function getSystemTime(): number { 70 return OriginalDate.now(); 71} 72 73export function initializeTimeSync(): void { 74 if (Platform.OS !== "web") { 75 return; 76 } 77 78 // store original Date 79 OriginalDate = Date; 80 const OriginalDatePrototype = OriginalDate.prototype; 81 82 // create patched Date constructor 83 function PatchedDate(this: any, ...args: any[]): any { 84 // If called as a function (no `new`), forward to original Date to get the string form 85 if (!(this instanceof PatchedDate)) { 86 return OriginalDate.apply(undefined, args as any); 87 } 88 89 // If called as a constructor, construct a Date with synced time when no args provided 90 if (args.length === 0) { 91 const syncedTime = OriginalDate.now() + timeOffset; 92 return Reflect.construct(OriginalDate, [syncedTime], PatchedDate); 93 } 94 95 // Otherwise construct with the provided arguments 96 return Reflect.construct(OriginalDate, args, PatchedDate); 97 } 98 99 // copy static methods 100 PatchedDate.now = function (): number { 101 return OriginalDate.now() + timeOffset; 102 }; 103 104 PatchedDate.parse = OriginalDate.parse; 105 PatchedDate.UTC = OriginalDate.UTC; 106 107 // copy prototype 108 PatchedDate.prototype = OriginalDatePrototype; 109 110 // replace global Date 111 (globalThis as any).Date = PatchedDate; 112}