Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Mission control: a place to ask g1t, shown and not on yet, with the actions under it | 1 | import { useEffect } from "react"; |
| 2 | import { useNavigation, useRevalidator } from "react-router"; | |
| 3 | ||
| 4 | /** How often a page with something moving asks again. */ | |
| 5 | export const REFRESH_MS = 4000; | |
| 6 | ||
| 7 | /** | |
| Merge branch 'worktree-agent-a9934473c8cf2bca6' | 8 | * Revalidates the page `everyMs` after it last loaded while `on` and the |
| 9 | * tab is visible. Whatever refreshed it last (this, a live change, a form, | |
| 10 | * a navigation) starts the count again, so a page that also follows live | |
| 11 | * changes is not refreshed twice in a row. Out of view it waits, and asks | |
| 12 | * once when the tab comes back if the time has passed meanwhile. | |
| 13 | * | |
| Mission control: a place to ask g1t, shown and not on yet, with the actions under it | 14 | * Never while a navigation is pending: a revalidation then restarts the |
| 15 | * navigation, aborting its loaders, so a click to a page slower than the | |
| 16 | * interval would never arrive. Never on top of a revalidation still going. | |
| 17 | */ | |
| 18 | export function useRefreshWhile(on: boolean, everyMs = REFRESH_MS) { | |
| 19 | const revalidator = useRevalidator(); | |
| Merge branch 'worktree-agent-a9934473c8cf2bca6' | 20 | const idle = useNavigation().state === "idle" && revalidator.state === "idle"; |
| Mission control: a place to ask g1t, shown and not on yet, with the actions under it | 21 | useEffect(() => { |
| Merge branch 'worktree-agent-a9934473c8cf2bca6' | 22 | if (!on || !idle) return; |
| 23 | let due = false; | |
| 24 | const ask = () => { | |
| 25 | if (document.visibilityState === "visible") revalidator.revalidate(); | |
| 26 | else due = true; | |
| 27 | }; | |
| 28 | const timer = setTimeout(ask, everyMs); | |
| 29 | const back = () => { | |
| 30 | if (due && document.visibilityState === "visible") ask(); | |
| 31 | }; | |
| 32 | document.addEventListener("visibilitychange", back); | |
| 33 | return () => { | |
| 34 | clearTimeout(timer); | |
| 35 | document.removeEventListener("visibilitychange", back); | |
| 36 | }; | |
| 37 | // `revalidator` is a new object whenever its state changes, which `idle` already follows. | |
| 38 | // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 39 | }, [on, idle, everyMs]); | |
| Mission control: a place to ask g1t, shown and not on yet, with the actions under it | 40 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.