From 552e1741db1085050e105048fa665c59422dfb64 Mon Sep 17 00:00:00 2001 From: vrustx <279631638@qq.com> Date: Thu, 16 Jul 2026 15:19:04 +0800 Subject: [PATCH] fix(navigator): align object browser table sorting --- .../src/lib/table/objectBrowserRows.ts | 9 +++---- apps/desktop/src/lib/table/tableTree.ts | 6 +++++ packages/app-tests/objectBrowserRows.test.ts | 24 +++++++++++++++++-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/apps/desktop/src/lib/table/objectBrowserRows.ts b/apps/desktop/src/lib/table/objectBrowserRows.ts index 8b17d2c25..efdcaa81d 100644 --- a/apps/desktop/src/lib/table/objectBrowserRows.ts +++ b/apps/desktop/src/lib/table/objectBrowserRows.ts @@ -1,5 +1,5 @@ import type { ObjectInfo } from "@/types/database"; -import { createDatabaseObjectNameComparator, normalizeDatabaseObjectName } from "@/lib/table/tableTree"; +import { compareDatabaseObjectNames, normalizeDatabaseObjectName } from "@/lib/table/tableTree"; import { parseSlashDelimitedRegexQuery } from "@/lib/common/searchPattern"; export type ObjectBrowserRow = { @@ -122,11 +122,12 @@ export function filterObjectBrowserRows(rows: ObjectBrowserRow[], query: string) export function sortObjectBrowserRows(rows: ObjectBrowserRow[], key: ObjectBrowserSortKey, direction: ObjectBrowserSortDirection): ObjectBrowserRow[] { const multiplier = direction === "asc" ? 1 : -1; - const compareNames = createDatabaseObjectNameComparator(rows.map((row) => row.displayName)); + // Sort by natural visible name, matching the sidebar tree ordering + // (see fix "keep tables sorted by visible name" and issue #3604). return [...rows].sort((left, right) => { - const compared = key === "name" ? compareNames(left.displayName, right.displayName) : compareObjectBrowserValue(left[key], right[key], key, direction); + const compared = key === "name" ? compareDatabaseObjectNames(left.displayName, right.displayName) : compareObjectBrowserValue(left[key], right[key], key, direction); if (compared !== 0) return compared * multiplier; - return compareNames(left.displayName, right.displayName); + return compareDatabaseObjectNames(left.displayName, right.displayName); }); } diff --git a/apps/desktop/src/lib/table/tableTree.ts b/apps/desktop/src/lib/table/tableTree.ts index 48822cf5e..8f6a3db3b 100644 --- a/apps/desktop/src/lib/table/tableTree.ts +++ b/apps/desktop/src/lib/table/tableTree.ts @@ -211,6 +211,12 @@ export function sortDatabaseObjectsByName(items: readonly T[], getName: (item return [...items].sort((left, right) => databaseObjectNameCollator.compare(getName(left), getName(right))); } +// Shared with the object browser so both sides of the UI list objects in the +// same natural visible-name order as the sidebar tree (issue #3604). +export function compareDatabaseObjectNames(left: string, right: string): number { + return databaseObjectNameCollator.compare(left, right); +} + export function mergeTableInfosIntoObjects(objects: readonly ObjectInfo[], tables: readonly TableInfo[], schema?: string): ObjectInfo[] { const merged = [...objects]; const seen = new Set( diff --git a/packages/app-tests/objectBrowserRows.test.ts b/packages/app-tests/objectBrowserRows.test.ts index 6b4fe7063..21080c926 100644 --- a/packages/app-tests/objectBrowserRows.test.ts +++ b/packages/app-tests/objectBrowserRows.test.ts @@ -193,7 +193,7 @@ test("object browser formats statistics for compact table cells", () => { assert.equal(formatObjectBrowserBytes(null), ""); }); -test("object browser name sort keeps base-prefixed tables before prefixed variants", () => { +test("object browser name sort keeps natural name order like the sidebar tree", () => { const rows = buildObjectBrowserRows({ objects: [ { name: "chat_staff", object_type: "TABLE", schema: "public" }, @@ -208,7 +208,27 @@ test("object browser name sort keeps base-prefixed tables before prefixed varian assert.deepEqual( sortObjectBrowserRows(rows, "name", "asc").map((row) => row.name), - ["staff", "staff_his", "chat_staff", "chat_staff_his"], + ["chat_staff", "chat_staff_his", "staff", "staff_his"], + ); +}); + +test("object browser name sort does not relocate prefixed business tables by suffix", () => { + // Mirrors the sidebar regression test from "keep tables sorted by visible + // name" — both sides must list tables identically (issue #3604). + const rows = buildObjectBrowserRows({ + objects: [ + { name: "YonSuite_CurrentStock", object_type: "TABLE", schema: "dbo" }, + { name: "CurrentStock", object_type: "TABLE", schema: "dbo" }, + { name: "YonSuite_LocationStock", object_type: "TABLE", schema: "dbo" }, + ], + database: "app", + fallbackSchema: "dbo", + needsSchema: true, + }); + + assert.deepEqual( + sortObjectBrowserRows(rows, "name", "asc").map((row) => row.name), + ["CurrentStock", "YonSuite_CurrentStock", "YonSuite_LocationStock"], ); });