import {useEffect, useRef, useState} from 'react'; import {useSearchParams} from 'react-router-dom'; import {useTranslation} from 'react-i18next'; import {toast} from 'sonner'; import {Skeleton} from '@/components/ui/skeleton'; import AccountInfoCard from '../components/AccountInfoCard.jsx'; import AppearanceCard from '../components/AppearanceCard.jsx'; import BuildVersionCard from '../components/BuildVersionCard.jsx'; import ChangePasswordCard from '../components/ChangePasswordCard.jsx'; import DeleteAccountCard from '../components/DeleteAccountCard.jsx'; import PreferencesCard from '../components/PreferencesCard.jsx'; import ProfileCard from '../components/ProfileCard.jsx'; import SteamAccountCard from '../components/SteamAccountCard.jsx'; import {useCurrentUserContext} from '../context/CurrentUserContext.jsx'; import {refreshSession} from '../utils/api.js'; import {markSession} from '../utils/auth.js'; // The `steam` query parameter Auth adds when "Sign in through Steam" sends the user back. const STEAM_LINK_TOASTS = { linked: {show: toast.success, key: 'SETTINGS.STEAM_LINK.LINKED'}, 'in-use': {show: toast.error, key: 'SETTINGS.STEAM_LINK.IN_USE'}, cancelled: {show: toast.info, key: 'SETTINGS.STEAM_LINK.CANCELLED'}, failed: {show: toast.error, key: 'SETTINGS.STEAM_LINK.FAILED'}, }; export default function SettingsPage() { const {t} = useTranslation(); const {user: profile, updateUser: updateProfile, reload: reloadUser} = useCurrentUserContext(); const [isLoading, setIsLoading] = useState(true); const [loadError, setLoadError] = useState(null); // From this page's own load: the context user can still be empty when the form mounts. const [displayName, setDisplayName] = useState(''); const [searchParams, setSearchParams] = useSearchParams(); // Read once: removing the parameter below must not load the profile again. const [steamOutcome] = useState(() => searchParams.get('steam')); // A language change gives a new `t` and runs the effect again; the toast shows once. const steamToastShown = useRef(false); useEffect(() => { const outcome = STEAM_LINK_TOASTS[steamOutcome]; if (!outcome || steamToastShown.current) return; steamToastShown.current = true; outcome.show(t(outcome.key)); setSearchParams((params) => { params.delete('steam'); return params; }, {replace: true}); }, [steamOutcome, setSearchParams, t]); useEffect(() => { const load = async () => { if (steamOutcome === 'linked') { // Refresh reads the new Steam ID from the database, so Core gets it in the token at once. await refreshSession().catch(() => false); markSession(); } const {ok, status, data} = await reloadUser(); if (ok) setDisplayName(data.displayName ?? ''); else if (status !== 401) setLoadError(status === 0 ? 'INFO.ERROR.NETWORK_FAILURE' : 'INFO.ERROR.LOAD_PROFILE'); setIsLoading(false); }; load(); }, [reloadUser, steamOutcome]); if (isLoading) { return (