feat: unify search with browse page

This commit is contained in:
TerryM
2026-05-27 11:33:48 +08:00
parent f169144378
commit 3f0a395f40
6 changed files with 45 additions and 140 deletions

View File

@@ -1,5 +1,6 @@
import { useEffect, useMemo, useRef } from "react";
import { useSearchParams } from "react-router-dom";
import { postJSON } from "../../api";
import { useI18n } from "../../i18n";
import type { PostScope } from "../../types/post";
import { FilterChips } from "./FilterChips";
@@ -16,8 +17,12 @@ export function MessageStream({ scope }: MessageStreamProps) {
const [sp, setSp] = useSearchParams();
const type = sp.get("type") || "all";
const q = (sp.get("q") || "").trim();
const params = useMemo(() => ({ scope, type, lang }), [scope, type, lang]);
const params = useMemo(
() => ({ scope, type, q, lang }),
[scope, type, q, lang],
);
const { items, isLoading, error, hasMore, loadMore, reset } =
usePostStream(params);
@@ -34,6 +39,10 @@ export function MessageStream({ scope }: MessageStreamProps) {
isLoadingRef.current = isLoading;
}, [isLoading]);
useEffect(() => {
if (q) postJSON("/api/search-log", { query: q }).catch(() => {});
}, [q]);
useEffect(() => {
const el = sentinelRef.current;
if (!el) return;

View File

@@ -14,6 +14,7 @@ export type PostStreamParams = {
scope: PostScope;
type?: string;
language?: string;
q?: string;
lang: Lang;
};
@@ -56,7 +57,20 @@ function filterMock(params: PostStreamParams): Post[] {
p.categorySlug !== params.scope.slug
)
return false;
const q = params.q?.trim().toLowerCase();
if (params.language && p.language !== params.language) return false;
if (q) {
const haystack = [
p.text ?? "",
p.categorySlug,
p.postType ?? "",
...(p.tags ?? []),
...p.attachments.flatMap((a) => [a.filename, a.mime, a.kind]),
]
.join("\n")
.toLowerCase();
if (!haystack.includes(q)) return false;
}
if (!postMatchesType(p, params.type ?? "all")) return false;
return true;
}).sort(
@@ -67,13 +81,15 @@ function filterMock(params: PostStreamParams): Post[] {
function buildRealUrl(params: PostStreamParams, cursor?: string): string {
const sp = new URLSearchParams();
const q = params.q?.trim();
sp.set("lang", langQuery(params.lang));
sp.set("limit", String(PAGE_SIZE));
if (q) sp.set("q", q);
if (params.scope.kind === "category") sp.set("category", params.scope.slug);
if (params.type && params.type !== "all") sp.set("type", params.type);
if (params.language) sp.set("language", sourceLanguageQuery(params.language));
if (cursor) sp.set("cursor", cursor);
return `/api/posts?${sp.toString()}`;
return `${q ? "/api/posts/search" : "/api/posts"}?${sp.toString()}`;
}
export function usePostStream(params: PostStreamParams): PostStreamResult {
@@ -146,6 +162,7 @@ export function usePostStream(params: PostStreamParams): PostStreamResult {
params.scope.kind === "category" ? params.scope.slug : "",
params.type,
params.language,
params.q,
params.lang,
]);