fix: finish widget modernization audit
This commit is contained in:
1 parent
bbcfc505bc
commit
747ccdfa9e
27 files changed
+340
-115
No files matched your search
@@ -4,6 +4,7 @@ import { notFound, redirect } from "next/navigation";
|
||||
import { AppShellMain } from "@mantine/core";
|
||||
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";
|
||||
@@ -14,7 +15,8 @@ import { ModalProvider } from "@homarr/modals";
|
||||
import { MainHeader } from "~/components/layout/header";
|
||||
import { BoardLogoWithTitle } from "~/components/layout/logo/board-logo";
|
||||
import { ClientShell } from "~/components/layout/shell";
|
||||
import { BoardTourProvider } from "~/components/onboarding/board-tour";
|
||||
import { BoardTourGate } from "~/components/onboarding/board-tour-gate";
|
||||
import { env } from "~/env";
|
||||
import { getCurrentColorSchemeAsync } from "~/theme/color-scheme";
|
||||
import type { Board } from "./_types";
|
||||
import type { Params } from "./(content)/_creator";
|
||||
@@ -24,11 +26,6 @@ import { BoardMantineProvider } from "./(content)/_theme";
|
||||
|
||||
const logger = createLogger({ module: "createBoardLayout" });
|
||||
|
||||
const BoardTourWrapper = ({ hasSession, children }: PropsWithChildren<{ hasSession: boolean }>) => {
|
||||
if (!hasSession) return <>{children}</>;
|
||||
return <BoardTourProvider>{children}</BoardTourProvider>;
|
||||
};
|
||||
|
||||
interface CreateBoardLayoutProps<TParams extends Params> {
|
||||
headerActions: JSX.Element;
|
||||
getInitialBoardAsync: (params: TParams) => Promise<Board>;
|
||||
@@ -46,8 +43,34 @@ export const createBoardLayout = <TParams extends Params>({
|
||||
}: PropsWithChildren<{
|
||||
params: Promise<TParams>;
|
||||
}>) => {
|
||||
const session = await auth();
|
||||
const initialBoard = await getInitialBoard(await params).catch((error) => {
|
||||
const resolvedParams = await params;
|
||||
const sessionPromise = auth();
|
||||
const initialBoardPromise = getInitialBoard(resolvedParams).then(
|
||||
(board) => ({ status: "fulfilled", board }) as const,
|
||||
(error: unknown) => ({ status: "rejected", error }) as const,
|
||||
);
|
||||
const colorSchemePromise = getCurrentColorSchemeAsync();
|
||||
const initialViewportWidthPromise = getInitialViewportWidthAsync();
|
||||
const shouldRunBoardTourPromise = sessionPromise.then(async (session) => {
|
||||
if (!withTour || !session || env.DEMO_MODE) return false;
|
||||
|
||||
try {
|
||||
const user = await getRscUserSettingsAsync(session.user.id);
|
||||
return user !== undefined && !user.completedBoardTour;
|
||||
} catch (error) {
|
||||
logger.error(new Error("Failed to load the board tour status", { cause: error }));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
const [session, initialBoardResult, colorScheme, shouldRunBoardTour, initialViewportWidth] = await Promise.all([
|
||||
sessionPromise,
|
||||
initialBoardPromise,
|
||||
colorSchemePromise,
|
||||
shouldRunBoardTourPromise,
|
||||
initialViewportWidthPromise,
|
||||
]);
|
||||
if (initialBoardResult.status === "rejected") {
|
||||
const { error } = initialBoardResult;
|
||||
if (error instanceof TRPCError && error.code === "NOT_FOUND") {
|
||||
if (!session) {
|
||||
logger.debug("No home board found for anonymous user, redirecting to login");
|
||||
@@ -63,9 +86,8 @@ export const createBoardLayout = <TParams extends Params>({
|
||||
}
|
||||
|
||||
throw error;
|
||||
});
|
||||
const colorScheme = await getCurrentColorSchemeAsync();
|
||||
const initialViewportWidth = await getInitialViewportWidthAsync();
|
||||
}
|
||||
const initialBoard = initialBoardResult.board;
|
||||
const initialLayoutId = getLayoutIdForViewportWidth(initialBoard.layouts, initialViewportWidth);
|
||||
|
||||
return (
|
||||
@@ -79,16 +101,16 @@ export const createBoardLayout = <TParams extends Params>({
|
||||
<BoardMantineProvider defaultColorScheme={colorScheme}>
|
||||
<ModalProvider>
|
||||
<CustomCss />
|
||||
<BoardTourWrapper hasSession={withTour && !!session}>
|
||||
<BoardTourGate enabled={shouldRunBoardTour}>
|
||||
<ClientShell hasNavigation={false}>
|
||||
<MainHeader
|
||||
logo={<BoardLogoWithTitle size="md" hideTitleOnMobile />}
|
||||
actions={headerActions}
|
||||
hasNavigation={false}
|
||||
/>
|
||||
<AppShellMain>{children}</AppShellMain>
|
||||
<AppShellMain data-advanced-focus-background>{children}</AppShellMain>
|
||||
</ClientShell>
|
||||
</BoardTourWrapper>
|
||||
</BoardTourGate>
|
||||
</ModalProvider>
|
||||
</BoardMantineProvider>
|
||||
</EditModeProvider>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
.surfaceHostAdvanced {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: calc(var(--mantine-z-index-modal) - 1);
|
||||
z-index: var(--homarr-z-index-widget-focus);
|
||||
width: auto;
|
||||
height: auto;
|
||||
pointer-events: none;
|
||||
|
||||
@@ -229,6 +229,19 @@ export const BoardAdvancedFocusProvider = ({ children }: PropsWithChildren) => {
|
||||
if (isEditMode && activeRef.current) close(false);
|
||||
}, [close, isEditMode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (active?.activation !== "manual") return;
|
||||
const background = document.querySelectorAll<HTMLElement>("[data-advanced-focus-background]");
|
||||
background.forEach((element) => {
|
||||
element.inert = true;
|
||||
});
|
||||
return () => {
|
||||
background.forEach((element) => {
|
||||
element.inert = false;
|
||||
});
|
||||
};
|
||||
}, [active?.activation]);
|
||||
|
||||
const value = useMemo(
|
||||
() => ({ active, open, close, dismiss, hover, leave }),
|
||||
[active, close, dismiss, hover, leave, open],
|
||||
@@ -244,7 +257,7 @@ export const BoardAdvancedFocusProvider = ({ children }: PropsWithChildren) => {
|
||||
data-advanced-focus-overlay
|
||||
backgroundOpacity={0.38}
|
||||
blur={0}
|
||||
zIndex="calc(var(--mantine-z-index-modal) - 2)"
|
||||
zIndex="var(--homarr-z-index-widget-preview-backdrop)"
|
||||
className={`${classes.backdrop} ${active.phase === "closing" ? classes.backdropClosing : ""}`}
|
||||
aria-hidden
|
||||
/>
|
||||
|
||||
@@ -59,7 +59,7 @@ export const AdvancedFocusManualSurface = ({
|
||||
radius={radius}
|
||||
padding={0}
|
||||
shadow="none"
|
||||
zIndex="calc(var(--mantine-z-index-modal) - 1)"
|
||||
zIndex="var(--homarr-z-index-widget-focus)"
|
||||
closeOnEscape={false}
|
||||
closeOnClickOutside
|
||||
lockScroll
|
||||
|
||||
@@ -18,7 +18,13 @@ interface Props {
|
||||
|
||||
export const MainHeader = ({ logo, actions, hasNavigation = true }: Props) => {
|
||||
return (
|
||||
<AppShellHeader maw="100vw" zIndex={201} style={{ overflowX: "hidden" }} data-app-shell-header>
|
||||
<AppShellHeader
|
||||
maw="100vw"
|
||||
zIndex="var(--homarr-z-index-board-header)"
|
||||
style={{ overflowX: "hidden" }}
|
||||
data-advanced-focus-background
|
||||
data-app-shell-header
|
||||
>
|
||||
<Group h="100%" gap="xl" px="md" justify="apart" wrap="nowrap">
|
||||
<Group h="100%" align="center" style={{ flex: 1 }} wrap="nowrap">
|
||||
{hasNavigation && <ClientBurger />}
|
||||
|
||||
Reference in new issue
Block a user