fix: favorites click opens isolated single-post view

When `linkToResource` is set, PopularRankRow now navigates to /resource/<id>?single=1 and PostRedirect propagates the `single=1` flag to the /browse?post=... target. MessageStream already supports singlePostMode (no filter bar, no sentinel, only the target post in the list), so favorites cards open the post in isolation instead of dropping the user into the surrounding stream.
This commit is contained in:
TerryM
2026-06-06 00:23:46 +08:00
parent 37e6e4901f
commit fd1a3f4b3e
2 changed files with 17 additions and 8 deletions

View File

@@ -150,7 +150,7 @@ export function PopularRankRow({
type="button" type="button"
onClick={() => { onClick={() => {
if (linkToResource) { if (linkToResource) {
navigate(lp(`/resource/${encodeURIComponent(post.id)}`)); navigate(lp(`/resource/${encodeURIComponent(post.id)}?single=1`));
return; return;
} }
const params = new URLSearchParams(); const params = new URLSearchParams();

View File

@@ -1,5 +1,5 @@
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams, useSearchParams } from "react-router-dom";
import { getJSON } from "../../api"; import { getJSON } from "../../api";
import { langQuery, useI18n, type Lang } from "../../i18n"; import { langQuery, useI18n, type Lang } from "../../i18n";
import { useLocalizedPath } from "../../useLocalizedPath"; import { useLocalizedPath } from "../../useLocalizedPath";
@@ -25,6 +25,8 @@ function postLangToUiLang(code: string | undefined): Lang | null {
export function PostRedirect() { export function PostRedirect() {
const { id } = useParams(); const { id } = useParams();
const [sp] = useSearchParams();
const singleMode = sp.get("single") === "1";
const { lang, t } = useI18n(); const { lang, t } = useI18n();
const navigate = useNavigate(); const navigate = useNavigate();
const lp = useLocalizedPath(); const lp = useLocalizedPath();
@@ -41,18 +43,25 @@ export function PostRedirect() {
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);
const suffix = singleMode ? "&single=1" : "";
navigate( navigate(
lp(post ? `/browse?post=${encodeURIComponent(post.id)}` : "/browse"), lp(
{ post
replace: true, ? `/browse?post=${encodeURIComponent(post.id)}${suffix}`
}, : "/browse",
),
{ replace: true },
); );
return; return;
} }
const goToPostInLang = (post: Post, targetLang: Lang) => { const goToPostInLang = (post: Post, targetLang: Lang) => {
const suffix = singleMode ? "&single=1" : "";
navigate( navigate(
localizePath(`/browse?post=${encodeURIComponent(post.id)}`, targetLang), localizePath(
`/browse?post=${encodeURIComponent(post.id)}${suffix}`,
targetLang,
),
{ replace: true }, { replace: true },
); );
}; };
@@ -73,7 +82,7 @@ export function PostRedirect() {
}) })
.catch(() => navigate(lp("/browse"), { replace: true })); .catch(() => navigate(lp("/browse"), { replace: true }));
}); });
}, [id, lang, navigate, lp, showToast, t]); }, [id, lang, navigate, lp, showToast, singleMode, t]);
return ( return (
<div <div