Fix foldable background layout

This commit is contained in:
Codex Agent
2026-01-24 10:41:24 +01:00
parent 6c83f4ee4e
commit 0f4d7450ff
4 changed files with 201 additions and 48 deletions

View File

@@ -495,11 +495,11 @@ function resolveSlots(layout: EventQrInviteLayout | null, isFoldable: boolean, o
const baseSlots = isFoldable
? {
headline: { x: 0.08, y: 0.15, w: 0.84, fontSize: 50, fontWeight: 800, fontFamily: DEFAULT_DISPLAY_FONT, align: 'center' as const },
subtitle: { x: 0.1, y: 0.21, w: 0.8, fontSize: 37, fontWeight: 600, fontFamily: DEFAULT_BODY_FONT, align: 'center' as const },
description: { x: 0.1, y: 0.66, w: 0.8, fontSize: 13, fontFamily: DEFAULT_BODY_FONT, lineHeight: 1.4, align: 'center' as const },
instructions: { x: 0.12, y: 0.36, w: 0.76, fontSize: 13, fontFamily: DEFAULT_BODY_FONT, lineHeight: 1.3 },
qr: { x: 0.3, y: 0.3, w: 0.28 },
headline: { x: 0.08, y: 0.24, w: 0.84, fontSize: 50, fontWeight: 800, fontFamily: DEFAULT_DISPLAY_FONT, align: 'center' as const },
subtitle: { x: 0.1, y: 0.28, w: 0.8, fontSize: 37, fontWeight: 600, fontFamily: DEFAULT_BODY_FONT, align: 'center' as const },
description: { x: 0.42, y: 0.6, w: 0.58, fontSize: 23, fontFamily: DEFAULT_BODY_FONT, lineHeight: 1.4, align: 'left' as const },
instructions: { x: 0.42, y: 0.42, w: 0.58, fontSize: 15, fontFamily: DEFAULT_BODY_FONT, lineHeight: 1.3, align: 'left' as const },
qr: { x: 0, y: 0.3, w: 0.26 },
}
: getDefaultSlots();
@@ -539,6 +539,8 @@ function buildFabricOptions({
qrPngUrl,
baseWidth = CANVAS_WIDTH,
baseHeight = CANVAS_HEIGHT,
renderWidth = CANVAS_WIDTH,
renderHeight = CANVAS_HEIGHT,
slotOverrides = {},
}: {
layout: EventQrInviteLayout | null;
@@ -551,10 +553,12 @@ function buildFabricOptions({
qrPngUrl?: string | null;
baseWidth?: number;
baseHeight?: number;
renderWidth?: number;
renderHeight?: number;
slotOverrides?: SlotOverrides;
}) {
const scaleX = CANVAS_WIDTH / baseWidth;
const scaleY = CANVAS_HEIGHT / baseHeight;
const scaleX = renderWidth / baseWidth;
const scaleY = renderHeight / baseHeight;
const panelWidth = isFoldable ? baseWidth / 2 : baseWidth;
const panelHeight = baseHeight;
const slots = resolveSlots(layout, isFoldable, slotOverrides);
@@ -563,20 +567,20 @@ function buildFabricOptions({
? [
{
url: backgroundImageUrl,
centerX: (panelWidth / 2) * scaleX,
centerY: (panelHeight / 2) * scaleY,
width: panelWidth * scaleX,
height: panelHeight * scaleY,
rotation: 90,
centerX: (renderWidth / 2) * 0.5,
centerY: renderHeight / 2,
width: renderWidth / 2,
height: renderHeight,
rotation: 0,
mirrored: false,
},
{
url: backgroundImageUrl,
centerX: (panelWidth + panelWidth / 2) * scaleX,
centerY: (panelHeight / 2) * scaleY,
width: panelWidth * scaleX,
height: panelHeight * scaleY,
rotation: -90,
centerX: (renderWidth / 2) * 1.5,
centerY: renderHeight / 2,
width: renderWidth / 2,
height: renderHeight,
rotation: 0,
mirrored: true,
},
]
@@ -706,6 +710,8 @@ function buildFabricOptions({
backgroundGradient,
backgroundImageUrl: backgroundPanels ? null : backgroundImageUrl,
backgroundImagePanels: backgroundPanels ?? undefined,
canvasWidth: renderWidth,
canvasHeight: renderHeight,
readOnly: true,
} as const;
}
@@ -1093,6 +1099,13 @@ function PreviewStep({
const resolvedBgSolid = backgroundSolid ?? layout?.preview?.background ?? null;
const backgroundImageUrl = presetSrc ?? null;
const canvasBase = React.useMemo(() => resolveCanvasBase(layout, isFoldable), [layout, isFoldable]);
const renderCanvas = React.useMemo(
() => ({
width: isFoldable ? CANVAS_HEIGHT : CANVAS_WIDTH,
height: isFoldable ? CANVAS_WIDTH : CANVAS_HEIGHT,
}),
[isFoldable],
);
const resolvedSlots = React.useMemo(() => resolveSlots(layout, isFoldable, slotOverrides), [isFoldable, layout, slotOverrides]);
const exportOptions = React.useMemo(() => {
return buildFabricOptions({
@@ -1106,9 +1119,25 @@ function PreviewStep({
qrPngUrl,
baseWidth: canvasBase.width,
baseHeight: canvasBase.height,
renderWidth: renderCanvas.width,
renderHeight: renderCanvas.height,
slotOverrides,
});
}, [backgroundImageUrl, canvasBase.height, canvasBase.width, isFoldable, layout, qrPngUrl, qrUrl, resolvedBgGradient, resolvedBgSolid, slotOverrides, textFields]);
}, [
backgroundImageUrl,
canvasBase.height,
canvasBase.width,
isFoldable,
layout,
qrPngUrl,
qrUrl,
renderCanvas.height,
renderCanvas.width,
resolvedBgGradient,
resolvedBgSolid,
slotOverrides,
textFields,
]);
const [previewUrl, setPreviewUrl] = React.useState<string | null>(null);
const [previewLoading, setPreviewLoading] = React.useState(false);