diff --git a/packages/editor/src/components/ui/sidebar/panels/settings-panel/print-export-button.test.ts b/packages/editor/src/components/ui/sidebar/panels/settings-panel/print-export-button.test.ts index 26fedea1b..b6b016e33 100644 --- a/packages/editor/src/components/ui/sidebar/panels/settings-panel/print-export-button.test.ts +++ b/packages/editor/src/components/ui/sidebar/panels/settings-panel/print-export-button.test.ts @@ -40,7 +40,7 @@ describe('simple 3D print export', () => { return artifact } - const prepared = await preparePrintExport(modelExport, true) + const prepared = await preparePrintExport(modelExport, true, 'print-3mf') expect(calls).toEqual([ { @@ -58,6 +58,33 @@ describe('simple 3D print export', () => { expect(prepared).toEqual({ artifact, report }) }) + test('uses the same safe profile for printable STL files', async () => { + const calls: { format?: string; options?: ModelExportOptions }[] = [] + const stlReport: PrintExportReport = { ...report, format: 'stl' } + const artifact = { blob: new Blob(['stl']), filename: 'house.zip', metadata: stlReport } + const modelExport: ModelExport = async (format, options) => { + calls.push({ format, options }) + return artifact + } + + const prepared = await preparePrintExport(modelExport, false, 'print-stl') + + expect(calls).toEqual([ + { + format: 'print-stl', + options: { + onlyVisible: false, + download: false, + printScale: 100, + printScope: 'levels', + printContent: 'structure', + printBase: 'none', + }, + }, + ]) + expect(prepared).toEqual({ artifact, report: stlReport }) + }) + test('blocks the download when preflight finds invalid geometry', async () => { const blockedReport: PrintExportReport = { ...report, @@ -76,7 +103,7 @@ describe('simple 3D print export', () => { metadata: blockedReport, }) - await expect(preparePrintExport(modelExport, true)).rejects.toThrow( + await expect(preparePrintExport(modelExport, true, 'print-3mf')).rejects.toThrow( 'One wall has an open edge.', ) }) @@ -122,7 +149,7 @@ describe('simple 3D print export', () => { metadata: blockedBundleReport, }) - await expect(preparePrintExport(modelExport, true)).rejects.toThrow( + await expect(preparePrintExport(modelExport, true, 'print-3mf')).rejects.toThrow( 'The upper level has an open edge.', ) }) @@ -133,7 +160,7 @@ describe('simple 3D print export', () => { filename: 'house.3mf', }) - await expect(preparePrintExport(modelExport, false)).rejects.toThrow( + await expect(preparePrintExport(modelExport, false, 'print-3mf')).rejects.toThrow( 'did not return a valid file', ) }) diff --git a/packages/editor/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx b/packages/editor/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx index b7298edb5..eb7cd0d8e 100644 --- a/packages/editor/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx +++ b/packages/editor/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx @@ -5,7 +5,11 @@ import { isPrintLevelBundleReport, type PrintLevelBundleReport, } from '../../../../../lib/level-print-export' -import type { ModelExport, ModelExportArtifact } from '../../../../../lib/model-export' +import type { + ModelExport, + ModelExportArtifact, + ModelExportFormat, +} from '../../../../../lib/model-export' import { isPrintExportReport, type PrintExportReport, @@ -17,6 +21,8 @@ type PreparedPrintExport = { report: PrintExportReport | PrintLevelBundleReport } +type PrintModelExportFormat = Extract + function downloadArtifact(artifact: ModelExportArtifact) { const url = URL.createObjectURL(artifact.blob) const link = document.createElement('a') @@ -39,8 +45,9 @@ function firstBlockingMessage(report: PrintExportReport | PrintLevelBundleReport export async function preparePrintExport( modelExport: ModelExport, onlyVisible: boolean, + format: PrintModelExportFormat, ): Promise { - const artifact = await modelExport('print-3mf', { + const artifact = await modelExport(format, { onlyVisible, download: false, printScale: 100, @@ -68,35 +75,47 @@ export async function preparePrintExport( export function PrintExportButton({ onlyVisible }: { onlyVisible: boolean }) { const modelExport = useEditor((state) => state.modelExport) - const [isExporting, setIsExporting] = useState(false) + const [exportingFormat, setExportingFormat] = useState(null) const [error, setError] = useState(null) - const handleExport = async () => { + const handleExport = async (format: PrintModelExportFormat) => { if (!modelExport) return - setIsExporting(true) + setExportingFormat(format) setError(null) try { - const prepared = await preparePrintExport(modelExport, onlyVisible) + const prepared = await preparePrintExport(modelExport, onlyVisible, format) downloadArtifact(prepared.artifact) } catch (reason) { setError(reason instanceof Error ? reason.message : '3D print export failed.') } finally { - setIsExporting(false) + setExportingFormat(null) } } + const isExporting = exportingFormat !== null + return ( <> + {error && (