feat: unify search with browse page
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user