fix: dedupe post redirect language fallback
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 30s

This commit is contained in:
TerryM
2026-06-04 18:07:51 +08:00
parent 1fcf2ea46d
commit 062f630798

View File

@@ -1,25 +1,43 @@
import { useEffect } from "react"; import { useEffect, useRef } from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { getJSON } from "../../api"; import { getJSON } from "../../api";
import { langQuery, useI18n } from "../../i18n"; import { langQuery, useI18n, type Lang } from "../../i18n";
import { useLocalizedPath } from "../../useLocalizedPath"; import { useLocalizedPath } from "../../useLocalizedPath";
import { localizePath } from "../../languageRoutes";
import { MOCK_POSTS } from "../../mocks/mockPosts"; import { MOCK_POSTS } from "../../mocks/mockPosts";
import { POST_STREAM_USES_MOCK } from "../../components/messageStream/hooks/usePostStream"; import { POST_STREAM_USES_MOCK } from "../../components/messageStream/hooks/usePostStream";
import { useToast } from "../../components/Toast"; import { useToast } from "../../components/Toast";
import { Skeleton } from "../../components/Skeleton";
import type { Post } from "../../types/post"; import type { Post } from "../../types/post";
function postLangToUiLang(code: string | undefined): Lang | null {
if (!code) return null;
const lc = code.trim().toLowerCase();
if (lc === "zh" || lc === "zh-cn" || lc === "zh-hans") return "zh-CN";
if (lc === "en") return "en";
if (lc === "ja") return "ja";
if (lc === "ko") return "ko";
if (lc === "vi") return "vi";
if (lc === "id") return "id";
if (lc === "ms") return "ms";
return null;
}
export function PostRedirect() { export function PostRedirect() {
const { id } = useParams(); const { id } = useParams();
const { lang, t } = useI18n(); const { lang, t } = useI18n();
const navigate = useNavigate(); const navigate = useNavigate();
const lp = useLocalizedPath(); const lp = useLocalizedPath();
const { showToast } = useToast(); const { showToast } = useToast();
const handledIdRef = useRef<string | null>(null);
useEffect(() => { useEffect(() => {
if (!id) { if (!id) {
navigate(lp("/browse"), { replace: true }); navigate(lp("/browse"), { replace: true });
return; return;
} }
if (handledIdRef.current === id) return;
handledIdRef.current = id;
if (POST_STREAM_USES_MOCK) { if (POST_STREAM_USES_MOCK) {
const post = MOCK_POSTS.find((p) => p.id === id); const post = MOCK_POSTS.find((p) => p.id === id);
@@ -32,25 +50,47 @@ export function PostRedirect() {
return; return;
} }
const goToPost = (post: Post) => { const goToPostInLang = (post: Post, targetLang: Lang) => {
navigate(lp(`/browse?post=${encodeURIComponent(post.id)}`), { navigate(
replace: true, localizePath(`/browse?post=${encodeURIComponent(post.id)}`, targetLang),
}); { replace: true },
);
}; };
getJSON<Post>( getJSON<Post>(
`/api/posts/${id}?lang=${encodeURIComponent(langQuery(lang))}`, `/api/posts/${id}?lang=${encodeURIComponent(langQuery(lang))}`,
) )
.then(goToPost) .then((post) => goToPostInLang(post, lang))
.catch(() => { .catch(() => {
getJSON<Post>(`/api/posts/${id}`) getJSON<Post>(`/api/posts/${id}`)
.then((post) => { .then((post) => {
const sourceLang =
postLangToUiLang(post.sourceLanguage) ||
postLangToUiLang(post.language) ||
lang;
showToast(t("postShownInOriginalLanguage")); showToast(t("postShownInOriginalLanguage"));
goToPost(post); goToPostInLang(post, sourceLang);
}) })
.catch(() => navigate(lp("/browse"), { replace: true })); .catch(() => navigate(lp("/browse"), { replace: true }));
}); });
}, [id, lang, navigate, lp, showToast, t]); }, [id, lang, navigate, lp, showToast, t]);
return <div className="text-neutral-400"></div>; return (
<div
aria-live="polite"
aria-label={t("loading")}
className="mx-auto flex max-w-[1180px] flex-col gap-3 px-4 pt-4 md:px-0 md:pt-2"
>
{Array.from({ length: 6 }).map((_, i) => (
<div
key={i}
className="mx-auto w-full max-w-[358px] md:max-w-[680px] lg:max-w-[900px] xl:max-w-[1120px]"
>
<Skeleton
className={`rounded-2xl ${i % 3 === 0 ? "h-[220px]" : "h-[80px]"}`}
/>
</div>
))}
</div>
);
} }