diff --git a/apps/nextjs/src/app/[locale]/boards/_layout-creator.tsx b/apps/nextjs/src/app/[locale]/boards/_layout-creator.tsx index 6914d69f0..c06a20196 100644 --- a/apps/nextjs/src/app/[locale]/boards/_layout-creator.tsx +++ b/apps/nextjs/src/app/[locale]/boards/_layout-creator.tsx @@ -6,8 +6,7 @@ import { TRPCError } from "@trpc/server"; import { getRscUserSettingsAsync } from "@homarr/api/user-server"; import { auth } from "@homarr/auth/next"; -import { BoardProvider } from "@homarr/boards/context"; -import { EditModeProvider } from "@homarr/boards/edit-mode"; +import { constructBoardPermissions } from "@homarr/auth/shared"; import { boardViewportWidthCookieName, getLayoutIdForViewportWidth } from "@homarr/boards/layout-selection"; import { createLogger } from "@homarr/core/infrastructure/logs"; import { ModalProvider } from "@homarr/modals"; @@ -19,6 +18,7 @@ import { BoardTourGate } from "~/components/onboarding/board-tour-gate"; import { env } from "~/env"; import { getCurrentColorSchemeAsync } from "~/theme/color-scheme"; import type { Board } from "./_types"; +import { BoardProviders } from "./_providers"; import type { Params } from "./(content)/_creator"; import { CustomCss } from "./(content)/_custom-css"; import { BoardReadyProvider } from "./(content)/_ready-context"; @@ -88,34 +88,34 @@ export const createBoardLayout = ({ throw error; } const initialBoard = initialBoardResult.board; + const { hasChangeAccess } = constructBoardPermissions(initialBoard, session); const initialLayoutId = getLayoutIdForViewportWidth(initialBoard.layouts, initialViewportWidth); return ( - - - - - - - - } - actions={headerActions} - hasNavigation={false} - /> - {children} - - - - - + + + + + + } + actions={headerActions} + hasNavigation={false} + /> + {children} + + + + - + ); }; diff --git a/apps/nextjs/src/components/board/mobile/mobile-board.module.css b/apps/nextjs/src/components/board/mobile/mobile-board.module.css index f598ba348..902e77372 100644 --- a/apps/nextjs/src/components/board/mobile/mobile-board.module.css +++ b/apps/nextjs/src/components/board/mobile/mobile-board.module.css @@ -1,6 +1,6 @@ .grid { display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-template-columns: repeat(var(--mobile-column-count), minmax(0, 1fr)); grid-auto-flow: row; grid-auto-rows: min(calc((100vw - 42px) / 2), 12rem); gap: 10px; diff --git a/apps/nextjs/src/components/board/mobile/mobile-board.tsx b/apps/nextjs/src/components/board/mobile/mobile-board.tsx index 1568b6aac..5e7a1029f 100644 --- a/apps/nextjs/src/components/board/mobile/mobile-board.tsx +++ b/apps/nextjs/src/components/board/mobile/mobile-board.tsx @@ -1,6 +1,6 @@ "use client"; -import type { RefObject } from "react"; +import type { CSSProperties, RefObject } from "react"; import { useMemo, useRef } from "react"; import { Box } from "@mantine/core"; @@ -11,19 +11,22 @@ import type { GridItemHTMLElement, GridStack as GridStackInstance } from "@homar import { BoardItemContent } from "../items/item-content"; import { SectionProvider } from "../sections/section-context"; import classes from "./mobile-board.module.css"; -import { createMobileBoardItems } from "./mobile-layout"; +import { createMobileBoardItems, mobileColumnCount } from "./mobile-layout"; export const MobileBoard = () => { const board = useRequiredBoard(); const desktopLayout = getDesktopLayout(board); const items = useMemo(() => createMobileBoardItems(board, desktopLayout.id), [board, desktopLayout.id]); - const rootSection = board.sections.find((section) => section.kind !== "dynamic"); + const rootSection = board.sections.find((section) => section.kind !== "dynamic") ?? { + id: "mobile", + kind: "empty" as const, + xOffset: 0, + yOffset: 0, + }; const wrapperRef = useRef(null); const itemRefs = useRef>>({}); const gridstackRef = useRef(null); - if (!rootSection) return null; - return ( { refs: { wrapper: wrapperRef, items: itemRefs, gridstack: gridstackRef }, }} > - + {items.map((item) => ( useMediaQuery(mobileBoardMediaQuery); diff --git a/apps/nextjs/src/components/board/use-mobile-board.tsx b/apps/nextjs/src/components/board/use-mobile-board.tsx new file mode 100644 index 000000000..84eea8508 --- /dev/null +++ b/apps/nextjs/src/components/board/use-mobile-board.tsx @@ -0,0 +1,21 @@ +"use client"; + +import type { PropsWithChildren } from "react"; +import { createContext, useContext } from "react"; +import { useMediaQuery } from "@mantine/hooks"; + +export const mobileBoardMediaQuery = "(max-width: 48em)"; + +const InitialMobileBoardContext = createContext(undefined); + +export const MobileBoardViewportProvider = ({ + initialIsMobile, + children, +}: PropsWithChildren<{ initialIsMobile: boolean }>) => ( + {children} +); + +export const useIsMobileBoard = () => { + const initialIsMobile = useContext(InitialMobileBoardContext); + return useMediaQuery(mobileBoardMediaQuery, initialIsMobile, { getInitialValueInEffect: true }); +};