diff --git a/web/src/components/MemoEditor/index.tsx b/web/src/components/MemoEditor/index.tsx index 970372b02..ba5b74ad8 100644 --- a/web/src/components/MemoEditor/index.tsx +++ b/web/src/components/MemoEditor/index.tsx @@ -118,10 +118,17 @@ const MemoEditorImpl: React.FC = ({ cacheService.clear(cacheService.key(currentUser?.name ?? "", cacheKey)); // Invalidate React Query cache to refresh memo lists across the app - await Promise.all([ + const invalidationPromises = [ queryClient.invalidateQueries({ queryKey: memoKeys.lists() }), queryClient.invalidateQueries({ queryKey: userKeys.stats() }), - ]); + ]; + + // If this was a comment, also invalidate the comments query for the parent memo + if (parentMemoName) { + invalidationPromises.push(queryClient.invalidateQueries({ queryKey: memoKeys.comments(parentMemoName) })); + } + + await Promise.all(invalidationPromises); // Reset editor state to initial values dispatch(actions.reset()); diff --git a/web/src/hooks/useMemoQueries.ts b/web/src/hooks/useMemoQueries.ts index 40a152b96..bb61426ed 100644 --- a/web/src/hooks/useMemoQueries.ts +++ b/web/src/hooks/useMemoQueries.ts @@ -13,6 +13,7 @@ export const memoKeys = { list: (filters: Partial) => [...memoKeys.lists(), filters] as const, details: () => [...memoKeys.all, "detail"] as const, detail: (name: string) => [...memoKeys.details(), name] as const, + comments: (name: string) => [...memoKeys.all, "comments", name] as const, }; export function useMemos(request: Partial = {}) { @@ -139,3 +140,15 @@ export function useDeleteMemo() { }, }); } + +export function useMemoComments(name: string, options?: { enabled?: boolean }) { + return useQuery({ + queryKey: memoKeys.comments(name), + queryFn: async () => { + const response = await memoServiceClient.listMemoComments({ name }); + return response; + }, + enabled: options?.enabled ?? true, + staleTime: 1000 * 60, // 1 minute + }); +} diff --git a/web/src/pages/MemoDetail.tsx b/web/src/pages/MemoDetail.tsx index 7c45a10a7..acc724e20 100644 --- a/web/src/pages/MemoDetail.tsx +++ b/web/src/pages/MemoDetail.tsx @@ -10,11 +10,10 @@ import MobileHeader from "@/components/MobileHeader"; import { Button } from "@/components/ui/button"; import { memoNamePrefix } from "@/helpers/resource-names"; import useCurrentUser from "@/hooks/useCurrentUser"; -import { useMemo as useMemoQuery } from "@/hooks/useMemoQueries"; +import { useMemo, useMemoComments } from "@/hooks/useMemoQueries"; import useNavigateTo from "@/hooks/useNavigateTo"; import useResponsiveWidth from "@/hooks/useResponsiveWidth"; import { cn } from "@/lib/utils"; -import { Memo, MemoRelation_Type } from "@/types/proto/api/v1/memo_service_pb"; import { useTranslate } from "@/utils/i18n"; const MemoDetail = () => { @@ -29,7 +28,7 @@ const MemoDetail = () => { const [showCommentEditor, setShowCommentEditor] = useState(false); // Fetch main memo with React Query - const { data: memo, error, isLoading } = useMemoQuery(memoName, { enabled: !!memoName }); + const { data: memo, error, isLoading } = useMemo(memoName, { enabled: !!memoName }); // Handle errors if (error) { @@ -38,18 +37,15 @@ const MemoDetail = () => { } // Fetch parent memo if exists - const { data: parentMemo } = useMemoQuery(memo?.parent || "", { + const { data: parentMemo } = useMemo(memo?.parent || "", { enabled: !!memo?.parent, }); - // Get comment relations and memo names - const commentRelations = - memo?.relations.filter((relation) => relation.relatedMemo?.name === memo.name && relation.type === MemoRelation_Type.COMMENT) || []; - const commentMemoNames = commentRelations.map((relation) => relation.memo!.name); - - // Fetch all comment memos - const commentQueries = commentMemoNames.map((name) => useMemoQuery(name)); - const comments = commentQueries.map((q) => q.data).filter((memo): memo is Memo => !!memo); + // Fetch all comments for this memo in a single query + const { data: commentsResponse } = useMemoComments(memoName, { + enabled: !!memo, + }); + const comments = commentsResponse?.memos || []; const showCreateCommentButton = currentUser && !showCommentEditor;