129 lines
3.7 KiB
TypeScript
129 lines
3.7 KiB
TypeScript
// 레거시 레이아웃 로더
|
|
// DB에 저장된 V5(12칸) 좌표를 현재 블록 좌표로 변환한다.
|
|
// DB 데이터는 건드리지 않고, 로드 시 메모리에서만 변환.
|
|
|
|
import {
|
|
PopGridPosition,
|
|
PopLayoutData,
|
|
BLOCK_SIZE,
|
|
BLOCK_GAP,
|
|
BLOCK_PADDING,
|
|
getBlockColumns,
|
|
} from "../types/pop-layout";
|
|
|
|
const LEGACY_COLUMNS = 12;
|
|
const LEGACY_ROW_HEIGHT = 48;
|
|
const LEGACY_GAP = 16;
|
|
const DESIGN_WIDTH = 1024;
|
|
|
|
function isLegacyGridConfig(layout: PopLayoutData): boolean {
|
|
if (layout.gridConfig?.rowHeight === BLOCK_SIZE) return false;
|
|
|
|
const maxCol = Object.values(layout.components).reduce((max, comp) => {
|
|
const end = comp.position.col + comp.position.colSpan - 1;
|
|
return Math.max(max, end);
|
|
}, 0);
|
|
|
|
return maxCol <= LEGACY_COLUMNS;
|
|
}
|
|
|
|
function convertLegacyPosition(
|
|
pos: PopGridPosition,
|
|
targetColumns: number,
|
|
): PopGridPosition {
|
|
const colRatio = targetColumns / LEGACY_COLUMNS;
|
|
const rowRatio = (LEGACY_ROW_HEIGHT + LEGACY_GAP) / (BLOCK_SIZE + BLOCK_GAP);
|
|
|
|
const newCol = Math.max(1, Math.round((pos.col - 1) * colRatio) + 1);
|
|
let newColSpan = Math.max(1, Math.round(pos.colSpan * colRatio));
|
|
const newRowSpan = Math.max(1, Math.round(pos.rowSpan * rowRatio));
|
|
|
|
if (newCol + newColSpan - 1 > targetColumns) {
|
|
newColSpan = targetColumns - newCol + 1;
|
|
}
|
|
|
|
return { col: newCol, row: pos.row, colSpan: newColSpan, rowSpan: newRowSpan };
|
|
}
|
|
|
|
const BLOCK_GRID_CONFIG = {
|
|
rowHeight: BLOCK_SIZE,
|
|
gap: BLOCK_GAP,
|
|
padding: BLOCK_PADDING,
|
|
};
|
|
|
|
/**
|
|
* DB에서 로드한 레이아웃을 현재 블록 좌표로 변환한다.
|
|
*
|
|
* - 12칸 레거시 좌표 → 블록 좌표 변환
|
|
* - 이미 블록 좌표인 경우 → gridConfig만 보정
|
|
* - 구 모드별 overrides는 항상 제거 (리플로우가 대체)
|
|
*/
|
|
export function loadLegacyLayout(layout: PopLayoutData): PopLayoutData {
|
|
if (!isLegacyGridConfig(layout)) {
|
|
return {
|
|
...layout,
|
|
gridConfig: BLOCK_GRID_CONFIG,
|
|
overrides: undefined,
|
|
};
|
|
}
|
|
|
|
const blockColumns = getBlockColumns(DESIGN_WIDTH);
|
|
|
|
const rowGroups: Record<number, string[]> = {};
|
|
Object.entries(layout.components).forEach(([id, comp]) => {
|
|
const r = comp.position.row;
|
|
if (!rowGroups[r]) rowGroups[r] = [];
|
|
rowGroups[r].push(id);
|
|
});
|
|
|
|
const convertedPositions: Record<string, PopGridPosition> = {};
|
|
Object.entries(layout.components).forEach(([id, comp]) => {
|
|
convertedPositions[id] = convertLegacyPosition(comp.position, blockColumns);
|
|
});
|
|
|
|
const sortedRows = Object.keys(rowGroups).map(Number).sort((a, b) => a - b);
|
|
const rowMapping: Record<number, number> = {};
|
|
let currentRow = 1;
|
|
for (const legacyRow of sortedRows) {
|
|
rowMapping[legacyRow] = currentRow;
|
|
const maxSpan = Math.max(
|
|
...rowGroups[legacyRow].map(id => convertedPositions[id].rowSpan)
|
|
);
|
|
currentRow += maxSpan;
|
|
}
|
|
|
|
const newComponents = { ...layout.components };
|
|
Object.entries(newComponents).forEach(([id, comp]) => {
|
|
const converted = convertedPositions[id];
|
|
const mappedRow = rowMapping[comp.position.row] ?? converted.row;
|
|
newComponents[id] = {
|
|
...comp,
|
|
position: { ...converted, row: mappedRow },
|
|
};
|
|
});
|
|
|
|
const newModals = layout.modals?.map(modal => {
|
|
const modalComps = { ...modal.components };
|
|
Object.entries(modalComps).forEach(([id, comp]) => {
|
|
modalComps[id] = {
|
|
...comp,
|
|
position: convertLegacyPosition(comp.position, blockColumns),
|
|
};
|
|
});
|
|
return {
|
|
...modal,
|
|
gridConfig: BLOCK_GRID_CONFIG,
|
|
components: modalComps,
|
|
overrides: undefined,
|
|
};
|
|
});
|
|
|
|
return {
|
|
...layout,
|
|
gridConfig: BLOCK_GRID_CONFIG,
|
|
components: newComponents,
|
|
overrides: undefined,
|
|
modals: newModals,
|
|
};
|
|
}
|