Official URL migration preserves sessions, shortcuts prefs, and last clock-in client; auth screens match web with legal links; time clock and invoice editor/send flows are updated for the new domain and UI patterns. Co-authored-by: Cursor <cursoragent@cursor.com>
45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
import { useEffect } from "react";
|
|
import { AppState } from "react-native";
|
|
|
|
import {
|
|
endTimeClockLiveActivity,
|
|
syncTimeClockLiveActivity,
|
|
} from "@/lib/time-clock-live-activity";
|
|
import { api } from "@/lib/trpc";
|
|
|
|
/** Keeps the iOS Live Activity in sync while a timer runs — app-wide, not just on the Timer tab. */
|
|
export function TimeClockLiveActivitySync() {
|
|
const runningQuery = api.timeEntries.getRunning.useQuery(undefined, {
|
|
refetchInterval: 60_000,
|
|
});
|
|
const running = runningQuery.data;
|
|
|
|
useEffect(() => {
|
|
if (!running) {
|
|
void endTimeClockLiveActivity();
|
|
return;
|
|
}
|
|
|
|
const sync = () => {
|
|
const seconds = Math.floor(
|
|
(Date.now() - new Date(running.startedAt).getTime()) / 1000,
|
|
);
|
|
void syncTimeClockLiveActivity(running, seconds);
|
|
};
|
|
|
|
sync();
|
|
|
|
const interval = setInterval(sync, 60_000);
|
|
const subscription = AppState.addEventListener("change", (state) => {
|
|
if (state === "active") sync();
|
|
});
|
|
|
|
return () => {
|
|
clearInterval(interval);
|
|
subscription.remove();
|
|
};
|
|
}, [running]);
|
|
|
|
return null;
|
|
}
|