fix: right-click apps, board keyboard shortcuts, scrollbar oscillation, Beszel JSON errors
- #6416: Skip widget context menu for app widgets (pass through native right-click) - #6392: Add board keyboard shortcuts (mod+shift+arrows to cycle, mod+shift+1-9 for direct) - #6080: Prevent GridStack scrollbar oscillation by thresholding resize events - #6024: Add try-catch for Beszel response.json() calls in auth and testing paths
This commit is contained in:
8 files changed
+144
-4
No files matched your search
@@ -0,0 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { useBoardHotkeys } from "~/components/board/use-board-hotkeys";
|
||||
|
||||
export const BoardHotkeys = () => {
|
||||
useBoardHotkeys();
|
||||
return null;
|
||||
};
|
||||
@@ -18,6 +18,7 @@ import type { Params } from "./(content)/_creator";
|
||||
import { CustomCss } from "./(content)/_custom-css";
|
||||
import { BoardReadyProvider } from "./(content)/_ready-context";
|
||||
import { BoardMantineProvider } from "./(content)/_theme";
|
||||
import { BoardHotkeys } from "./_board-hotkeys";
|
||||
|
||||
const logger = createLogger({ module: "createBoardLayout" });
|
||||
|
||||
@@ -69,6 +70,7 @@ export const createBoardLayout = <TParams extends Params>({
|
||||
<EditModeProvider>
|
||||
<BoardMantineProvider defaultColorScheme={colorScheme}>
|
||||
<CustomCss />
|
||||
<BoardHotkeys />
|
||||
<BoardTourWrapper hasSession={withTour && !!session}>
|
||||
<ClientShell hasNavigation={false}>
|
||||
<MainHeader
|
||||
|
||||
@@ -170,6 +170,7 @@ export const WidgetContextMenu = ({ item, widgetStateRef, children }: WidgetCont
|
||||
|
||||
if (!session) return <>{children}</>;
|
||||
if (!isRightClickEnabled) return <>{children}</>;
|
||||
if (item.kind === "app") return <>{children}</>;
|
||||
|
||||
const visibleWidgetActions = widgetContextActions.filter((a) => !a.hidden);
|
||||
|
||||
|
||||
@@ -319,9 +319,24 @@ const useCssVariableConfiguration = ({
|
||||
columnCount,
|
||||
isDynamic,
|
||||
}: UseCssVariableConfiguration) => {
|
||||
const prevWidthRef = useRef<number | null>(null);
|
||||
|
||||
const onResize = useCallback(() => {
|
||||
if (!wrapperRef.current) return;
|
||||
if (!gridRef.current) return;
|
||||
|
||||
const currentWidth = wrapperRef.current.clientWidth;
|
||||
const prevWidth = prevWidthRef.current;
|
||||
|
||||
// Only recalculate if the width change is significant enough (> 20px)
|
||||
// This prevents infinite feedback loops when the vertical scrollbar
|
||||
// appears/disappears, causing clientWidth to oscillate by ~15px
|
||||
if (prevWidth !== null && Math.abs(currentWidth - prevWidth) < 20) {
|
||||
return;
|
||||
}
|
||||
|
||||
prevWidthRef.current = currentWidth;
|
||||
|
||||
handleResizeChange(
|
||||
wrapperRef.current,
|
||||
gridRef.current,
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
import { useRequiredBoard } from "@homarr/boards/context";
|
||||
import { hotkeys } from "@homarr/definitions";
|
||||
import { useHotkeys } from "@mantine/hooks";
|
||||
|
||||
export const useBoardHotkeys = () => {
|
||||
const router = useRouter();
|
||||
const currentBoard = useRequiredBoard();
|
||||
const { data: boards = [] } = clientApi.board.getAllBoards.useQuery();
|
||||
|
||||
const navigateToBoard = useCallback(
|
||||
(boardName: string) => {
|
||||
if (boardName !== currentBoard.name) {
|
||||
router.push(`/boards/${boardName}`);
|
||||
}
|
||||
},
|
||||
[router, currentBoard.name],
|
||||
);
|
||||
|
||||
const currentIndex = boards.findIndex((board) => board.id === currentBoard.id);
|
||||
|
||||
useHotkeys([
|
||||
[hotkeys.nextBoard, () => navigateToNextBoard(boards, currentIndex, navigateToBoard)],
|
||||
[hotkeys.previousBoard, () => navigateToPreviousBoard(boards, currentIndex, navigateToBoard)],
|
||||
[hotkeys.switchBoard1, () => navigateToBoardByIndex(boards, 0, navigateToBoard)],
|
||||
[hotkeys.switchBoard2, () => navigateToBoardByIndex(boards, 1, navigateToBoard)],
|
||||
[hotkeys.switchBoard3, () => navigateToBoardByIndex(boards, 2, navigateToBoard)],
|
||||
[hotkeys.switchBoard4, () => navigateToBoardByIndex(boards, 3, navigateToBoard)],
|
||||
[hotkeys.switchBoard5, () => navigateToBoardByIndex(boards, 4, navigateToBoard)],
|
||||
[hotkeys.switchBoard6, () => navigateToBoardByIndex(boards, 5, navigateToBoard)],
|
||||
[hotkeys.switchBoard7, () => navigateToBoardByIndex(boards, 6, navigateToBoard)],
|
||||
[hotkeys.switchBoard8, () => navigateToBoardByIndex(boards, 7, navigateToBoard)],
|
||||
[hotkeys.switchBoard9, () => navigateToBoardByIndex(boards, 8, navigateToBoard)],
|
||||
]);
|
||||
};
|
||||
|
||||
const navigateToNextBoard = (
|
||||
boards: { name: string }[],
|
||||
currentIndex: number,
|
||||
navigate: (name: string) => void,
|
||||
) => {
|
||||
if (boards.length === 0) return;
|
||||
const nextIndex = (currentIndex + 1) % boards.length;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
navigate(boards[nextIndex]!.name);
|
||||
};
|
||||
|
||||
const navigateToPreviousBoard = (
|
||||
boards: { name: string }[],
|
||||
currentIndex: number,
|
||||
navigate: (name: string) => void,
|
||||
) => {
|
||||
if (boards.length === 0) return;
|
||||
const previousIndex = (currentIndex - 1 + boards.length) % boards.length;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
navigate(boards[previousIndex]!.name);
|
||||
};
|
||||
|
||||
const navigateToBoardByIndex = (
|
||||
boards: { name: string }[],
|
||||
index: number,
|
||||
navigate: (name: string) => void,
|
||||
) => {
|
||||
if (index < boards.length) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
navigate(boards[index]!.name);
|
||||
}
|
||||
};
|
||||
Reference in new issue
Block a user