import { logger } from "@homarr/log"; import type { BoardSize, OldmarrApp, OldmarrConfig, OldmarrWidget, SizedShape } from "@homarr/old-schema"; import { boardSizes } from "@homarr/old-schema"; import type { GridAlgorithmItem } from "../../../api/src/router/board/grid-algorithm"; import { generateResponsiveGridFor } from "../../../api/src/router/board/grid-algorithm"; import { mapColumnCount } from "../mappers/map-column-count"; import { mapApp, mapWidget } from "../mappers/map-item"; export const prepareItems = ( { apps, widgets, settings }: Pick, appsMap: Map, sectionMap: Map, layoutMap: Record, boardId: string, ) => { let localApps = apps; let localWidgets = widgets; const incompleteSizes = boardSizes.filter((size) => widgets .map((widget) => widget.shape) .concat(apps.map((app) => app.shape)) .some((shape) => !shape[size]), ); if (incompleteSizes.length > 0) { logger.warn( `Found items with incomplete sizes board=${boardId} count=${incompleteSizes.length} sizes=${incompleteSizes.join(", ")}\nHomarr will automatically generate missing sizes`, ); incompleteSizes.forEach((size) => { const columnCount = mapColumnCount(settings.customization.gridstack, size); const previousSize = !incompleteSizes.includes("lg") ? "lg" : incompleteSizes.includes("sm") ? "md" : "sm"; const previousWidth = mapColumnCount(settings.customization.gridstack, previousSize); logger.info(`Generating missing size boardId=${boardId} from=${previousSize} to=${size}`); const items = widgets .map((item) => mapItemForGridAlgorithm(item, previousSize)) .concat(apps.map((item) => mapItemForGridAlgorithm(item, previousSize))); const distinctSectionIds = [...new Set(items.map((item) => item.sectionId))]; distinctSectionIds.forEach((sectionId) => { const { items: newItems } = generateResponsiveGridFor({ items, previousWidth, width: columnCount, sectionId }); localApps = localApps.map((app) => { const item = newItems.find((item) => item.id === app.id); if (!item) return app; return { ...app, shape: { ...app.shape, [size]: mapShapeFromGridAlgorithm(item), }, }; }); localWidgets = localWidgets.map((widget) => { const item = newItems.find((item) => item.id === widget.id); if (!item) return widget; return { ...widget, shape: { ...widget.shape, [size]: mapShapeFromGridAlgorithm(item), }, }; }); }); }); } return localWidgets .map((widget) => mapWidget(widget, appsMap, sectionMap, layoutMap, boardId)) .concat(localApps.map((app) => mapApp(app, appsMap, sectionMap, layoutMap, boardId))) .filter((widget) => widget !== null); }; const mapItemForGridAlgorithm = (item: OldmarrApp | OldmarrWidget, size: BoardSize): GridAlgorithmItem => ({ width: item.shape[size]?.size.width ?? 1, height: item.shape[size]?.size.height ?? 1, xOffset: item.shape[size]?.location.x ?? 0, yOffset: item.shape[size]?.location.y ?? 0, sectionId: item.area.type === "sidebar" ? item.area.properties.location : item.area.properties.id, id: item.id, type: "item", }); const mapShapeFromGridAlgorithm = (item: GridAlgorithmItem) => ({ location: { x: item.xOffset, y: item.yOffset, }, size: { width: item.width, height: item.height, }, }) satisfies SizedShape;