From d0cd310d6e80b7a2f3046a032c5f186764568486 Mon Sep 17 00:00:00 2001 From: u8array Date: Mon, 11 May 2026 23:02:32 +0200 Subject: [PATCH 1/2] feat: Add ZPL import append mode Introduces an "append mode" for ZPL imports, allowing users to add imported pages to an existing design without overwriting it. This includes a new toggle and corresponding locale keys. --- src/components/Output/ZplImportModal.tsx | 63 ++++++++++++++++++------ src/locales/ar.ts | 2 + src/locales/bg.ts | 2 + src/locales/cs.ts | 2 + src/locales/da.ts | 2 + src/locales/de.ts | 2 + src/locales/el.ts | 2 + src/locales/en.ts | 2 + src/locales/es.ts | 2 + src/locales/et.ts | 2 + src/locales/fa.ts | 2 + src/locales/fi.ts | 2 + src/locales/fr.ts | 2 + src/locales/he.ts | 2 + src/locales/hr.ts | 2 + src/locales/hu.ts | 2 + src/locales/it.ts | 2 + src/locales/ja.ts | 2 + src/locales/ko.ts | 2 + src/locales/lt.ts | 2 + src/locales/lv.ts | 2 + src/locales/nl.ts | 2 + src/locales/no.ts | 2 + src/locales/pl.ts | 2 + src/locales/pt.ts | 2 + src/locales/ro.ts | 2 + src/locales/sk.ts | 2 + src/locales/sl.ts | 2 + src/locales/sr.ts | 2 + src/locales/sv.ts | 2 + src/locales/tr.ts | 2 + src/locales/zh-hans.ts | 2 + src/locales/zh-hant.ts | 2 + src/store/labelStore.test.ts | 33 +++++++++++++ src/store/labelStore.ts | 16 ++++++ 35 files changed, 162 insertions(+), 14 deletions(-) diff --git a/src/components/Output/ZplImportModal.tsx b/src/components/Output/ZplImportModal.tsx index 67e77935..c9ad69b8 100644 --- a/src/components/Output/ZplImportModal.tsx +++ b/src/components/Output/ZplImportModal.tsx @@ -2,7 +2,8 @@ import { useRef, useState } from 'react'; import { XMarkIcon, ClipboardDocumentIcon, CheckIcon, FolderOpenIcon } from '@heroicons/react/16/solid'; import { importZplText } from '../../lib/zplImportService'; import { readFileAsText } from '../../lib/readFile'; -import { useLabelStore } from '../../store/labelStore'; +import { useLabelStore, type Page } from '../../store/labelStore'; +import type { LabelConfig } from '../../types/ObjectType'; import { formatReportAsText, type ImportResult } from '../../lib/importReport'; import { ImportSummaryBody } from './ImportReportModal'; import { useT } from '../../lib/useT'; @@ -18,9 +19,30 @@ export function ZplImportModal({ onClose }: Props) { const [error, setError] = useState(null); const [result, setResult] = useState(null); const [copied, setCopied] = useState(false); + const [appendMode, setAppendMode] = useState(false); const fileInputRef = useRef(null); const loadDesign = useLabelStore((s) => s.loadDesign); + const appendPages = useLabelStore((s) => s.appendPages); const label = useLabelStore((s) => s.label); + const pages = useLabelStore((s) => s.pages); + + // Append-mode only makes sense when there is something to append *to*. + // On a fresh designer (one empty page) we hide the toggle entirely + // because the resulting [empty, imported] state would just be clutter + // the user has to clean up manually. + const hasExistingContent = + pages.length > 1 || (pages[0]?.objects.length ?? 0) > 0; + + const applyImport = (labelConfig: Partial, importedPages: Page[]) => { + if (appendMode && hasExistingContent) { + // Keep the current label config — the user opted to keep the + // existing design's dimensions, so any imported ^PW/^LL is + // intentionally discarded. + appendPages(importedPages); + } else { + loadDesign({ ...label, ...labelConfig }, importedPages); + } + }; const handleImport = () => { setError(null); @@ -29,15 +51,15 @@ export function ZplImportModal({ onClose }: Props) { return; } - const { labelConfig, pages, report } = importZplText(zpl, label.dpmm); - const totalObjects = pages.reduce((s, p) => s + p.objects.length, 0); + const { labelConfig, pages: importedPages, report } = importZplText(zpl, label.dpmm); + const totalObjects = importedPages.reduce((s, p) => s + p.objects.length, 0); if (totalObjects === 0 && Object.keys(labelConfig).length === 0) { setError('No supported objects found in the ZPL code.'); return; } - loadDesign({ ...label, ...labelConfig }, pages); + applyImport(labelConfig, importedPages); setResult({ objectCount: totalObjects, report }); }; @@ -60,9 +82,9 @@ export function ZplImportModal({ onClose }: Props) { return; } - const { labelConfig, pages, report } = importZplText(text, label.dpmm); - const totalObjects = pages.reduce((s, p) => s + p.objects.length, 0); - loadDesign({ ...label, ...labelConfig }, pages); + const { labelConfig, pages: importedPages, report } = importZplText(text, label.dpmm); + const totalObjects = importedPages.reduce((s, p) => s + p.objects.length, 0); + applyImport(labelConfig, importedPages); setResult({ objectCount: totalObjects, report }); }; @@ -142,13 +164,26 @@ export function ZplImportModal({ onClose }: Props) {
- +
+ + {hasExistingContent && ( + + )} +