LibreChat/client
Danny Avila af7b2761eb
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
GitNexus Index / index (push) Waiting to run
GitNexus Index / post-index (push) Blocked by required conditions
🪟 perf: Virtualize Search Results and Stop the Per-Query Remount (#14352)
* 🪟 perf: Virtualize Search Results and Stop the Per-Query Remount

* 🔧 fix: Type-safe globalThis cast in Search route test

* 🔑 fix: Stabilize Search Row Keys and Harden Virtualized Result Edges

Address Codex review findings on the virtualized search results view:

- Key rows by messageId (outer React key + CellMeasurer + cache keyMapper all
  aligned) so React reconciles by message, not scroll slot.
- Compare title and conversationId in areSearchMessagePropsEqual so a rename or
  refetch that keeps text/id intact still re-renders the row.
- Recompute cached heights on same-length content changes (file previews
  resolving, refetch) and on font-size changes.
- Keep the aria-live announcement on the empty-results branch.
- Don't paginate the outgoing query while the user is still typing.
- Show the spinner during the initial debounce instead of a blank route.

* 🧵 fix: Reset Scroll, Remeasure Growth, and Footer-Pad Virtualized Search

Address the second Codex round on the virtualized search results view:

- Reset the List scroll to the top on a new query (results stay mounted via
  keepPreviousData, so the List otherwise keeps the previous scrollTop and can
  open a new search mid-list); a font-size change keeps the user's place.
- Re-measure a row when its content later grows/shrinks (tool/code output
  expands, a late image loads) via a ResizeObserver that clears just that row's
  cached height and recomputes from it.
- Give the load-more throttle trailing:false and cancel it when the query
  changes, so a queued fetch can't page a stale search.
- Add a fixed trailing spacer row so the last result clears the bottom
  gradient/spinner overlay.

* 🫥 fix: Gate Stale Search Results on Refetch State, Not Just Typing

Address the third Codex round: `isTyping` clears when the debounce publishes the
new query, but `keepPreviousData` keeps the old pages mounted until the new
request lands, leaving a window the typing-only guards missed.

- Derive `showingStale = isTyping || isPreviousData` and gate both the dimming
  and pagination on it, so the outgoing results stay dimmed and don't page while
  the new query is still fetching.
- Compare `unfinished` in areSearchMessagePropsEqual so a finish/cancel that
  changes only that flag re-renders SearchContent's incomplete-response notice.

* 📐 fix: Invalidate Row Height Against the Cache and Compare clientTimestamp

Address the fourth Codex round on virtualized search:

- Compare each ResizeObserver height against the cached row height instead of
  skipping the first callback, so a cached/fast-loading image that is already
  taller than CellMeasurer's mount measurement still invalidates the stale
  height (no more overlap/clipping of following rows).
- Compare clientTimestamp in areSearchMessagePropsEqual, since the row timestamp
  falls back to it when createdAt is absent.

* 🕳️ fix: Spinner Over False Nothing-Found for Stale Empty Search Data

Address the fifth Codex round: when the previous search had zero matches,
keepPreviousData holds those empty pages (isPreviousData, isLoading false)
during the new request, so the loading gate missed it and flashed a false
"nothing found". Gate the spinner on `showingStale` too, not just isLoading/
isTyping.
2026-07-22 04:26:47 -04:00
..
public
scripts
src 🪟 perf: Virtualize Search Results and Stop the Per-Query Remount (#14352) 2026-07-22 04:26:47 -04:00
sw 🛟 fix: Auto-Recover from Stale Service Worker Assets After Deploys (#13686) 2026-06-11 11:57:06 -04:00
test 🧰 feat: Redesign Agent Builder with Unified Tools Marketplace, Skills & Orchestration (#13952) 2026-07-05 11:30:12 -04:00
babel.config.cjs
check_updates.sh
index.html 📡 feat: add rum browser page-load diagnostics (#14106) 2026-07-05 11:32:53 -04:00
jest.config.cjs ⬆️ chore: Migrate off deprecated @ariakit/react-core to @ariakit/react-components (#13940) 2026-06-24 23:13:57 -04:00
jest.resolver.cjs ⬆️ chore: Migrate off deprecated @ariakit/react-core to @ariakit/react-components (#13940) 2026-06-24 23:13:57 -04:00
nginx.conf 🐳 feat: Bundle Admin Panel in Docker Compose Stacks (#13876) 2026-06-22 16:59:08 -04:00
package.json feat: Add Gemini 3.6 Flash and Gemini 3.5 Flash-Lite Support (#14369) 2026-07-21 21:14:11 -04:00
postcss.config.cjs
tailwind.config.cjs ⌨️ feat: Keyboard Shortcuts (#12425) 2026-06-22 17:02:46 -04:00
tsconfig.json 👷 ci: Type-check the Client Workspace (#13560) 2026-06-06 18:40:31 -04:00
vite.config.ts 🧩 chore: Prebundle Node Polyfills for Buffer, Process, and Global in Vite optimizeDeps (#14354) 2026-07-20 21:18:27 -04:00