feat(player): improve wallet activity and session handling
Some checks failed
lotteryfront CI / build (push) Has been cancelled

This commit is contained in:
wchino
2026-07-22 20:53:43 +08:00
parent 508b28df22
commit 827f369eb6
40 changed files with 925 additions and 349 deletions

View File

@@ -2,8 +2,8 @@
import { useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { useI18nHydrated } from "@/components/i18n-hydration-provider";
import { useHydrationSafeEntryT } from "@/i18n/hydration-t";
import { toast } from "sonner";
@@ -32,7 +32,7 @@ function stripSearchParamFromBrowserUrl(name: string): void {
}
export function PlayerLoginScreen(): React.ReactElement {
const { t: tErrors } = useTranslation("entry");
const i18nHydrated = useI18nHydrated();
const t = useHydrationSafeEntryT();
const tRef = useRef(t);
useEffect(() => {
@@ -43,8 +43,9 @@ export function PlayerLoginScreen(): React.ReactElement {
const setBearerToken = usePlayerSessionStore((s) => s.setBearerToken);
const setProfile = usePlayerSessionStore((s) => s.setProfile);
const clearBearerToken = usePlayerSessionStore((s) => s.clearBearerToken);
const sessionExpiredHandled = useRef(false);
const sessionStatusHandled = useRef(false);
const passwordChangedHandled = useRef(false);
const captchaInitialized = useRef(false);
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
@@ -71,29 +72,28 @@ export function PlayerLoginScreen(): React.ReactElement {
}, []);
useEffect(() => {
let cancelled = false;
void (async () => {
if (cancelled) {
return;
}
await loadCaptcha();
})();
return () => {
cancelled = true;
};
if (captchaInitialized.current) return;
captchaInitialized.current = true;
void loadCaptcha();
}, [loadCaptcha]);
useEffect(() => {
if (sessionExpiredHandled.current) return;
if (searchParams.get("session") !== "expired") return;
if (!i18nHydrated) return;
if (sessionStatusHandled.current) return;
const sessionStatus = searchParams.get("session");
if (sessionStatus !== "expired" && sessionStatus !== "replaced") return;
sessionExpiredHandled.current = true;
sessionStatusHandled.current = true;
clearBearerToken();
toast.error(tErrors("errors.sessionExpired"));
toast.error(
t(
sessionStatus === "replaced"
? "errors.sessionReplaced"
: "errors.sessionExpired",
),
);
stripSearchParamFromBrowserUrl("session");
}, [clearBearerToken, searchParams, tErrors]);
}, [clearBearerToken, i18nHydrated, searchParams, t]);
useEffect(() => {
if (passwordChangedHandled.current) return;
@@ -118,7 +118,7 @@ export function PlayerLoginScreen(): React.ReactElement {
}
if (!captchaCode.trim()) {
toast.error(t("login.captchaRequired"));
toast.error(t("login.captchaCodeRequired"));
return;
}