CI / Test & Type-Check (push) Canceled after 0s
Snapshot of in-progress module work across multiple slices: - Dealer Flow: dealerExposureEngine, dealerMapService, dealerMapExplain, dealerMapIntegrity, dealerMapReplay, dealerStudyEngine, hanStyleLevels - Mirror Portfolio (M21): fundRepository, captureIngest, mirrorAlertProducers, fund holdings strip, live book, position capture ingest - Options: BSM, NormalizedOptionSurface types, OptionsChainRouter, ConvexityGate, option legs panel - Alert producers: vixLevel, rotation, thesis, unlock, portfolioRisk, mirror (fund_capture, fund_13f, mirror_diff) - FINRA short interest adapter + queue integration - SEC company tickers adapter + ingest (symbol search index seed) - Vendor gate (rate-limit-first data plane, ADR-0009) - CUSIP registry, reverse 13F refresh, stock float service - LRU cache, portfolio backtest engine - Frontend: dealer-flow, funds, journal, lab, monitor, plan, portfolio, reports, screener, strategies, theses, guided-start, exits, more pages - Volume profile, workspace profile, visibility-aware poll - ADRs 0010 (mirror math not advice), 0011 (symbol search index) - VENDOR_INTEGRATIONS.md, END_USER_TEST.md - .gitignore: exclude DBs, .DS_Store, local config, agent scratch
57 lines
1.2 KiB
TypeScript
57 lines
1.2 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef } from "react";
|
|
|
|
/**
|
|
* Run `tick` on an interval, but pause while the document is hidden
|
|
* (background Safari tab / phone locked). Resumes with an immediate tick
|
|
* when the page becomes visible again.
|
|
*/
|
|
export function useVisibilityAwarePoll(
|
|
tick: () => void | Promise<void>,
|
|
intervalMs: number,
|
|
enabled = true,
|
|
): void {
|
|
const tickRef = useRef(tick);
|
|
tickRef.current = tick;
|
|
|
|
useEffect(() => {
|
|
if (!enabled || intervalMs <= 0) return;
|
|
|
|
let id: ReturnType<typeof setInterval> | null = null;
|
|
|
|
const run = () => {
|
|
void tickRef.current();
|
|
};
|
|
|
|
const start = () => {
|
|
if (id != null) return;
|
|
id = setInterval(run, intervalMs);
|
|
};
|
|
|
|
const stop = () => {
|
|
if (id != null) {
|
|
clearInterval(id);
|
|
id = null;
|
|
}
|
|
};
|
|
|
|
const onVisibility = () => {
|
|
if (document.hidden) {
|
|
stop();
|
|
} else {
|
|
run();
|
|
start();
|
|
}
|
|
};
|
|
|
|
if (!document.hidden) start();
|
|
|
|
document.addEventListener("visibilitychange", onVisibility);
|
|
return () => {
|
|
stop();
|
|
document.removeEventListener("visibilitychange", onVisibility);
|
|
};
|
|
}, [intervalMs, enabled]);
|
|
}
|