diff --git a/apps/nextjs/src/components/board/board-switcher.tsx b/apps/nextjs/src/components/board/board-switcher.tsx index 9c7be4ec2..9184a0d99 100644 --- a/apps/nextjs/src/components/board/board-switcher.tsx +++ b/apps/nextjs/src/components/board/board-switcher.tsx @@ -53,9 +53,12 @@ export const BoardSwitcher = ({ children }: BoardSwitcherProps) => { data: boards = [], isPending, isError, - } = clientApi.board.getManageOverview.useQuery(undefined, { - enabled: isOpen, - }); + } = clientApi.board.getManageOverview.useQuery( + { fullPreview: true }, + { + enabled: isOpen, + }, + ); const switcherBoards = useMemo( () => [ @@ -79,7 +82,7 @@ export const BoardSwitcher = ({ children }: BoardSwitcherProps) => { setSearch(""); setActiveIndex(0); }, []); - const preloadBoards = () => void utils.board.getManageOverview.prefetch(); + const preloadBoards = () => void utils.board.getManageOverview.prefetch({ fullPreview: true }); useHotkeys([[boardSwitcherHotkey, openSwitcher, { preventDefault: true }]]); diff --git a/packages/api/src/router/board.ts b/packages/api/src/router/board.ts index 617c9b270..345dd1161 100644 --- a/packages/api/src/router/board.ts +++ b/packages/api/src/router/board.ts @@ -86,6 +86,7 @@ interface BoardItemPlacementRectangle { const boardItemPlacementTails = new Map>(); const maxManageOverviewPreviewRows = 12; +const manageOverviewInputSchema = z.object({ fullPreview: z.boolean().default(false) }).optional(); const serializeBoardItemPlacementAsync = async (boardId: string, operation: () => Promise) => { const previous = boardItemPlacementTails.get(boardId) ?? Promise.resolve(); @@ -225,7 +226,7 @@ export const boardRouter = createTRPCRouter({ isMobileHome: currentUser?.mobileHomeBoardId === board.id, })); }), - getManageOverview: publicProcedure.query(async ({ ctx }) => { + getManageOverview: publicProcedure.input(manageOverviewInputSchema).query(async ({ ctx, input }) => { const userId = ctx.session?.user.id; const { boardIds, currentUser, groupMemberships } = await getBoardAccessContextAsync(ctx.db, userId); const groupPermissionWhere = getBoardGroupPermissionWhere(groupMemberships); @@ -306,7 +307,7 @@ export const boardRouter = createTRPCRouter({ inArray(itemLayouts.sectionId, rootSectionIds), gte(itemLayouts.xOffset, 0), gte(itemLayouts.yOffset, 0), - lt(itemLayouts.yOffset, maxManageOverviewPreviewRows), + input?.fullPreview ? undefined : lt(itemLayouts.yOffset, maxManageOverviewPreviewRows), gt(itemLayouts.width, 0), gt(itemLayouts.height, 0), ), @@ -331,7 +332,7 @@ export const boardRouter = createTRPCRouter({ inArray(sectionLayouts.parentSectionId, rootSectionIds), gte(sectionLayouts.xOffset, 0), gte(sectionLayouts.yOffset, 0), - lt(sectionLayouts.yOffset, maxManageOverviewPreviewRows), + input?.fullPreview ? undefined : lt(sectionLayouts.yOffset, maxManageOverviewPreviewRows), gt(sectionLayouts.width, 0), gt(sectionLayouts.height, 0), ), @@ -366,7 +367,7 @@ export const boardRouter = createTRPCRouter({ inArray(itemLayouts.sectionId, previewContainerSectionIds), gte(itemLayouts.xOffset, 0), gte(itemLayouts.yOffset, 0), - lt(itemLayouts.yOffset, maxManageOverviewPreviewRows), + input?.fullPreview ? undefined : lt(itemLayouts.yOffset, maxManageOverviewPreviewRows), gt(itemLayouts.width, 0), gt(itemLayouts.height, 0), ), diff --git a/packages/api/src/router/test/board.spec.ts b/packages/api/src/router/test/board.spec.ts index c194dd5ca..b8411ca1f 100644 --- a/packages/api/src/router/test/board.spec.ts +++ b/packages/api/src/router/test/board.spec.ts @@ -337,7 +337,7 @@ describe("getManageOverview", () => { expect(overview.map((board) => board.id)).not.toContain(hiddenBoardId); }); - test("returns one compact base-layout preview for each accessible board", async () => { + test("returns compact previews by default and full previews on request", async () => { const db = createDb(); const caller = boardRouter.createCaller({ db, deviceType: undefined, session: defaultSession }); const boardId = createId(); @@ -487,6 +487,10 @@ describe("getManageOverview", () => { expect(result[0]?.preview?.layouts).toHaveLength(1); expect(result[0]?.preview?.items.map((item) => item.id)).toEqual([itemId, nestedItemId]); expect(result[0]?.preview?.sections).toHaveLength(2); + + const fullResult = await caller.getManageOverview({ fullPreview: true }); + + expect(fullResult[0]?.preview?.items.map((item) => item.id)).toEqual([itemId, offscreenItemId, nestedItemId]); }); test("includes app and widget icons in compact previews", async () => {