From ff514b2c3857fdb35cbb442320db66dfda2f1331 Mon Sep 17 00:00:00 2001 From: Donkie Date: Sun, 13 Sep 2026 10:55:12 +0200 Subject: [PATCH] fix(labels): let the print dialog pick sheet orientation, clamp migrated margins Two more problems from #1149. Sheet mode set @page size to the paper's exact dimensions. A 62x34 page makes the browser send it as landscape, and Chromium hides the orientation picker when the page CSS sets a size. Label printer drivers disagree on which way round a roll is: a Brother QL needed landscape, a Niimbot B1 needed portrait, so any fixed choice prints rotated for someone. Sheet mode now uses size: auto like v1 did, and the page is still laid out in mm. Label mode keeps its exact size. The v1 migration derived the label size from the raw margins. v1 users paired -20mm margins with a 1.5mm printer margin to pull an oversized cell back onto a 62x34 page, which migrated as a 102x74 label. Margins are now clamped at migration; the safe-zone alone gives the same content inset (max(safe, margin) in both versions), and the label comes out at the paper size. --- client_v2/src/lib/labels/migrateV1.test.ts | 20 ++++++++++++++++++++ client_v2/src/lib/labels/migrateV1.ts | 11 +++++++---- client_v2/src/lib/labels/print.ts | 6 ++++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/client_v2/src/lib/labels/migrateV1.test.ts b/client_v2/src/lib/labels/migrateV1.test.ts index 77eca7dd..21258fb7 100644 --- a/client_v2/src/lib/labels/migrateV1.test.ts +++ b/client_v2/src/lib/labels/migrateV1.test.ts @@ -140,6 +140,26 @@ describe('presetToDesign', () => { expect(d.layout.columns).toBeGreaterThanOrEqual(1); }); + it('clamps v1 negative margins so the label matches the paper (#1149)', () => { + // A real preset: -20mm margins with a 1.5mm printer margin on a 62x34 roll. + // Carried over raw, the derived label came out 102x74. + const d = presetToDesign({ + labelSettings: { + printSettings: { + paperSize: 'custom', + customPaperSize: { width: 62, height: 34 }, + columns: 1, + rows: 1, + margin: { top: -20, bottom: -20, left: -20, right: -20 }, + printerMargin: { top: 1.5, bottom: 1.5, left: 1.5, right: 1.5 } + } + } + }); + expect(d.layout.margin).toEqual({ t: 0, b: 0, l: 0, r: 0 }); + expect(d.layout.safe).toEqual({ t: 1.5, b: 1.5, l: 1.5, r: 1.5 }); + expect(d.label).toEqual({ w: 62, h: 34 }); + }); + it('omits the QR element when v1 had the QR turned off', () => { const d = presetToDesign({ labelSettings: { showQRCodeMode: 'no' } }); expect(d.elements.some((e) => e.type === 'qr')).toBe(false); diff --git a/client_v2/src/lib/labels/migrateV1.ts b/client_v2/src/lib/labels/migrateV1.ts index 8ac7d59d..3de77bdb 100644 --- a/client_v2/src/lib/labels/migrateV1.ts +++ b/client_v2/src/lib/labels/migrateV1.ts @@ -133,11 +133,14 @@ function mapLayout(ps: V1PrintSettings): PrintLayout { paper, custom, landscape: false, + // v1 users paired negative margins with a printer margin to pull an oversized + // grid cell back onto a label-sized page. Clamped, the safe-zone alone gives the + // same inset and the label is sized to the paper instead of that cell (#1149). margin: { - t: ps.margin?.top ?? DEFAULT_LAYOUT.margin.t, - b: ps.margin?.bottom ?? DEFAULT_LAYOUT.margin.b, - l: ps.margin?.left ?? DEFAULT_LAYOUT.margin.l, - r: ps.margin?.right ?? DEFAULT_LAYOUT.margin.r + t: Math.max(0, ps.margin?.top ?? DEFAULT_LAYOUT.margin.t), + b: Math.max(0, ps.margin?.bottom ?? DEFAULT_LAYOUT.margin.b), + l: Math.max(0, ps.margin?.left ?? DEFAULT_LAYOUT.margin.l), + r: Math.max(0, ps.margin?.right ?? DEFAULT_LAYOUT.margin.r) }, safe: { t: ps.printerMargin?.top ?? 0, diff --git a/client_v2/src/lib/labels/print.ts b/client_v2/src/lib/labels/print.ts index efe74a22..1c30eebd 100644 --- a/client_v2/src/lib/labels/print.ts +++ b/client_v2/src/lib/labels/print.ts @@ -141,8 +141,10 @@ export async function printLabels({ design, bindings, layout, baseUrl }: PrintJo style.textContent = pageCss(`${design.label.w}mm ${design.label.h}mm`); } else { buildSheetPages(root, items, design, layout); - const page = paperSize(layout); - style.textContent = pageCss(`${page.w}mm ${page.h}mm`); + // `size: auto`, as v1 did. A fixed size makes the browser pick the orientation + // and (in Chromium) hide the picker, and label printer drivers disagree on which + // way round a roll is, so any fixed choice prints rotated for someone (#1149). + style.textContent = pageCss('auto'); } document.body.appendChild(style);