authorgravatar for 123344143+AksharP5@users.noreply.github.comAkshar Patel <123344143+AksharP5@users.noreply.github.com> 2026-09-06 13:09:26-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-06 14:09:26-03:00
log64fafbdfcf91d3c44b533f5b8febbe8d6b19d482
treefd025b7c2d8e8c6ff8d88d3625cfd3b59a91f3a2
parent72cb638a8a6656d0b89899d9d62afaed0c2f7e5f
signature Signed by PGP key B5690EEEBB952194

perf(web): speed up folder menu sorting (#10190)


2 files changed, 12 insertions(+), 3 deletions(-)

apps/web/src/components/files/filePath.test.ts+9-2
......@@ -67,8 +67,15 @@ describe("fileBreadcrumbChildren", () => {
6767 ]);
6868 });
6969
70 it("uses natural file-name ordering", () => {
71 expect(fileBreadcrumbChildren(entries, "src/lib").map((entry) => entry.label)).toEqual([
70 it("uses natural file-name ordering and preserves input order for equivalent names", () => {
71 const files = ["file10.ts", "File2.ts", "file02.ts", "file2.ts"].map((name) => ({
72 path: `src/lib/${name}`,
73 kind: "file" as const,
74 }));
75
76 expect(fileBreadcrumbChildren(files, "src/lib").map((entry) => entry.label)).toEqual([
77 "File2.ts",
78 "file02.ts",
7279 "file2.ts",
7380 "file10.ts",
7481 ]);
apps/web/src/components/files/filePath.ts+3-1
......@@ -36,6 +36,7 @@ export function fileBreadcrumbChildren(
3636 entries: readonly ProjectEntry[],
3737 directoryPath: string,
3838): FileBreadcrumbChild[] {
39 let collator: Intl.Collator | undefined;
3940 const prefix = directoryPath ? `${directoryPath}/` : "";
4041 return entries
4142 .flatMap((entry) => {
......@@ -46,10 +47,11 @@ export function fileBreadcrumbChildren(
4647 })
4748 .toSorted((left, right) => {
4849 if (left.kind !== right.kind) return left.kind === "directory" ? -1 : 1;
49 return left.label.localeCompare(right.label, undefined, {
50 collator ??= new Intl.Collator(undefined, {
5051 numeric: true,
5152 sensitivity: "base",
5253 });
54 return collator.compare(left.label, right.label);
5355 });
5456}
5557