feat: disconnect collab websocket on idle tabs (#848)

* disconnect real-time collab if user is idle
* log yjs document disconnect and unload in dev mode
* no longer set editor to read-only mode on collab websocket disconnection
* treat delayed collab websocket "connecting" state as disconnected
* increase maxDebounce to 45 seconds
* add reset handle to useIdle hook
This commit is contained in:
Philip Okugbe
2025-03-08 18:16:23 +00:00
committed by GitHub
parent dd52eb15ca
commit fd36076ae7
8 changed files with 119 additions and 12 deletions

View File

@ -0,0 +1,58 @@
// Mantine Idle hook to support reset handle - MIT
//src: https://github.com/mantinedev/mantine/blob/06018d0beff22caa7b36d796e56ad597cc5c23f7/packages/%40mantine/hooks/src/use-idle/use-idle.ts
import { useEffect, useRef, useState } from "react";
const DEFAULT_EVENTS: (keyof DocumentEventMap)[] = [
"keypress",
"mousemove",
"touchmove",
"click",
"scroll",
];
const DEFAULT_OPTIONS = {
events: DEFAULT_EVENTS,
initialState: true,
};
export function useIdle(
timeout: number,
options?: Partial<{
events: (keyof DocumentEventMap)[];
initialState: boolean;
}>,
) {
const { events, initialState } = { ...DEFAULT_OPTIONS, ...options };
const [idle, setIdle] = useState<boolean>(initialState);
const timer = useRef<number>(-1);
const reset = () => {
setIdle(false);
if (timer.current) {
window.clearTimeout(timer.current);
}
timer.current = window.setTimeout(() => {
setIdle(true);
}, timeout);
};
useEffect(() => {
const handleEvents = () => {
reset();
};
events.forEach((event) => document.addEventListener(event, handleEvents));
// Start the timer immediately instead of waiting for the first event to happen
timer.current = window.setTimeout(() => {
setIdle(true);
}, timeout);
return () => {
events.forEach((event) =>
document.removeEventListener(event, handleEvents),
);
};
}, [timeout, events]);
return { isIdle: idle, resetIdle: reset };
}