import { useEffect } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { api, type MeResponse } from "../../shared/api/client"; /** 当前登录态。未配置后端的旧部署会 404 → 按未登录降级。 */ export function useMe() { const qc = useQueryClient(); const q = useQuery({ queryKey: ["me"], queryFn: api.me, staleTime: 60_000, retry: false, }); // Listen for popup OAuth completion signal — popup sends user data directly useEffect(() => { const handler = (e: MessageEvent) => { if (e.data?.type === "ov-oauth-complete" && e.data.user) { // Popup fetched /api/me in top-level context (cookie works there) qc.setQueryData(["me"], e.data.user as MeResponse); qc.invalidateQueries({ queryKey: ["owner-findings"] }); } else if (e.data?.type === "ov-oauth-complete") { // Fallback: no user data, try refetch qc.invalidateQueries({ queryKey: ["me"] }); } }; window.addEventListener("message", handler); return () => window.removeEventListener("message", handler); }, [qc]); // When popup is open, poll /api/me every 1.5s for up to 2 min useEffect(() => { let interval: ReturnType | null = null; let timeout: ReturnType | null = null; const startPolling = () => { if (interval) return; interval = setInterval(() => { qc.invalidateQueries({ queryKey: ["me"] }); }, 1500); timeout = setTimeout(() => { if (interval) clearInterval(interval); interval = null; }, 120_000); }; const onFocus = () => qc.invalidateQueries({ queryKey: ["me"] }); window.addEventListener("focus", onFocus); window.addEventListener("ov-oauth-popup-opened", startPolling); return () => { window.removeEventListener("focus", onFocus); window.removeEventListener("ov-oauth-popup-opened", startPolling); if (interval) clearInterval(interval); if (timeout) clearTimeout(timeout); }; }, [qc]); return q; } export function useLogout() { const qc = useQueryClient(); return useMutation({ mutationFn: api.logout, onSettled: () => { const anon: MeResponse = { authenticated: false, user: null }; qc.setQueryData(["me"], anon); // owner 视图数据全部作废 qc.invalidateQueries({ queryKey: ["owner-findings"] }); }, }); }