fix: sort child chats newest-first and prepend on creation (#24524)

GetChildChatsByParentIDs sorted created_at ASC, but the cache
helper appended new children to the end. On refetch the API and
cache agreed on oldest-first, putting the just-created child at
the bottom. Users expect newest first, matching the root-chat
sidebar convention.

- SQL: change child sort to created_at DESC, id DESC.
- Cache: prepend instead of append in addChildToParentInCache
  (renamed from appendChildToParentInCache to avoid leaking
  position semantics).
- Test: update ordering assertion to expect newest-first.

Refs #24404
This commit is contained in:
Mathias Fredriksson
2026-04-20 10:43:31 +00:00
committed by GitHub
parent df7e838c21
commit 467430d8fa
6 changed files with 19 additions and 19 deletions
+6 -6
View File
@@ -4,7 +4,7 @@ import { API } from "#/api/api";
import type * as TypesGen from "#/api/typesGenerated";
import { buildOptimisticEditedMessage } from "./chatMessageEdits";
import {
appendChildToParentInCache,
addChildToParentInCache,
archiveChat,
cancelChatListRefetches,
chatCostSummary,
@@ -1703,8 +1703,8 @@ describe("mutation onMutate cancels pagination fetches", () => {
});
});
describe("appendChildToParentInCache", () => {
it("appends the child to the matching parent's children array", () => {
describe("addChildToParentInCache", () => {
it("prepends new child to the parent's children array", () => {
const queryClient = createTestQueryClient();
const parent = makeChat("parent-1");
seedInfiniteChats(queryClient, [parent]);
@@ -1713,7 +1713,7 @@ describe("appendChildToParentInCache", () => {
parent_chat_id: "parent-1",
root_chat_id: "parent-1",
});
appendChildToParentInCache(queryClient, child, "parent-1");
addChildToParentInCache(queryClient, child, "parent-1");
const result = readInfiniteChats(queryClient);
expect(result).toHaveLength(1);
@@ -1730,7 +1730,7 @@ describe("appendChildToParentInCache", () => {
parent_chat_id: "missing-parent",
root_chat_id: "missing-parent",
});
appendChildToParentInCache(queryClient, child, "missing-parent");
addChildToParentInCache(queryClient, child, "missing-parent");
const result = readInfiniteChats(queryClient);
expect(result).toHaveLength(1);
@@ -1747,7 +1747,7 @@ describe("appendChildToParentInCache", () => {
const parent = makeChat("parent-1", { children: [existingChild] });
seedInfiniteChats(queryClient, [parent]);
appendChildToParentInCache(queryClient, existingChild, "parent-1");
addChildToParentInCache(queryClient, existingChild, "parent-1");
const result = readInfiniteChats(queryClient);
expect(result?.[0].children).toHaveLength(1);
+3 -3
View File
@@ -103,11 +103,11 @@ export const readInfiniteChatsCache = (
};
/**
* Appends a child chat to its parent's `children` array across all
* Adds a child chat to its parent's `children` array across all
* infinite chat query caches. If the parent is not in any loaded page,
* the child is silently dropped (it will appear when the parent loads).
*/
export const appendChildToParentInCache = (
export const addChildToParentInCache = (
queryClient: QueryClient,
child: TypesGen.Chat,
parentId: string,
@@ -119,7 +119,7 @@ export const appendChildToParentInCache = (
// Avoid duplicates.
if (c.children?.some((ch) => ch.id === child.id)) return c;
changed = true;
return { ...c, children: [...(c.children ?? []), child] };
return { ...c, children: [child, ...(c.children ?? [])] };
});
return changed ? next : chats;
});