mirror of
https://github.com/tale/headplane.git
synced 2026-08-16 00:13:14 +00:00
fix: make useLiveData a context that is pausable
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { createContext, useContext, useEffect, useState } from 'react';
|
||||
import { useRevalidator } from 'react-router';
|
||||
import { useInterval } from 'usehooks-ts';
|
||||
|
||||
const LiveDataPausedContext = createContext({
|
||||
paused: false,
|
||||
setPaused: (_: boolean) => {},
|
||||
});
|
||||
|
||||
interface LiveDataProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function LiveDataProvider({ children }: LiveDataProps) {
|
||||
const [paused, setPaused] = useState(false);
|
||||
const revalidator = useRevalidator();
|
||||
|
||||
// Document is marked as optional here because it's not available in SSR
|
||||
// The optional chain means if document is not defined, visible is false
|
||||
const [visible, setVisible] = useState(
|
||||
() =>
|
||||
typeof document !== 'undefined' && document.visibilityState === 'visible',
|
||||
);
|
||||
|
||||
// Function to revalidate safely
|
||||
const revalidateIfIdle = () => {
|
||||
if (revalidator.state === 'idle') {
|
||||
revalidator.revalidate();
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleVisibilityChange = () => {
|
||||
setVisible(document.visibilityState === 'visible');
|
||||
if (!paused && document.visibilityState === 'visible') {
|
||||
revalidateIfIdle();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('online', revalidateIfIdle);
|
||||
document.addEventListener('focus', revalidateIfIdle);
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('online', revalidateIfIdle);
|
||||
document.removeEventListener('focus', revalidateIfIdle);
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
};
|
||||
}, [paused, revalidator]);
|
||||
|
||||
// Poll only when visible and not paused
|
||||
useInterval(revalidateIfIdle, visible && !paused ? 3000 : null);
|
||||
|
||||
return (
|
||||
<LiveDataPausedContext.Provider value={{ paused, setPaused }}>
|
||||
{children}
|
||||
</LiveDataPausedContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useLiveData() {
|
||||
const context = useContext(LiveDataPausedContext);
|
||||
return {
|
||||
pause: () => context.setPaused(true),
|
||||
resume: () => context.setPaused(false),
|
||||
};
|
||||
}
|
||||
+2
-10
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef } from 'react';
|
||||
import { useFetcher } from 'react-router';
|
||||
import { HostInfo } from '~/types';
|
||||
|
||||
export default function useAgent(nodeIds: string[], interval = 3000) {
|
||||
export default function useAgent(nodeIds: string[]) {
|
||||
const fetcher = useFetcher<Record<string, HostInfo>>();
|
||||
const qp = useMemo(
|
||||
() => new URLSearchParams({ node_ids: nodeIds.join(',') }),
|
||||
@@ -15,15 +15,7 @@ export default function useAgent(nodeIds: string[], interval = 3000) {
|
||||
fetcher.load(`/api/agent?${qp.toString()}`);
|
||||
idRef.current = nodeIds;
|
||||
}
|
||||
|
||||
const intervalID = setInterval(() => {
|
||||
fetcher.load(`/api/agent?${qp.toString()}`);
|
||||
}, interval);
|
||||
|
||||
return () => {
|
||||
clearInterval(intervalID);
|
||||
};
|
||||
}, [interval, qp]);
|
||||
}, [qp.toString()]);
|
||||
|
||||
return {
|
||||
data: fetcher.data,
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import { useRevalidator } from 'react-router';
|
||||
import { useEffect } from 'react';
|
||||
import { useInterval } from 'usehooks-ts';
|
||||
|
||||
interface Props {
|
||||
interval: number;
|
||||
}
|
||||
|
||||
export function useLiveData({ interval }: Props) {
|
||||
const revalidator = useRevalidator();
|
||||
|
||||
// Handle normal stale-while-revalidate behavior
|
||||
useInterval(() => {
|
||||
if (revalidator.state === 'idle') {
|
||||
revalidator.revalidate();
|
||||
}
|
||||
}, interval);
|
||||
|
||||
useEffect(() => {
|
||||
const handler = () => {
|
||||
if (revalidator.state === 'idle') {
|
||||
revalidator.revalidate();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('online', handler);
|
||||
document.addEventListener('focus', handler);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('online', handler);
|
||||
document.removeEventListener('focus', handler);
|
||||
};
|
||||
}, [revalidator]);
|
||||
return revalidator;
|
||||
}
|
||||
Reference in New Issue
Block a user