@@ -18,7 +18,7 @@ import {
1818 Trash2 ,
1919} from "lucide-react" ;
2020import Link from "next/link" ;
21- import React , { useMemo , useState } from "react" ;
21+ import React , { useMemo , useState , useEffect } from "react" ;
2222import { useImmer } from "use-immer" ;
2323import { useLoginPopup } from "./app-login-popup" ;
2424import ResourceReaction from "./ResourceReaction" ;
@@ -38,6 +38,7 @@ import { Button } from "./ui/button";
3838import { Skeleton } from "./ui/skeleton" ;
3939import { Textarea } from "./ui/textarea" ;
4040import getFileUrl from "@/utils/getFileUrl" ;
41+ import { listenChannel } from "@/lib/pusher/pusher.client" ;
4142
4243const Context = React . createContext <
4344 { mutatingId ?: string ; setMutatingId : ( id ?: string ) => void } | undefined
@@ -155,6 +156,22 @@ export const CommentSection = (props: {
155156 refetchOnReconnect : false ,
156157 } ) ;
157158
159+ // Phase 2: subscribe to the resource's public Pusher channel and
160+ // invalidate the comments query when any mutation arrives from another client.
161+ useEffect ( ( ) => {
162+ const channelName = `resource.${ props . resource_type } .${ props . resource_id } ` ;
163+ const invalidate = ( ) => {
164+ queryClient . invalidateQueries ( {
165+ queryKey : [ "comments" , props . resource_id , props . resource_type ] ,
166+ } ) ;
167+ } ;
168+ return listenChannel ( channelName , {
169+ "comment.created" : invalidate ,
170+ "comment.updated" : invalidate ,
171+ "comment.deleted" : invalidate ,
172+ } ) ;
173+ } , [ props . resource_id , props . resource_type , queryClient ] ) ;
174+
158175 const generated_comment_id = ( ) => crypto . randomUUID ( ) ;
159176 const listQueryKey = [
160177 "comments" ,
0 commit comments