diff --git a/apps/mobile/src/features/pull-requests/PullRequestListFilters.tsx b/apps/mobile/src/features/pull-requests/PullRequestListFilters.tsx index 38ac98f3b2a84..4bceebd637bfc 100644 --- a/apps/mobile/src/features/pull-requests/PullRequestListFilters.tsx +++ b/apps/mobile/src/features/pull-requests/PullRequestListFilters.tsx @@ -41,12 +41,18 @@ function choices(field: string, options: Readonly>, selec })); } -type ProjectOrder = readonly { readonly memberProjectRefs: readonly ScopedProjectRef[] }[]; +type ProjectOrder = readonly { + readonly memberProjectRefs: readonly ScopedProjectRef[]; + readonly pinned: boolean; + readonly archived: boolean; +}[]; const sameProjectOrder = (previous: ProjectOrder, next: ProjectOrder) => previous.length === next.length && previous.every((group, index) => { const members = next[index]!.memberProjectRefs; return ( + group.pinned === next[index]!.pinned && + group.archived === next[index]!.archived && group.memberProjectRefs.length === members.length && group.memberProjectRefs.every( (ref, member) => @@ -69,7 +75,11 @@ const sidebarProjectOrderFamily = Atom.family((mode: SidebarProjectGroupingMode) threads: get(environmentThreadShells.threadShellsAtom), pendingTasks: [], projectSortOrder: "updated_at", - }).map((scope) => ({ memberProjectRefs: scope.projectRefs })), + }).map((scope) => ({ + memberProjectRefs: scope.projectRefs, + pinned: scope.pinned, + archived: scope.archived, + })), ).pipe(Atom.withEquality(sameProjectOrder)), ); diff --git a/packages/client-runtime/src/state/projectGrouping.test.ts b/packages/client-runtime/src/state/projectGrouping.test.ts index a5957d06e1b01..8f2be1133e07f 100644 --- a/packages/client-runtime/src/state/projectGrouping.test.ts +++ b/packages/client-runtime/src/state/projectGrouping.test.ts @@ -416,8 +416,23 @@ describe("sortProjectsByGroupOrder", () => { it("tells the same project id on two environments apart", () => { const sorted = sortProjectsByGroupOrder( [project("shared"), project("shared", remote)], - [{ memberProjectRefs: [ref("shared", remote)] }, { memberProjectRefs: [ref("shared")] }], + [ + { memberProjectRefs: [ref("shared", remote)], pinned: false, archived: false }, + { memberProjectRefs: [ref("shared")], pinned: false, archived: false }, + ], ); expect(sorted.map((entry) => entry.environmentId)).toEqual([remote, environmentId]); }); + + it("lists pinned projects first and archived ones last, like the sidebar's project menu", () => { + const sorted = sortProjectsByGroupOrder( + [project("archived"), project("recent"), project("pinned"), project("unlisted")], + [ + { memberProjectRefs: [ref("archived")], pinned: false, archived: true }, + { memberProjectRefs: [ref("recent")], pinned: false, archived: false }, + { memberProjectRefs: [ref("pinned")], pinned: true, archived: false }, + ], + ); + expect(sorted.map((entry) => entry.id)).toEqual(["pinned", "recent", "archived", "unlisted"]); + }); }); diff --git a/packages/client-runtime/src/state/projectGrouping.ts b/packages/client-runtime/src/state/projectGrouping.ts index 46fdc4e3dd3ae..1fbfd7af2c1e0 100644 --- a/packages/client-runtime/src/state/projectGrouping.ts +++ b/packages/client-runtime/src/state/projectGrouping.ts @@ -384,10 +384,14 @@ export function sortProjectsByGroupOrder< TProject extends { readonly id: string; readonly environmentId: string }, >( projects: ReadonlyArray, - groups: ReadonlyArray<{ readonly memberProjectRefs: ReadonlyArray }>, + groups: ReadonlyArray<{ + readonly memberProjectRefs: ReadonlyArray; + readonly pinned: boolean; + readonly archived: boolean; + }>, ): TProject[] { const rankByProject = new Map(); - groups.forEach((group, rank) => { + pickableProjectGroups(groups).forEach((group, rank) => { for (const ref of group.memberProjectRefs) { const key = `${ref.environmentId}\0${ref.projectId}`; if (!rankByProject.has(key)) rankByProject.set(key, rank);