feat(app,server): rank new-workspace picker by recency with debounced search

Plumb updatedAt through GitHub issue/PR search and committerDate through
branch suggestions so the new-workspace picker interleaves branches and
PRs sorted by last activity. Debounce the search query so remote GitHub
searches are driven by what the user typed rather than a static list.
This commit is contained in:
Mohamed Boudra
2026-04-19 14:26:51 +07:00
parent 43bbf8cb12
commit d3393b434a
6 changed files with 123 additions and 83 deletions
+23 -7
View File
@@ -765,12 +765,21 @@ const x = 1;
execSync("git fetch origin", { cwd: repoDir });
const branches = await listBranchSuggestions(repoDir, { limit: 50 });
expect(branches).toContain("main");
expect(branches).toContain("local-only");
expect(branches).toContain("remote-only");
expect(branches.filter((name) => name === "main")).toHaveLength(1);
expect(branches).not.toContain("HEAD");
expect(branches.some((name) => name.startsWith("origin/"))).toBe(false);
const branchNames = branches.map((branch) => branch.name);
expect(branchNames).toContain("main");
expect(branchNames).toContain("local-only");
expect(branchNames).toContain("remote-only");
expect(branchNames.filter((name) => name === "main")).toHaveLength(1);
expect(branchNames).not.toContain("HEAD");
expect(branchNames.some((name) => name.startsWith("origin/"))).toBe(false);
expect(branches).toEqual(
expect.arrayContaining([
expect.objectContaining({
name: "main",
committerDate: expect.any(Number),
}),
]),
);
});
it("filters branch suggestions by query and enforces result limit", async () => {
@@ -786,7 +795,8 @@ const x = 1;
limit: 1,
});
expect(branches).toHaveLength(1);
expect(branches[0]?.toLowerCase()).toContain("feature/");
expect(branches[0]?.name.toLowerCase()).toContain("feature/");
expect(branches[0]?.committerDate).toEqual(expect.any(Number));
});
it("disables GitHub features when gh is unavailable", async () => {
@@ -816,6 +826,7 @@ const x = 1;
state: "OPEN",
body: "issue body",
labels: ["bug"],
updatedAt: "2026-04-18T12:00:00Z",
},
];
};
@@ -832,6 +843,7 @@ const x = 1;
baseRefName: "main",
headRefName: "feature",
labels: ["enhancement"],
updatedAt: "2026-04-18T13:00:00Z",
},
];
};
@@ -853,6 +865,7 @@ const x = 1;
labels: ["bug"],
baseRefName: null,
headRefName: null,
updatedAt: "2026-04-18T12:00:00Z",
},
{
kind: "pr",
@@ -864,6 +877,7 @@ const x = 1;
labels: ["enhancement"],
baseRefName: "main",
headRefName: "feature",
updatedAt: "2026-04-18T13:00:00Z",
},
],
});
@@ -890,6 +904,7 @@ const x = 1;
baseRefName: "main",
headRefName: "feature",
labels: ["enhancement"],
updatedAt: "2026-04-18T13:00:00Z",
},
];
};
@@ -913,6 +928,7 @@ const x = 1;
labels: ["enhancement"],
baseRefName: "main",
headRefName: "feature",
updatedAt: "2026-04-18T13:00:00Z",
},
],
});