From 78f7baf07580fea48e5b6872ceb7a0d1f7cb97d7 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sat, 20 May 2023 00:19:55 +0300 Subject: [PATCH] Revalidate subscribe pages on tab back + resub --- .../routes/to.$id.brackets.tsx | 13 ++++++++++- .../routes/to.$id.matches.$mid.tsx | 19 +++++++++++---- app/features/tournament/routes/to.$id.tsx | 3 +-- app/hooks/useVisibilityChange.ts | 23 +++++++++++++++++++ 4 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 app/hooks/useVisibilityChange.ts diff --git a/app/features/tournament-bracket/routes/to.$id.brackets.tsx b/app/features/tournament-bracket/routes/to.$id.brackets.tsx index 3e1b1035a..3a527a27b 100644 --- a/app/features/tournament-bracket/routes/to.$id.brackets.tsx +++ b/app/features/tournament-bracket/routes/to.$id.brackets.tsx @@ -44,6 +44,7 @@ import { Status } from "~/db/types"; import { checkInHasStarted, teamHasCheckedIn } from "~/features/tournament"; import clsx from "clsx"; import { LinkButton } from "~/components/Button"; +import { useVisibilityChange } from "~/hooks/useVisibilityChange"; export const links: LinksFunction = () => { return [ @@ -131,6 +132,8 @@ export const loader = ({ params }: LoaderArgs) => { }; export default function TournamentBracketsPage() { + const visibility = useVisibilityChange(); + const { revalidate } = useRevalidator(); const user = useUser(); const data = useLoaderData(); const ref = React.useRef(null); @@ -212,13 +215,20 @@ export default function TournamentBracketsPage() { lessThanTwoTeamsRegistered, ]); + // TODO: also disable autorefresh (don't render component) and don't trigger revalidate after tournament is finalized + React.useEffect(() => { + if (visibility !== "visible") return; + + revalidate(); + }, [visibility, revalidate]); + const myTeam = parentRouteData.teams.find((team) => team.members.some((m) => m.userId === user?.id) ); return (
- + {visibility !== "hidden" ? : null} {!data.hasStarted && !lessThanTwoTeamsRegistered ? (
{!canAdminTournament({ user, event: parentRouteData.event }) ? ( @@ -299,6 +309,7 @@ function useAutoRefresh() { // so we revalidate loader when the match is over revalidate(); } else { + // TODO: shows 1 - "-" when updating match where other score is 0 // @ts-expect-error - brackets-viewer is not typed window.bracketsViewer.updateMatch({ id: matchId, diff --git a/app/features/tournament-bracket/routes/to.$id.matches.$mid.tsx b/app/features/tournament-bracket/routes/to.$id.matches.$mid.tsx index 3bda11256..cef3fef62 100644 --- a/app/features/tournament-bracket/routes/to.$id.matches.$mid.tsx +++ b/app/features/tournament-bracket/routes/to.$id.matches.$mid.tsx @@ -50,6 +50,7 @@ import { nanoid } from "nanoid"; import { emitter } from "../core/emitters.server"; import { useEventSource } from "remix-utils"; import * as React from "react"; +import { useVisibilityChange } from "~/hooks/useVisibilityChange"; export const links: LinksFunction = () => [ { @@ -298,20 +299,28 @@ export const loader = ({ params }: LoaderArgs) => { }; export default function TournamentMatchPage() { + const visibility = useVisibilityChange(); + const { revalidate } = useRevalidator(); const parentRouteData = useOutletContext(); const data = useLoaderData(); - const matchHasTwoTeams = Boolean( - data.match.opponentOne?.id && data.match.opponentTwo?.id - ); - const matchIsOver = data.match.opponentOne?.result === "win" || data.match.opponentTwo?.result === "win"; + const matchHasTwoTeams = Boolean( + data.match.opponentOne?.id && data.match.opponentTwo?.id + ); + + React.useEffect(() => { + if (visibility !== "visible" || matchIsOver) return; + + revalidate(); + }, [visibility, revalidate, matchIsOver]); + return (
- {!matchIsOver ? : null} + {!matchIsOver && visibility !== "hidden" ? : null}
{/* TODO: better title */}

Match #{data.match.id}

diff --git a/app/features/tournament/routes/to.$id.tsx b/app/features/tournament/routes/to.$id.tsx index 5f388d12b..bcea2bec8 100644 --- a/app/features/tournament/routes/to.$id.tsx +++ b/app/features/tournament/routes/to.$id.tsx @@ -36,9 +36,8 @@ export const shouldRevalidate: ShouldRevalidateFunction = (args) => { } const wasRevalidation = !args.formMethod; - const wasOnBracketPage = args.currentUrl.href.includes("brackets"); - if (wasRevalidation && wasOnBracketPage) { + if (wasRevalidation) { return false; } diff --git a/app/hooks/useVisibilityChange.ts b/app/hooks/useVisibilityChange.ts new file mode 100644 index 000000000..f2945e98f --- /dev/null +++ b/app/hooks/useVisibilityChange.ts @@ -0,0 +1,23 @@ +import React from "react"; + +// "initial" = user has not tabbed out yet +type Visibility = "initial" | DocumentVisibilityState; + +/** Track the `visibilitychange` event: The `visibilitychange` event is fired at the document when the contents of its tab have become visible or have been hidden. */ +export function useVisibilityChange() { + const [visible, setVisible] = React.useState("initial"); + + React.useEffect(() => { + function handleVisibilityChange() { + setVisible(document.visibilityState); + } + + document.addEventListener("visibilitychange", handleVisibilityChange); + + return () => { + document.removeEventListener("visibilitychange", handleVisibilityChange); + }; + }, []); + + return visible; +}