fix(web): keep timeline date labels fresh and stop regrouping every render

Two issues in the timeline view:

- `now` was captured once with `useState(() => new Date())`, so the relative
  date headers ("Today", "Yesterday", weekday names) never updated. A tab left
  open across midnight kept labelling the previous day's documents as "Today".
  Refresh `now` on a one-minute interval, but only swap the value when the
  calendar day actually changes so same-day ticks don't cause re-renders.

- `groupDocuments(documents, now)` (sorts the full list and reparses every
  createdAt) ran on every render, including during scroll and selection.
  Memoize it on `[documents, now]` so it only recomputes when the data or the
  day changes.

The pre-existing type error at timeline-view.tsx:279 is unrelated (present on
main).
This commit is contained in:
abhay-codes07 2026-08-16 14:27:20 +05:30
parent e651045ac5
commit 727c79c49e
No known key found for this signature in database

View file

@ -1,6 +1,6 @@
"use client"
import { useState, useEffect, useRef, useCallback } from "react"
import { useState, useEffect, useMemo, useRef, useCallback } from "react"
import { AnimatePresence, motion } from "motion/react"
import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api"
import type { z } from "zod"
@ -505,7 +505,21 @@ export function TimelineView({
selectedDocumentIds = new Set(),
onToggleSelection,
}: TimelineViewProps) {
const [now] = useState(() => new Date())
// `now` drives the "Today"/"Yesterday"/weekday labels. Refresh it when the
// calendar day rolls over so a tab left open across midnight doesn't keep
// labelling yesterday's documents as "Today". Same-day ticks return the
// previous value, so React skips the re-render and the grouping below only
// recomputes on an actual day change.
const [now, setNow] = useState(() => new Date())
useEffect(() => {
const id = setInterval(() => {
setNow((prev) => {
const current = new Date()
return current.toDateString() === prev.toDateString() ? prev : current
})
}, 60_000)
return () => clearInterval(id)
}, [])
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set())
const sentinelRef = useRef<HTMLDivElement>(null)
@ -532,7 +546,10 @@ export function TimelineView({
})
}, [])
const periodGroups = groupDocuments(documents, now)
const periodGroups = useMemo(
() => groupDocuments(documents, now),
[documents, now],
)
const handleTimelineCardSelection = useCallback(
(doc: DocumentWithMemories) => {
if (doc.id) onToggleSelection?.(doc.id)