From 240351bd317a2018115c9cf8c3c1ad46433da22a Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Sat, 7 Feb 2026 05:39:51 +0530 Subject: [PATCH] fix(board): show live feed history --- frontend/src/app/boards/[boardId]/page.tsx | 80 +++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/boards/[boardId]/page.tsx b/frontend/src/app/boards/[boardId]/page.tsx index b7736a60..1784834d 100644 --- a/frontend/src/app/boards/[boardId]/page.tsx +++ b/frontend/src/app/boards/[boardId]/page.tsx @@ -44,6 +44,7 @@ import { streamApprovalsApiV1BoardsBoardIdApprovalsStreamGet, updateApprovalApiV1BoardsBoardIdApprovalsApprovalIdPatch, } from "@/api/generated/approvals/approvals"; +import { listTaskCommentFeedApiV1ActivityTaskCommentsGet } from "@/api/generated/activity/activity"; import { getBoardSnapshotApiV1BoardsBoardIdSnapshotGet } from "@/api/generated/boards/boards"; import { createBoardMemoryApiV1BoardsBoardIdMemoryPost, @@ -307,6 +308,12 @@ export default function BoardDetailPage() { const openedTaskIdFromUrlRef = useRef(null); const [comments, setComments] = useState([]); const [liveFeed, setLiveFeed] = useState([]); + const [isLiveFeedHistoryLoading, setIsLiveFeedHistoryLoading] = + useState(false); + const [liveFeedHistoryError, setLiveFeedHistoryError] = useState< + string | null + >(null); + const liveFeedHistoryLoadedRef = useRef(false); const [isCommentsLoading, setIsCommentsLoading] = useState(false); const [commentsError, setCommentsError] = useState(null); const [newComment, setNewComment] = useState(""); @@ -345,6 +352,71 @@ export default function BoardDetailPage() { }); }, []); + useEffect(() => { + liveFeedHistoryLoadedRef.current = false; + setIsLiveFeedHistoryLoading(false); + setLiveFeedHistoryError(null); + setLiveFeed([]); + }, [boardId]); + + useEffect(() => { + if (!isLiveFeedOpen) return; + if (!isSignedIn || !boardId) return; + if (liveFeedHistoryLoadedRef.current) return; + + let cancelled = false; + setIsLiveFeedHistoryLoading(true); + setLiveFeedHistoryError(null); + + const fetchHistory = async () => { + try { + const result = await listTaskCommentFeedApiV1ActivityTaskCommentsGet({ + board_id: boardId, + limit: 200, + }); + if (cancelled) return; + if (result.status !== 200) { + throw new Error("Unable to load live feed."); + } + const items = result.data.items ?? []; + liveFeedHistoryLoadedRef.current = true; + + const mapped: TaskComment[] = items.map((item) => ({ + id: item.id, + message: item.message ?? null, + agent_id: item.agent_id ?? null, + task_id: item.task_id ?? null, + created_at: item.created_at, + })); + + setLiveFeed((prev) => { + const map = new Map(); + [...prev, ...mapped].forEach((item) => map.set(item.id, item)); + const merged = [...map.values()]; + merged.sort((a, b) => { + const aTime = apiDatetimeToMs(a.created_at) ?? 0; + const bTime = apiDatetimeToMs(b.created_at) ?? 0; + return bTime - aTime; + }); + return merged.slice(0, 50); + }); + } catch (err) { + if (cancelled) return; + setLiveFeedHistoryError( + err instanceof Error ? err.message : "Unable to load live feed.", + ); + } finally { + if (cancelled) return; + setIsLiveFeedHistoryLoading(false); + } + }; + + void fetchHistory(); + return () => { + cancelled = true; + }; + }, [boardId, isLiveFeedOpen, isSignedIn]); + const [isDialogOpen, setIsDialogOpen] = useState(false); const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); @@ -2365,7 +2437,13 @@ export default function BoardDetailPage() {
- {orderedLiveFeed.length === 0 ? ( + {isLiveFeedHistoryLoading && orderedLiveFeed.length === 0 ? ( +

Loading feed…

+ ) : liveFeedHistoryError ? ( +
+ {liveFeedHistoryError} +
+ ) : orderedLiveFeed.length === 0 ? (

Waiting for new comments…