From df4b57bd414d4402522f9210b1470d0561c37274 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 22 May 2026 09:06:48 +0200 Subject: [PATCH] perf(boards): remove loading overlay and show board immediately (#5735) --- .../app/[locale]/boards/(content)/_client.tsx | 47 +------------------ .../boards/(content)/_ready-context.tsx | 39 ++------------- 2 files changed, 5 insertions(+), 81 deletions(-) diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx index e9551af52..0ba502a9a 100644 --- a/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx +++ b/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx @@ -1,70 +1,27 @@ "use client"; -import { useCallback, useRef } from "react"; -import { Box, LoadingOverlay, Stack } from "@mantine/core"; +import { Box, Stack } from "@mantine/core"; -import type { RouterOutputs } from "@homarr/api"; -import { clientApi } from "@homarr/api/client"; import { useCurrentLayout, useRequiredBoard } from "@homarr/boards/context"; import { BoardCategorySection } from "~/components/board/sections/category-section"; import { BoardEmptySection } from "~/components/board/sections/empty-section"; import { BoardBackgroundVideo } from "~/components/layout/background"; -import { fullHeightWithoutHeaderAndFooter } from "~/constants"; -import { useIsBoardReady } from "./_ready-context"; - -let boardName: string | null = null; - -export const updateBoardName = (name: string | null) => { - boardName = name; -}; - -type UpdateCallback = (prev: RouterOutputs["board"]["getHomeBoard"]) => RouterOutputs["board"]["getHomeBoard"]; - -export const useUpdateBoard = () => { - const utils = clientApi.useUtils(); - - const updateBoard = useCallback( - (updaterWithoutUndefined: UpdateCallback) => { - if (!boardName) { - throw new Error("Board name is not set"); - } - utils.board.getBoardByName.setData({ name: boardName }, (previous) => - previous ? updaterWithoutUndefined(previous) : previous, - ); - }, - [utils], - ); - - return { - updateBoard, - }; -}; export const ClientBoard = () => { const board = useRequiredBoard(); const currentLayoutId = useCurrentLayout(); - const isReady = useIsBoardReady(); const fullWidthSortedSections = board.sections .filter((section) => section.kind === "empty" || section.kind === "category") .sort((sectionA, sectionB) => sectionA.yOffset - sectionB.yOffset); - const ref = useRef(null); - return ( - - + {fullWidthSortedSections.map((section) => section.kind === "empty" ? ( - // Unique keys per layout to always reinitialize the gridstack ) : ( diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_ready-context.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_ready-context.tsx index 606a296ea..3d50c5a8c 100644 --- a/apps/nextjs/src/app/[locale]/boards/(content)/_ready-context.tsx +++ b/apps/nextjs/src/app/[locale]/boards/(content)/_ready-context.tsx @@ -1,42 +1,19 @@ "use client"; import type { PropsWithChildren } from "react"; -import { createContext, useCallback, useContext, useEffect, useState } from "react"; -import { usePathname } from "next/navigation"; - -import { clientApi } from "@homarr/api/client"; -import { useRequiredBoard } from "@homarr/boards/context"; +import { createContext, useCallback, useContext } from "react"; const BoardReadyContext = createContext<{ - isReady: boolean; markAsReady: (id: string) => void; } | null>(null); export const BoardReadyProvider = ({ children }: PropsWithChildren) => { - const pathname = usePathname(); - const utils = clientApi.useUtils(); - const board = useRequiredBoard(); - const [readySections, setReadySections] = useState([]); - - // Reset sections required for ready state - useEffect(() => { - return () => { - setReadySections([]); - }; - }, [pathname, utils]); - - useEffect(() => { - setReadySections((previous) => previous.filter((id) => board.sections.some((section) => section.id === id))); - }, [board.sections.length, setReadySections]); - - const markAsReady = useCallback((id: string) => { - setReadySections((previous) => (previous.includes(id) ? previous : [...previous, id])); - }, []); + // eslint-disable-next-line @typescript-eslint/no-empty-function + const markAsReady = useCallback((_id: string) => {}, []); return ( @@ -54,13 +31,3 @@ export const useMarkSectionAsReady = () => { return context.markAsReady; }; - -export const useIsBoardReady = () => { - const context = useContext(BoardReadyContext); - - if (!context) { - throw new Error("BoardReadyProvider is required"); - } - - return context.isReady; -};