From 480a43daf7d938b6e952160bae88df8be0df6024 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Sun, 31 May 2026 13:14:24 -0400 Subject: [PATCH 01/93] chore(release): open 1.0.5-alpha.1 cycle on alpha Following the 1.0.4 stable release: - Bump version 1.0.4-alpha.4 -> 1.0.5-alpha.1 (per CLAUDE.md lesson #9: never continue 1.0.4-alpha.N after 1.0.4 stable, or electron-updater 404s on the missing alpha.yml). Channel resolves to "alpha"/prerelease. - Sync CHANGELOG with main: consolidated [1.0.4] - 2026-05-31 entry plus a fresh empty [Unreleased]; alpha CHANGELOG is now identical to main. Verified: electron-builder reports "Channel: alpha (prerelease: true)"; pnpm install --frozen-lockfile passes. Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 52 ++++++++++++++++++++++++++++++++++++++++++---------- package.json | 2 +- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b19cc96..8179790 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,19 +7,50 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Added -- Job uploader now surfaces translated slicer warnings and the estimated first-layer time when previewing a sliced file (f2c8933) +## [1.0.4] - 2026-05-31 -### Changed -- Upgrade Electron from 35.7.5 to 39.8.10; the four-major-version jump required no source changes (type-check, build, lint, and the full Jest suite pass unchanged) (4a9d494) -- Streamline the README into a concise, table-driven overview and align the tech badges with current dependency versions (ade8cbb) +The 1.0.4 stable release consolidates the 1.0.4-alpha cycle: a major new Calibration Assistant, a complete camera-streaming rework on go2rtc, a full security hardening pass, and a modern testing and tooling foundation. -### Removed -- Stale `security-audit-2026-02-14.md` snapshot, superseded by the Dependabot remediation (a0cce37) +### Calibration Assistant +- New Calibration Assistant connects to your printer over SSH/SCP, parses Klipper configuration, and runs bed-mesh and input-shaper analysis with rendered reports — all from a dedicated desktop dialog (874f9de, 40e0c1c) + +### go2rtc Camera Streaming +- Replaced the legacy RTSP/JSMpeg stack with the go2rtc streaming gateway for low-latency WebRTC/MSE/MJPEG playback on both desktop and WebUI, with managed binary lifecycle and automatic stream configuration (462f35a, b3ebb4f) +- Auto-detect OEM cameras from printer-reported stream URLs, with intelligent fallback probing of `http://:8080/?action=stream` when firmware omits the URL (f4a62ed, 7d585d5, 64b17af) +- Retired CameraProxyService, RtspStreamService, PortAllocator, and JSMpeg canvas rendering (462f35a) + +### Notifications +- Discord notifications can now include a camera snapshot of the print (89267c3) +- Corrected time and ETA reporting across the WebUI and Discord alerts (6135d60) + +### Material Station (IFS) +- The IFS material station is now a first-class GridStack component with responsive layouts (1x4, 4x1, 2x2, compact) and dynamic spool sizing, replacing the old dialog (e14e058) + +### Theme Profiles & UI +- Create, rename, and delete custom theme profiles on both Desktop and WebUI (67b6971, 24f765d) +- Resizable UI components with updated default sizes (5931146) + +### Debug Logging +- New file-based debug logging system with session management, log rotation, and network-specific logs for connection troubleshooting (be53b98) +- `--debug` / `--debug-network` CLI flags for desktop and headless, a Settings toggle with a nested network option, and WebUI endpoints to list/download logs (be53b98) + +### Per-Printer Legacy Mode +- Legacy API mode is now a per-printer setting instead of a global override, with full settings/UI plumbing for 5M-series fallback (7bf2db9) + +### Testing & Reliability +- Browser Playwright coverage for the built WebUI — asset versioning, auth, WebSocket login, and context switching — backed by a fixture server (d967df9) +- Emulator-backed and live Electron Playwright coverage across 5M Pro, 5M, AD5X, Adventurer 3/4, plus multi-printer discovery, with dedicated Windows-friendly scripts (dc58252, c9c0348, 5a5f62d) +- Greatly expanded Jest coverage across managers, services, WebUI server/routes, static client modules, and build utilities (5d7e7e5) +- Aligned runtime discovery with the latest `@ghosttypes/ff-api` and kept printer-tab state synchronized; no-cache WebUI assets prevent stale mixes (6de2a87, 3d57598, 5d7e7e5) ### Security -- Resolve all 67 open Dependabot alerts (23 high / 35 moderate / 9 low → 0); `pnpm audit` reports 0 vulnerabilities. Bumps Electron to 39.8.10, Vite to 7.3.x, and `ws` to 8.21.x, pins `axios` to 1.16.1, and adds/refreshes `pnpm.overrides` for `tmp`, `qs`, `ip-address`, `postcss`, `@babel/plugin-transform-modules-systemjs`, `fast-xml-parser`, `@xmldom/xmldom`, and `brace-expansion` (4a9d494) -- Move the ineffective top-level `js-yaml` override into `pnpm.overrides` so the 4.1.1 pin actually applies, and drop the now-redundant `fast-xml-builder` and `follow-redirects` overrides (their parents already resolve patched versions) (9420edd, cb979aa) +- Hardened the WebUI: path-traversal protection on job filenames, timing-safe auth comparison, security headers (CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy), stored-XSS prevention, PBKDF2 password hashing (210k iterations) with automatic migration, per-installation dynamic secrets, and a secured go2rtc proxy binding (3d51c6e, 6366705, e2905d6, 235a225, d98e809, 649f704, 4c7433b, 98ea4ec) +- Resolved all 67 open Dependabot alerts (23 high / 35 moderate / 9 low → 0); `pnpm audit` reports 0 vulnerabilities (4a9d494, 9420edd, cb979aa) + +### Platform & Tooling +- Upgraded Electron from 35 to 39.8.10 and migrated the project from npm to pnpm (4a9d494, 0adcdca) +- Migrated the entire app to native ESM (c4a5d3c) +- Job uploader now displays translated slicer warnings and the estimated first-layer time (f2c8933) ## [1.0.4-alpha.4] - 2026-03-21 @@ -846,6 +877,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - README.md - Added download link to v1.0.0 release and feature comparison table (fcd8750) -[Unreleased]: https://github.com/Parallel-7/FlashForgeUI-Electron/compare/v1.0.4-alpha.4...alpha +[Unreleased]: https://github.com/Parallel-7/FlashForgeUI-Electron/compare/v1.0.4...alpha +[1.0.4]: https://github.com/Parallel-7/FlashForgeUI-Electron/compare/v1.0.4-alpha.4...v1.0.4 [1.0.4-alpha.4]: https://github.com/Parallel-7/FlashForgeUI-Electron/compare/v1.0.4-alpha.3...v1.0.4-alpha.4 [1.0.4-alpha.3]: https://github.com/Parallel-7/FlashForgeUI-Electron/compare/v1.0.4-alpha.2...v1.0.4-alpha.3 diff --git a/package.json b/package.json index 613c976..96cd52e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "FlashForgeUI", "productName": "FlashForgeUI", - "version": "1.0.4-alpha.4", + "version": "1.0.5-alpha.1", "packageManager": "pnpm@10.23.0", "description": "Monitoring and Control software for FlashForge printers", "main": "out/main/index.js", From b64ae3332f1a5a2112d098bc0268a8241aa1bd89 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Mon, 1 Jun 2026 15:40:11 -0400 Subject: [PATCH 02/93] feat(ui): add Edit Layout item to the main menu Edit mode was only reachable via the undocumented CTRL+E shortcut, while the WebUI already exposed a visible toggle. Add an "Edit Layout" entry to the hamburger dropdown that toggles GridStack edit mode, mirroring the WebUI for discoverability (issue #62). - New menu item with a pencil icon and platform-aware Ctrl+E / Cmd+E hint - Dynamic label: flips between "Edit Layout" and "Exit Edit Mode" - Disabled when no printer is connected, matching edit mode availability - EditModeController gains an onStateChange subscription so the label stays in sync regardless of trigger (menu, CTRL+E, reset, printer disconnect) - Disabled menu-item styling added Co-Authored-By: Claude Opus 4.8 --- src/renderer/index.html | 8 +++ src/renderer/src/index.css | 10 ++++ src/renderer/src/renderer.ts | 8 ++- .../src/ui/gridstack/EditModeController.ts | 42 ++++++++++++++ .../src/ui/legacy/LegacyUiController.ts | 57 ++++++++++++++++++- 5 files changed, 123 insertions(+), 2 deletions(-) diff --git a/src/renderer/index.html b/src/renderer/index.html index 72fa2d6..4e3cb89 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -68,6 +68,14 @@ Ctrl+P + + - + `; + + const actionBtn = popover.querySelector('.ifs-editor-action') as HTMLButtonElement | null; + actionBtn?.addEventListener('click', (e) => { + e.stopPropagation(); + void this.startSpoolPick(slot); + }); + + slotEl.appendChild(popover); + this.editorPopover = popover; + + // Dismiss when clicking elsewhere within the component. + const onOutside = (e: MouseEvent): void => { + if (!popover.contains(e.target as Node)) { + this.closeSlotEditor(); + document.removeEventListener('click', onOutside, true); + } + }; + // Defer so the originating click doesn't immediately dismiss it. + setTimeout(() => document.addEventListener('click', onOutside, true), 0); + } + + /** + * Close the slot editor popover if open. + */ + private closeSlotEditor(): void { + if (this.editorPopover) { + this.editorPopover.remove(); + this.editorPopover = null; + } + } + + /** + * Begin the Spoolman pick flow for a slot: register a one-shot listener for the + * chosen spool, then open the existing spool picker in slot-config mode. + */ + private async startSpoolPick(slot: number): Promise { + if (!window.api?.spoolman) return; + + this.closeSlotEditor(); + this.pendingSlot = slot; + + // Replace any stale listener. + this.spoolPickedDisposer?.(); + this.spoolPickedDisposer = window.api.spoolman.onSpoolPickedForSlot((spool: unknown) => { + // One-shot: dispose immediately so reopening the picker doesn't double-fire. + this.spoolPickedDisposer?.(); + this.spoolPickedDisposer = null; + void this.applyPickedSpool(spool as PickedSpool); + }); + + try { + await window.api.spoolman.openSpoolSelection('slot-config'); + } catch (error) { + console.error('[IFSStation] Failed to open spool picker:', error); + this.spoolPickedDisposer?.(); + this.spoolPickedDisposer = null; + this.pendingSlot = null; + } + } + + /** + * Apply the picked spool to the pending slot: snap + configure via IPC, confirm + * with the user, then show the result. The station refreshes via polling. + */ + private async applyPickedSpool(spool: PickedSpool): Promise { + const slot = this.pendingSlot; + this.pendingSlot = null; + + if (slot === null || !spool || typeof spool.id !== 'number') { + return; + } + + if (!window.api?.material?.configureSlot) { + window.api?.loading?.showError('Material control is not available', 4000); + return; + } + + // Desktop confirm step before writing to the printer. + const spoolLabel = spool.name || `spool ${spool.id}`; + const confirmed = window.confirm( + `Set Slot ${slot} from "${spoolLabel}"?\n\n` + + `Its material and color will be snapped to the printer's fixed palette and applied to the slot.` + ); + if (!confirmed) { + return; + } + + try { + const result = await window.api.material.configureSlot(slot, spool.id, this.contextId || undefined); + + if (!result.success) { + window.api?.loading?.showError(result.error || 'Failed to configure slot', 5000); + return; + } + + const spoolName = result.spoolName || spool.name || `spool ${spool.id}`; + window.api?.loading?.showSuccess( + `Slot ${result.slot ?? slot} → ${result.material ?? 'material kept'} · ${result.colorName ?? ''}, from ${spoolName}`, + 4000 + ); + // Station UI refreshes on the next poll cycle. + } catch (error) { + console.error('[IFSStation] Failed to apply spool to slot:', error); + window.api?.loading?.showError(error instanceof Error ? error.message : 'Failed to configure slot', 5000); + } + } + /** * Helper to find element by class name within component */ @@ -380,5 +587,10 @@ export class IFSStationComponent extends BaseComponent { this.resizeObserver.disconnect(); this.resizeObserver = null; } + + this.spoolPickedDisposer?.(); + this.spoolPickedDisposer = null; + this.closeSlotEditor(); + this.pendingSlot = null; } } diff --git a/src/shared/__tests__/ifs-palette.test.ts b/src/shared/__tests__/ifs-palette.test.ts new file mode 100644 index 0000000..84d7abf --- /dev/null +++ b/src/shared/__tests__/ifs-palette.test.ts @@ -0,0 +1,136 @@ +/** + * @fileoverview Tests for the AD5X IFS palette nearest-match helpers. + * + * Verifies the CIEDE2000 color snapping and material normalization in + * `src/shared/ifs-palette.ts` against the full 24-swatch palette, a small + * RGB neighborhood around each swatch, a curated set of known off-palette + * colors (including cases a naive RGB/ΔE76 distance gets wrong), hex-format + * variants, and the material mapping matrix. All fixtures are static; nothing + * here contacts a Spoolman instance. + * + * @module shared/__tests__/ifs-palette + */ + +import { IFS_COLORS, nearestColor, nearestMaterial } from '../ifs-palette.js'; + +/** Build a #RRGGBB hex from clamped RGB components. */ +function toHex(r: number, g: number, b: number): string { + const clamp = (n: number): number => Math.max(0, Math.min(255, n)); + const part = (n: number): string => clamp(n).toString(16).padStart(2, '0'); + return `#${part(r)}${part(g)}${part(b)}`; +} + +function parseHex(hex: string): [number, number, number] { + const h = hex.replace(/^#/, ''); + return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)]; +} + +describe('nearestColor', () => { + describe('each swatch resolves to itself', () => { + for (const swatch of IFS_COLORS) { + it(`${swatch.name} (${swatch.hex}) -> ${swatch.name}`, () => { + expect(nearestColor(swatch.hex)?.name).toBe(swatch.name); + }); + } + }); + + describe('a +/-6 RGB neighborhood around each swatch snaps back to it', () => { + const offsets = [-6, 0, 6]; + for (const swatch of IFS_COLORS) { + const [r, g, b] = parseHex(swatch.hex); + for (const dr of offsets) { + for (const dg of offsets) { + for (const db of offsets) { + const hex = toHex(r + dr, g + dg, b + db); + it(`${swatch.name} ${hex} -> ${swatch.name}`, () => { + expect(nearestColor(hex)?.name).toBe(swatch.name); + }); + } + } + } + } + }); + + describe('saturated/obvious off-palette colors snap to the intuitive swatch', () => { + // Pure primaries/secondaries plus neutrals — each has one obviously-correct + // nearest palette swatch, guarding the basic sanity of the matcher. + const fixtures: ReadonlyArray<[string, string]> = [ + ['#FF0000', 'Red'], + ['#00FF00', 'Green'], + ['#FFFF00', 'Yellow'], + ['#00FFFF', 'Light Blue'], + ['#FF00FF', 'Magenta'], + ['#FFA500', 'Orange'], // CSS "orange" + ['#FFFFFF', 'White'], + ['#000000', 'Black'], + ['#808080', 'Gray'], // mid-grey + ]; + for (const [hex, expected] of fixtures) { + it(`${hex} -> ${expected}`, () => { + expect(nearestColor(hex)?.name).toBe(expected); + }); + } + }); + + describe('perceptual edge cases a naive RGB/ΔE76 distance gets wrong', () => { + // The cases that motivate CIEDE2000 over a plain Lab/RGB distance: ΔE76 + // mis-snaps pure blue to Violet and burgundy to Coral; CIEDE2000 maps them + // to Dark Blue and Red as a human would. + const fixtures: ReadonlyArray<[string, string]> = [ + ['#0000FF', 'Dark Blue'], // ΔE76 picks Violet + ['#951e23', 'Red'], // burgundy — ΔE76 picks Coral + ['#6c4f4c', 'Brown'], // muted warm grey-brown + ]; + for (const [hex, expected] of fixtures) { + it(`${hex} -> ${expected}`, () => { + expect(nearestColor(hex)?.name).toBe(expected); + }); + } + }); + + describe('hex format variants', () => { + it('accepts a hex without leading #', () => { + expect(nearestColor('F72224')?.name).toBe('Red'); + }); + + it('drops alpha from an RRGGBBAA hex', () => { + expect(nearestColor('#F72224FF')?.name).toBe('Red'); + }); + + it('expands #RGB shorthand', () => { + // #F00 -> #FF0000 -> Red + expect(nearestColor('#F00')?.name).toBe('Red'); + }); + + it('returns null for an unparseable value', () => { + expect(nearestColor('not-a-color')).toBeNull(); + expect(nearestColor('#12')).toBeNull(); + expect(nearestColor('')).toBeNull(); + }); + }); +}); + +describe('nearestMaterial', () => { + const cases: ReadonlyArray<[string, string | null]> = [ + ['PLA-CF', 'PLA-CF'], + ['petg-cf', 'PETG-CF'], + ['PLA+', 'PLA'], + ['PLA Matte', 'PLA'], + ['PETG-CF Pro', 'PETG-CF'], + ['PCTG', null], + ['PA6', null], + ['Nylon', null], + ]; + + for (const [raw, expected] of cases) { + it(`${JSON.stringify(raw)} -> ${JSON.stringify(expected)}`, () => { + expect(nearestMaterial(raw)).toBe(expected); + }); + } + + it('returns null for empty or non-string input', () => { + expect(nearestMaterial('')).toBeNull(); + expect(nearestMaterial(' ')).toBeNull(); + expect(nearestMaterial(undefined as unknown as string)).toBeNull(); + }); +}); diff --git a/src/shared/ifs-palette.ts b/src/shared/ifs-palette.ts new file mode 100644 index 0000000..7a4f816 --- /dev/null +++ b/src/shared/ifs-palette.ts @@ -0,0 +1,164 @@ +/** + * @fileoverview AD5X IFS material/color palette and nearest-match helpers. + * + * Pure, framework-agnostic module (no DOM/Electron deps) importable by both the + * main and renderer processes. The AD5X printer only renders a fixed set of 14 + * materials and 24 colors on its material-station UI; arbitrary values won't draw + * an icon. These helpers snap an arbitrary Spoolman material/color onto that fixed + * palette: + * + * - {@link nearestColor} snaps a hex color to the nearest of the 24 swatches using + * CIEDE2000 distance (not plain ΔE76, which mismatches saturated blue/red regions). + * - {@link nearestMaterial} snaps a raw material string to one of the 14 recognized + * materials via exact (normalized) match, else leading-token match, else null. + * + * The 14 materials, 24 colors, and matching algorithm are ported verbatim from the + * validated reference implementation (`IfsPalette.kt`) and verified against all 24 + * swatches plus live-Spoolman fixtures. + * + * @module shared/ifs-palette + */ + +export interface PaletteColor { + /** Human-readable swatch name, e.g. "Dark Blue". */ + name: string; + /** Hex code with leading '#', e.g. "#2750E0". */ + hex: string; +} + +/** The 14 materials the AD5X UI renders (order matches the API docs). */ +export const IFS_MATERIALS: readonly string[] = [ + 'PLA', 'PLA-CF', 'PETG', 'PETG-CF', 'ABS', 'TPU', 'SILK', + 'PA', 'PA-CF', 'PAHT-CF', 'PC', 'PC-ABS', 'PET-CF', 'PPS-CF', +]; + +/** The 24 colors the AD5X UI renders. */ +export const IFS_COLORS: readonly PaletteColor[] = [ + { name: 'White', hex: '#FFFFFF' }, { name: 'Yellow', hex: '#FEF043' }, + { name: 'Light Green', hex: '#DCF478' }, { name: 'Green', hex: '#0ACC38' }, + { name: 'Dark Green', hex: '#067749' }, { name: 'Teal', hex: '#0C6283' }, + { name: 'Cyan', hex: '#0DE2A0' }, { name: 'Light Blue', hex: '#75D9F3' }, + { name: 'Blue', hex: '#45A8F9' }, { name: 'Dark Blue', hex: '#2750E0' }, + { name: 'Purple', hex: '#46328E' }, { name: 'Violet', hex: '#A03CF7' }, + { name: 'Magenta', hex: '#F330F9' }, { name: 'Pink', hex: '#D4B0DC' }, + { name: 'Coral', hex: '#F95D73' }, { name: 'Red', hex: '#F72224' }, + { name: 'Brown', hex: '#7C4B00' }, { name: 'Orange', hex: '#F98D33' }, + { name: 'Cream', hex: '#FDEBD5' }, { name: 'Tan', hex: '#D3C4A3' }, + { name: 'Dark Brown', hex: '#AF7836' }, { name: 'Gray', hex: '#898989' }, + { name: 'Light Gray', hex: '#BCBCBC' }, { name: 'Black', hex: '#161616' }, +]; + +type Lab = readonly [number, number, number]; + +function parseHex(hex: string): [number, number, number] | null { + if (typeof hex !== 'string') return null; + let h = hex.trim().replace(/^#/, ''); + if (h.length === 8) h = h.slice(0, 6); // drop alpha + if (h.length === 3) h = h.split('').map((c) => c + c).join(''); + if (h.length !== 6 || /[^0-9a-fA-F]/.test(h)) return null; + return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)]; +} + +function srgbToLinear(c: number): number { + const cs = c / 255; + return cs <= 0.04045 ? cs / 12.92 : ((cs + 0.055) / 1.055) ** 2.4; +} + +function hexToLab(hex: string): Lab | null { + const rgb = parseHex(hex); + if (!rgb) return null; + const r = srgbToLinear(rgb[0]) * 100; + const g = srgbToLinear(rgb[1]) * 100; + const b = srgbToLinear(rgb[2]) * 100; + const X = r * 0.4124 + g * 0.3576 + b * 0.1805; + const Y = r * 0.2126 + g * 0.7152 + b * 0.0722; + const Z = r * 0.0193 + g * 0.1192 + b * 0.9505; + const Xn = 95.047, Yn = 100.0, Zn = 108.883; + const f = (t: number): number => (t > 0.008856 ? Math.cbrt(t) : 7.787 * t + 16 / 116); + const fx = f(X / Xn), fy = f(Y / Yn), fz = f(Z / Zn); + return [116 * fy - 16, 500 * (fx - fy), 200 * (fy - fz)]; +} + +const rad = (d: number): number => (d * Math.PI) / 180; +const deg = (r: number): number => (r * 180) / Math.PI; + +function hueDeg(b: number, ap: number): number { + if (ap === 0 && b === 0) return 0; + let h = deg(Math.atan2(b, ap)); + if (h < 0) h += 360; + return h; +} + +function ciede2000(lab1: Lab, lab2: Lab): number { + const [L1, a1, b1] = lab1; + const [L2, a2, b2] = lab2; + const C1 = Math.hypot(a1, b1); + const C2 = Math.hypot(a2, b2); + const Cbar = (C1 + C2) / 2; + const Cbar7 = Cbar ** 7; + const G = 0.5 * (1 - Math.sqrt(Cbar7 / (Cbar7 + 25 ** 7))); + const a1p = a1 * (1 + G); + const a2p = a2 * (1 + G); + const C1p = Math.hypot(a1p, b1); + const C2p = Math.hypot(a2p, b2); + const h1p = hueDeg(b1, a1p); + const h2p = hueDeg(b2, a2p); + const dLp = L2 - L1; + const dCp = C2p - C1p; + let dhp: number; + if (C1p * C2p === 0) dhp = 0; + else if (Math.abs(h2p - h1p) <= 180) dhp = h2p - h1p; + else if (h2p - h1p > 180) dhp = h2p - h1p - 360; + else dhp = h2p - h1p + 360; + const dHp = 2 * Math.sqrt(C1p * C2p) * Math.sin(rad(dhp) / 2); + const Lbarp = (L1 + L2) / 2; + const Cbarp = (C1p + C2p) / 2; + let hbarp: number; + if (C1p * C2p === 0) hbarp = h1p + h2p; + else if (Math.abs(h1p - h2p) <= 180) hbarp = (h1p + h2p) / 2; + else if (h1p + h2p < 360) hbarp = (h1p + h2p + 360) / 2; + else hbarp = (h1p + h2p - 360) / 2; + const T = 1 - 0.17 * Math.cos(rad(hbarp - 30)) + 0.24 * Math.cos(rad(2 * hbarp)) + + 0.32 * Math.cos(rad(3 * hbarp + 6)) - 0.2 * Math.cos(rad(4 * hbarp - 63)); + const dtheta = 30 * Math.exp(-(((hbarp - 275) / 25) ** 2)); + const Cbarp7 = Cbarp ** 7; + const RC = 2 * Math.sqrt(Cbarp7 / (Cbarp7 + 25 ** 7)); + const SL = 1 + (0.015 * (Lbarp - 50) ** 2) / Math.sqrt(20 + (Lbarp - 50) ** 2); + const SC = 1 + 0.045 * Cbarp; + const SH = 1 + 0.015 * Cbarp * T; + const RT = -Math.sin(rad(2 * dtheta)) * RC; + return Math.sqrt((dLp / SL) ** 2 + (dCp / SC) ** 2 + (dHp / SH) ** 2 + RT * (dCp / SC) * (dHp / SH)); +} + +const PALETTE_LAB: ReadonlyArray<{ color: PaletteColor; lab: Lab }> = IFS_COLORS.map((color) => { + const lab = hexToLab(color.hex); + if (!lab) throw new Error(`Invalid palette hex: ${color.hex}`); + return { color, lab }; +}); + +/** Snap an arbitrary hex (#RRGGBB, RRGGBB, RRGGBBAA, or #RGB) to the nearest palette swatch via CIEDE2000. Returns null if unparseable. */ +export function nearestColor(hex: string): PaletteColor | null { + const lab = hexToLab(hex); + if (!lab) return null; + let best: PaletteColor | null = null; + let bestD = Number.POSITIVE_INFINITY; + for (const entry of PALETTE_LAB) { + const d = ciede2000(lab, entry.lab); + if (d < bestD) { bestD = d; best = entry.color; } + } + return best; +} + +function normalizeMaterial(raw: string): string { + return raw.toUpperCase().replace(/[^A-Z0-9]/g, ''); +} +const MATERIAL_NORM = new Map(IFS_MATERIALS.map((m) => [normalizeMaterial(m), m])); + +/** Snap a raw Spoolman material to a recognized material: exact (normalized) match, else leading-token match, else null (caller keeps current slot material). */ +export function nearestMaterial(raw: string): string | null { + if (typeof raw !== 'string' || raw.trim() === '') return null; + const exact = MATERIAL_NORM.get(normalizeMaterial(raw)); + if (exact) return exact; + const leading = raw.trim().split(/\s+/)[0]; + return MATERIAL_NORM.get(normalizeMaterial(leading)) ?? null; +} diff --git a/src/shared/types/global.d.ts b/src/shared/types/global.d.ts index c4016ce..a6bed6e 100644 --- a/src/shared/types/global.d.ts +++ b/src/shared/types/global.d.ts @@ -105,7 +105,7 @@ interface PrinterSettingsAPI { // Spoolman API interface interface SpoolmanAPI { - openSpoolSelection(): Promise; + openSpoolSelection(purpose?: 'active' | 'slot-config'): Promise; getActiveSpool(contextId?: string): Promise; setActiveSpool(spool: unknown, contextId?: string): Promise; getStatus( @@ -113,6 +113,23 @@ interface SpoolmanAPI { ): Promise<{ enabled: boolean; disabledReason?: string | null; contextId?: string | null }>; onSpoolSelected(callback: (spool: unknown) => void): void; onSpoolUpdated(callback: (spool: unknown) => void): void; + onSpoolPickedForSlot(callback: (spool: unknown) => void): () => void; +} + +// Result of an AD5X material-slot configuration attempt +interface ConfigureSlotResult { + success: boolean; + error?: string; + slot?: number; + material?: string | null; + colorName?: string; + colorHex?: string; + spoolName?: string; +} + +// Material station control API interface +interface MaterialAPI { + configureSlot(slot: number, spoolId: number, contextId?: string): Promise; } interface ConfigAPI { @@ -228,6 +245,7 @@ interface ElectronAPI { connectionState: ConnectionStateAPI; printerSettings: PrinterSettingsAPI; spoolman: SpoolmanAPI; + material: MaterialAPI; } // Window controls interface for sub-windows From 1a4fec3a3b9dfbc70dd043c357d18dae9d1a6071 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Sat, 6 Jun 2026 15:03:07 -0400 Subject: [PATCH 06/93] feat(ifs): manual slot editor dialog + Spoolman-independent slot writes Replace the small "Set from Spoolman" popover with a full slot editor dialog: a material dropdown (14 recognized materials) and a grid of the 24 recognized color swatches, pre-seeded from the slot's current material/color. Works with Spoolman disabled. - material:set-slot IPC + material.setSlot preload: apply an explicit material + color to a slot (no Spoolman dependency). - Gate the "Set from Spoolman" shortcut on the global Spoolman config (enabled + URL), not on spoolman.getStatus() - which the backend hard-disables for AD5X material-station printers, i.e. exactly the printers this feature targets. When used it pre-fills the dialog from the picked spool (snapped to the palette) for review before Apply. - SpoolmanIntegrationService.isContextSupported now detects AD5X via the firmware PID (FiveMClient.isAD5X) + material-station capability instead of the brittle printerModel.startsWith('AD5') string match. Co-Authored-By: Claude Opus 4.8 --- src/main/ipc/handlers/material-handlers.ts | 58 +++ .../services/SpoolmanIntegrationService.ts | 24 +- src/preload/index.ts | 24 ++ .../ui/components/ifs-station/ifs-station.css | 235 +++++++++-- .../ui/components/ifs-station/ifs-station.ts | 384 ++++++++++++------ src/shared/types/global.d.ts | 6 + 6 files changed, 566 insertions(+), 165 deletions(-) diff --git a/src/main/ipc/handlers/material-handlers.ts b/src/main/ipc/handlers/material-handlers.ts index 24f7e87..c54c14b 100644 --- a/src/main/ipc/handlers/material-handlers.ts +++ b/src/main/ipc/handlers/material-handlers.ts @@ -12,6 +12,8 @@ * IPC Channels: * - `material:configure-slot` - Snap a Spoolman spool's material/color onto the * AD5X fixed palette and apply it to a slot via the printer's `msConfig_cmd`. + * - `material:set-slot` - Apply an explicit material + color (already chosen from + * the fixed palette by the renderer) to a slot. Spoolman-independent. * * @module ipc/handlers/material-handlers */ @@ -53,6 +55,22 @@ interface ConfigureSlotResult { spoolName?: string; } +/** + * Request payload for `material:set-slot` — an explicit, Spoolman-independent + * slot write. The renderer has already chosen `materialName`/`colorHex` from the + * fixed AD5X palette via the manual slot editor. + */ +interface SetSlotRequest { + /** Target slot number (1-4). */ + slot: number; + /** Material name to write (one of the recognized AD5X materials). */ + materialName: string; + /** Color hex to write (with or without leading "#"). */ + colorHex: string; + /** Optional context ID; defaults to the active context. */ + contextId?: string; +} + /** * Register all material station related IPC handlers */ @@ -160,4 +178,44 @@ export function registerMaterialHandlers(backendManager: PrinterBackendManager): }; } }); + + // Manually set an AD5X slot's material + color (chosen from the fixed palette + // in the renderer's slot editor). No Spoolman dependency. + ipcMain.handle('material:set-slot', async (_event, request: SetSlotRequest): Promise => { + try { + const { slot, materialName, colorHex } = request; + + if (!Number.isInteger(slot) || slot < 1 || slot > 4) { + return { success: false, error: 'Invalid slot number (expected 1-4)' }; + } + if (typeof materialName !== 'string' || materialName.trim() === '') { + return { success: false, error: 'Material name is required' }; + } + if (typeof colorHex !== 'string' || !/^#?[0-9a-fA-F]{6}$/.test(colorHex.trim())) { + return { success: false, error: 'A valid 6-digit hex color is required' }; + } + + const contextManager = getPrinterContextManager(); + const contextId = request.contextId || contextManager.getActiveContextId(); + if (!contextId) { + return { success: false, error: 'No active printer context' }; + } + + const material = materialName.trim(); + const hex = colorHex.trim(); + const result = await backendManager.configureMaterialSlot(contextId, slot, material, hex); + + if (!result.success) { + return { success: false, error: result.error || 'Failed to configure slot', slot }; + } + + return { success: true, slot, material, colorHex: hex }; + } catch (error) { + console.error('[MaterialHandlers] set-slot error:', error); + return { + success: false, + error: error instanceof Error ? error.message : 'Unknown error', + }; + } + }); } diff --git a/src/main/services/SpoolmanIntegrationService.ts b/src/main/services/SpoolmanIntegrationService.ts index 69713ff..7e69d4e 100644 --- a/src/main/services/SpoolmanIntegrationService.ts +++ b/src/main/services/SpoolmanIntegrationService.ts @@ -13,12 +13,13 @@ * - Spoolman configuration validation and connection testing * * AD5X Detection Logic: - * - Material station feature flag (materialStation.available === true), OR - * - Printer model string starts with "AD5" + * - Firmware PID via the library (`FiveMClient.isAD5X`, derived from `/detail` pid), OR + * - Material station capability flag (materialStation.available === true) as a fallback * * @module services/SpoolmanIntegrationService */ +import { FiveMClient } from '@ghosttypes/ff-api'; import type { ConfigUpdateEvent } from '@shared/types/config.js'; import type { PrinterDetails } from '@shared/types/printer.js'; import type { ActiveSpoolData, SpoolResponse, SpoolSearchQuery } from '@shared/types/spoolman.js'; @@ -107,16 +108,19 @@ export class SpoolmanIntegrationService extends EventEmitter { return false; } - // Check for material station feature (AD5X indicator) - const features = this.backendManager.getFeatures(contextId); - if (features?.materialStation?.available === true) { - return false; // AD5X with material station + // AD5X printers manage filament via the Intelligent Filament Station rather + // than a single active spool, so active-spool tracking is not offered for + // them. Detect AD5X authoritatively from the firmware PID surfaced by the + // library (FiveMClient.isAD5X, derived from the `/detail` pid), with the + // material-station capability as a fallback. Do NOT substring-match the + // user-mutable model name. + const client = this.backendManager.getBackendForContext(contextId)?.getPrimaryClient(); + if (client instanceof FiveMClient && client.isAD5X) { + return false; } - // Check for AD5X model name - const printerModel = context.printerDetails?.printerModel || ''; - if (printerModel.startsWith('AD5')) { - return false; // AD5X model + if (this.backendManager.getFeatures(contextId)?.materialStation?.available === true) { + return false; } return true; diff --git a/src/preload/index.ts b/src/preload/index.ts index 1e9d380..adc4764 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -100,6 +100,12 @@ interface ConfigureSlotResult { // Material station control API interface interface MaterialAPI { configureSlot: (slot: number, spoolId: number, contextId?: string) => Promise; + setSlot: ( + slot: number, + materialName: string, + colorHex: string, + contextId?: string + ) => Promise; } // Camera API interface @@ -652,6 +658,7 @@ const electronAPI: ElectronAPI = { 'spoolman:set-active-spool', 'spoolman:get-status', 'material:configure-slot', + 'material:set-slot', 'debug:get-state', 'e2e:discord:send-current-status', 'e2e:discord:send-print-complete', @@ -869,6 +876,23 @@ const electronAPI: ElectronAPI = { } return { success: false, error: 'Invalid response from material:configure-slot' }; }, + setSlot: async ( + slot: number, + materialName: string, + colorHex: string, + contextId?: string + ): Promise => { + const result: unknown = await ipcRenderer.invoke('material:set-slot', { + slot, + materialName, + colorHex, + contextId, + }); + if (isRecord(result) && isBoolean(result.success)) { + return result as unknown as ConfigureSlotResult; + } + return { success: false, error: 'Invalid response from material:set-slot' }; + }, }, }; diff --git a/src/renderer/src/ui/components/ifs-station/ifs-station.css b/src/renderer/src/ui/components/ifs-station/ifs-station.css index bfda39f..944afc9 100644 --- a/src/renderer/src/ui/components/ifs-station/ifs-station.css +++ b/src/renderer/src/ui/components/ifs-station/ifs-station.css @@ -455,45 +455,232 @@ cursor: pointer; } -.ifs-slot-editor { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - z-index: 5; +/* ---- Slot editor dialog (manual material/color picker) ---- */ + +.ifs-dialog-backdrop { + position: fixed; + inset: 0; + z-index: 10000; + display: flex; + align-items: center; + justify-content: center; + padding: 16px; + background: color-mix(in srgb, var(--theme-background, #000) 55%, transparent); + backdrop-filter: blur(2px); + animation: ifs-dialog-fade 0.12s ease-out; +} + +@keyframes ifs-dialog-fade { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.ifs-dialog { display: flex; flex-direction: column; - align-items: stretch; - gap: 6px; - padding: 8px; - min-width: 140px; - background: var(--surface-elevated, var(--theme-surface)); + width: 100%; + max-width: 380px; + max-height: calc(100vh - 32px); + overflow: hidden; + background: var(--surface-elevated, var(--theme-surface, var(--card-bg))); border: 1px solid var(--border-color); - border-radius: 8px; - box-shadow: 0 4px 12px color-mix(in srgb, var(--theme-background) 40%, black); + border-radius: 12px; + box-shadow: 0 12px 40px color-mix(in srgb, var(--theme-background, #000) 60%, black); + animation: ifs-dialog-pop 0.14s ease-out; } -.ifs-editor-title { - font-size: 11px; +@keyframes ifs-dialog-pop { + from { + transform: translateY(8px) scale(0.98); + opacity: 0; + } + to { + transform: translateY(0) scale(1); + opacity: 1; + } +} + +.ifs-dialog-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 14px 16px; + border-bottom: 1px solid var(--border-color); +} + +.ifs-dialog-title { + font-size: 14px; font-weight: 600; + color: var(--theme-text, var(--text-color)); +} + +.ifs-dialog-close { + display: flex; + align-items: center; + justify-content: center; + width: 26px; + height: 26px; + font-size: 20px; + line-height: 1; color: var(--text-color-muted); + background: transparent; + border: none; + border-radius: 6px; + cursor: pointer; + transition: background 0.15s ease, color 0.15s ease; +} + +.ifs-dialog-close:hover { + color: var(--theme-text, var(--text-color)); + background: var(--surface-muted, color-mix(in srgb, var(--theme-text, #fff) 10%, transparent)); +} + +.ifs-dialog-body { + display: flex; + flex-direction: column; + gap: 16px; + padding: 16px; + overflow-y: auto; +} + +.ifs-dialog-field { + display: flex; + flex-direction: column; + gap: 8px; +} + +.ifs-dialog-label { + font-size: 11px; + font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; - text-align: center; + color: var(--text-color-muted); +} + +.ifs-dialog-material { + width: 100%; + padding: 8px 10px; + font-size: 13px; + color: var(--theme-text, var(--text-color)); + background: var(--surface-muted, var(--theme-background)); + border: 1px solid var(--border-color); + border-radius: 8px; + cursor: pointer; +} + +.ifs-dialog-material:focus { + outline: none; + border-color: var(--theme-primary); +} + +.ifs-swatch-grid { + display: grid; + grid-template-columns: repeat(8, 1fr); + gap: 6px; +} + +.ifs-swatch { + position: relative; + aspect-ratio: 1 / 1; + padding: 0; + background: var(--swatch); + border: 1px solid color-mix(in srgb, var(--theme-text, #fff) 18%, transparent); + border-radius: 6px; + cursor: pointer; + transition: transform 0.1s ease, box-shadow 0.1s ease; +} + +.ifs-swatch:hover { + transform: scale(1.08); +} + +.ifs-swatch.selected { + box-shadow: 0 0 0 2px var(--surface-elevated, var(--theme-surface)), + 0 0 0 4px var(--theme-primary); +} + +.ifs-swatch-check { + position: absolute; + inset: 0; + display: none; + align-items: center; + justify-content: center; + font-size: 13px; + font-weight: 700; + color: #fff; + text-shadow: 0 0 2px rgba(0, 0, 0, 0.9), 0 0 3px rgba(0, 0, 0, 0.7); +} + +.ifs-swatch.selected .ifs-swatch-check { + display: flex; +} + +.ifs-dialog-preview { + font-size: 12px; + color: var(--text-color-muted); + min-height: 16px; +} + +.ifs-dialog-footer { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 12px 16px; + border-top: 1px solid var(--border-color); } -.ifs-editor-action { +.ifs-dialog-footer-right { + display: flex; + gap: 8px; + margin-left: auto; +} + +.ifs-dialog-footer button { font-size: 12px; font-weight: 500; + padding: 7px 14px; + border-radius: 7px; + cursor: pointer; + transition: background 0.15s ease, opacity 0.15s ease; +} + +.ifs-dialog-cancel { color: var(--theme-text, var(--text-color)); - background: color-mix(in srgb, var(--theme-primary) 15%, transparent); + background: var(--surface-muted, transparent); + border: 1px solid var(--border-color); +} + +.ifs-dialog-cancel:hover { + background: color-mix(in srgb, var(--theme-text, #fff) 10%, transparent); +} + +.ifs-dialog-spoolman { + color: var(--theme-text, var(--text-color)); + background: color-mix(in srgb, var(--theme-primary) 14%, transparent); border: 1px solid color-mix(in srgb, var(--theme-primary) 40%, transparent); - border-radius: 6px; - padding: 6px 10px; - cursor: pointer; - transition: background 0.15s ease; } -.ifs-editor-action:hover { - background: color-mix(in srgb, var(--theme-primary) 28%, transparent); +.ifs-dialog-spoolman:hover { + background: color-mix(in srgb, var(--theme-primary) 26%, transparent); +} + +.ifs-dialog-apply { + color: #fff; + background: var(--theme-primary); + border: 1px solid var(--theme-primary); +} + +.ifs-dialog-apply:hover:not(:disabled) { + background: color-mix(in srgb, var(--theme-primary) 85%, black); +} + +.ifs-dialog-apply:disabled { + opacity: 0.45; + cursor: not-allowed; } diff --git a/src/renderer/src/ui/components/ifs-station/ifs-station.ts b/src/renderer/src/ui/components/ifs-station/ifs-station.ts index 4343738..310bb21 100644 --- a/src/renderer/src/ui/components/ifs-station/ifs-station.ts +++ b/src/renderer/src/ui/components/ifs-station/ifs-station.ts @@ -16,17 +16,19 @@ * @module ui/components/ifs-station */ -import type { AppConfig } from '@shared/types/config.js'; +import { IFS_COLORS, IFS_MATERIALS, nearestColor, nearestMaterial } from '@shared/ifs-palette.js'; import type { MaterialStationStatus } from '@shared/types/polling.js'; import { BaseComponent } from '../base/component.js'; import type { ComponentUpdateData } from '../base/types.js'; import type { IFSLayoutMode, MaterialSlot } from './types.js'; import './ifs-station.css'; -/** Minimal shape of a spool handed back from the Spoolman picker. */ +/** Shape of a spool handed back from the Spoolman picker (a subset of ActiveSpoolData). */ interface PickedSpool { id: number; name?: string; + material?: string | null; + colorHex?: string; } /** @@ -115,16 +117,20 @@ export class IFSStationComponent extends BaseComponent { // ResizeObserver for responsive layout private resizeObserver: ResizeObserver | null = null; - // Spoolman slot-config state + // Slot editor state private contextId: string | null = null; - private spoolmanEnabled = false; - private spoolmanContextEnabled = false; - /** Slot (1-4) awaiting a spool pick, or null when no editor flow is active. */ + /** Slot (1-4) currently being edited, or null when the dialog is closed. */ private pendingSlot: number | null = null; /** Disposer for the active one-shot "spool picked" listener. */ private spoolPickedDisposer: (() => void) | null = null; - /** Currently open slot editor popover element, if any. */ - private editorPopover: HTMLElement | null = null; + /** Currently open slot editor dialog (backdrop) element, if any. */ + private dialogEl: HTMLElement | null = null; + /** Escape-key handler for the open dialog, if any. */ + private dialogKeyHandler: ((e: KeyboardEvent) => void) | null = null; + /** Material currently selected in the open dialog. */ + private dialogMaterial = ''; + /** Color hex currently selected in the open dialog (with leading #), or null. */ + private dialogColorHex: string | null = null; /** * Setup event listeners and initialize the component @@ -152,9 +158,8 @@ export class IFSStationComponent extends BaseComponent { } /** - * Wire click handling on the slots container so a user can open a per-slot - * editor offering "Set from Spoolman". Uses event delegation so it survives - * slot re-renders. + * Wire click handling on the slots container so a user can open the per-slot + * editor dialog. Uses event delegation so it survives slot re-renders. */ private setupSlotInteraction(): void { if (!this.slotsContainer) return; @@ -165,7 +170,7 @@ export class IFSStationComponent extends BaseComponent { const slotAttr = slotEl.getAttribute('data-slot'); const slot = slotAttr ? Number.parseInt(slotAttr, 10) : NaN; if (!Number.isInteger(slot) || slot < 1 || slot > 4) return; - this.openSlotEditor(slot, slotEl); + this.openSlotDialog(slot); }); } @@ -223,50 +228,19 @@ export class IFSStationComponent extends BaseComponent { this.activeSlot = materialStation?.activeSlot ?? null; this.errorMessage = materialStation?.errorMessage ?? null; - // Track Spoolman availability for the "Set from Spoolman" affordance - let availabilityNeedsRefresh = false; - if (data.config) { - const config = data.config as AppConfig; - if (config.SpoolmanEnabled !== this.spoolmanEnabled) { - this.spoolmanEnabled = config.SpoolmanEnabled; - availabilityNeedsRefresh = true; - } - } + // Track the active printer context for slot-config IPC calls (falls back to + // the active context server-side when null). if (typeof data.contextId === 'string' && data.contextId !== this.contextId) { this.contextId = data.contextId; - availabilityNeedsRefresh = true; } this.updateState(data); this.updateView(); - - if (availabilityNeedsRefresh) { - void this.refreshSpoolmanAvailability(); - } } catch (error) { console.error(`[IFSStation] Error updating component:`, error); } } - /** - * Resolve whether Spoolman is enabled for the current printer context. - * Mirrors the gating used by the Spoolman tracker component. - */ - private async refreshSpoolmanAvailability(): Promise { - if (!this.spoolmanEnabled || !window.api?.spoolman?.getStatus) { - this.spoolmanContextEnabled = false; - return; - } - - try { - const status = await window.api.spoolman.getStatus(this.contextId || undefined); - this.spoolmanContextEnabled = status.enabled; - } catch (error) { - console.error('[IFSStation] Failed to resolve Spoolman status:', error); - this.spoolmanContextEnabled = false; - } - } - /** * Check if component is running inside a dialog window */ @@ -442,77 +416,233 @@ export class IFSStationComponent extends BaseComponent { } /** - * Open a small editor popover for a slot offering "Set from Spoolman". - * Gated on Spoolman being enabled for the current context; otherwise no-op. + * Open the per-slot editor dialog: a modal with a material dropdown and a grid + * of the 24 recognized swatches. Pre-seeds from the slot's current material/ + * color. When Spoolman is enabled it also offers a "Set from Spoolman" button + * that pre-fills the dialog (the user still reviews and applies). */ - private openSlotEditor(slot: number, slotEl: HTMLElement): void { - // Only AD5X printers render this component, so the remaining gate is Spoolman. - if (!this.spoolmanEnabled || !this.spoolmanContextEnabled) { + private openSlotDialog(slot: number): void { + // Toggle: clicking the same slot while its dialog is open closes it. + if (this.dialogEl && this.pendingSlot === slot) { + this.closeSlotDialog(); return; } + this.closeSlotDialog(); + this.pendingSlot = slot; - // Toggle: clicking the same slot again closes the editor. - if (this.editorPopover && this.pendingSlot === slot) { - this.closeSlotEditor(); - return; - } + // Seed selections from the slot's current material/color, snapped to the palette. + const current = this.slots.find((s) => s.slotId === slot && !s.isEmpty); + const matchedMaterial = current?.materialType ? nearestMaterial(current.materialType) : null; + this.dialogMaterial = matchedMaterial ?? IFS_MATERIALS[0] ?? 'PLA'; + const matchedColor = current?.materialColor ? nearestColor(current.materialColor) : null; + this.dialogColorHex = matchedColor?.hex ?? null; + + const backdrop = document.createElement('div'); + backdrop.className = 'ifs-dialog-backdrop'; + + const dialog = document.createElement('div'); + dialog.className = 'ifs-dialog'; + dialog.setAttribute('role', 'dialog'); + dialog.setAttribute('aria-modal', 'true'); + + const materialOptions = IFS_MATERIALS.map( + (m) => `` + ).join(''); + + const swatches = IFS_COLORS.map( + (c) => + `` + ).join(''); + + dialog.innerHTML = ` +
+ Configure Slot ${slot} + +
+
+ +
+ Color +
${swatches}
+
+
+
+ + `; - this.closeSlotEditor(); + backdrop.appendChild(dialog); + document.body.appendChild(backdrop); + this.dialogEl = backdrop; - const popover = document.createElement('div'); - popover.className = 'ifs-slot-editor'; - popover.innerHTML = ` -
Slot ${slot}
- - `; + // Wire controls. + const select = dialog.querySelector('.ifs-dialog-material') as HTMLSelectElement | null; + select?.addEventListener('change', () => { + this.dialogMaterial = select.value; + this.updateDialogPreviewAndApply(); + }); - const actionBtn = popover.querySelector('.ifs-editor-action') as HTMLButtonElement | null; - actionBtn?.addEventListener('click', (e) => { - e.stopPropagation(); - void this.startSpoolPick(slot); + dialog.querySelectorAll('.ifs-swatch').forEach((el) => { + el.addEventListener('click', () => { + const hex = (el as HTMLElement).getAttribute('data-hex'); + if (hex) this.selectDialogColor(hex); + }); }); - slotEl.appendChild(popover); - this.editorPopover = popover; + (dialog.querySelector('.ifs-dialog-close') as HTMLElement | null)?.addEventListener('click', () => + this.closeSlotDialog() + ); + (dialog.querySelector('.ifs-dialog-cancel') as HTMLElement | null)?.addEventListener('click', () => + this.closeSlotDialog() + ); + (dialog.querySelector('.ifs-dialog-apply') as HTMLElement | null)?.addEventListener('click', () => + void this.applyManualSlot(slot) + ); - // Dismiss when clicking elsewhere within the component. - const onOutside = (e: MouseEvent): void => { - if (!popover.contains(e.target as Node)) { - this.closeSlotEditor(); - document.removeEventListener('click', onOutside, true); - } + // Click on the backdrop (outside the dialog) dismisses. + backdrop.addEventListener('click', (e) => { + if (e.target === backdrop) this.closeSlotDialog(); + }); + + // Escape dismisses. + this.dialogKeyHandler = (e: KeyboardEvent): void => { + if (e.key === 'Escape') this.closeSlotDialog(); }; - // Defer so the originating click doesn't immediately dismiss it. - setTimeout(() => document.addEventListener('click', onOutside, true), 0); + document.addEventListener('keydown', this.dialogKeyHandler, true); + + this.updateDialogPreviewAndApply(); + + // Resolve Spoolman availability live (config isn't pushed to components after + // creation), and inject the "Set from Spoolman" shortcut if it's enabled. + void this.maybeAddSpoolmanShortcut(slot, dialog); } /** - * Close the slot editor popover if open. + * If Spoolman is enabled and a server URL is configured, inject a "Set from + * Spoolman" shortcut into the open dialog's footer. Done asynchronously because + * Spoolman config is not delivered via polling updates. + * + * NOTE: this intentionally gates on the global Spoolman config (enabled + URL), + * NOT on `spoolman.getStatus()`. That status reflects active-spool *tracking* + * availability, which the backend disables for AD5X material-station printers — + * i.e. exactly the printers this slot-config feature targets. The spool picker + * only needs the integration enabled with a reachable server. */ - private closeSlotEditor(): void { - if (this.editorPopover) { - this.editorPopover.remove(); - this.editorPopover = null; + private async maybeAddSpoolmanShortcut(slot: number, dialog: HTMLElement): Promise { + if (!window.api?.config?.get) return; + + let enabled = false; + try { + const config = (await window.api.config.get()) as { + SpoolmanEnabled?: boolean; + SpoolmanServerUrl?: string; + } | null; + enabled = Boolean(config?.SpoolmanEnabled) && Boolean(config?.SpoolmanServerUrl); + } catch (error) { + console.error('[IFSStation] Spoolman config check failed:', error); + return; } + + // Bail if the dialog closed or switched slots while we awaited. + if (!enabled || !this.dialogEl || this.pendingSlot !== slot) return; + + const footer = dialog.querySelector('.ifs-dialog-footer'); + if (!footer || footer.querySelector('.ifs-dialog-spoolman')) return; + + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'ifs-dialog-spoolman'; + btn.textContent = 'Set from Spoolman'; + btn.addEventListener('click', () => void this.startSpoolPick()); + footer.insertBefore(btn, footer.firstChild); } /** - * Begin the Spoolman pick flow for a slot: register a one-shot listener for the - * chosen spool, then open the existing spool picker in slot-config mode. + * Mark a swatch as selected and refresh the preview/apply state. */ - private async startSpoolPick(slot: number): Promise { - if (!window.api?.spoolman) return; + private selectDialogColor(hex: string): void { + this.dialogColorHex = hex; + if (this.dialogEl) { + this.dialogEl.querySelectorAll('.ifs-swatch').forEach((el) => { + const btn = el as HTMLElement; + btn.classList.toggle('selected', btn.getAttribute('data-hex') === hex); + }); + } + this.updateDialogPreviewAndApply(); + } - this.closeSlotEditor(); - this.pendingSlot = slot; + /** + * Update the dialog preview line and enable Apply only once a color is chosen. + */ + private updateDialogPreviewAndApply(): void { + if (!this.dialogEl) return; + const preview = this.dialogEl.querySelector('.ifs-dialog-preview') as HTMLElement | null; + const applyBtn = this.dialogEl.querySelector('.ifs-dialog-apply') as HTMLButtonElement | null; + const colorName = this.dialogColorHex + ? (IFS_COLORS.find((c) => c.hex === this.dialogColorHex)?.name ?? this.dialogColorHex) + : null; + if (preview) { + preview.textContent = colorName + ? `Slot ${this.pendingSlot} → ${this.dialogMaterial} · ${colorName}` + : 'Pick a color to continue'; + } + if (applyBtn) applyBtn.disabled = !this.dialogColorHex; + } + + /** + * Apply the dialog's chosen material + color to the slot via the manual + * (Spoolman-independent) IPC path. The station refreshes on the next poll. + */ + private async applyManualSlot(slot: number): Promise { + if (!this.dialogColorHex || !this.dialogMaterial) return; - // Replace any stale listener. + if (!window.api?.material?.setSlot) { + window.api?.loading?.showError('Material control is not available', 4000); + return; + } + + const material = this.dialogMaterial; + const hex = this.dialogColorHex; + const colorName = IFS_COLORS.find((c) => c.hex === hex)?.name ?? hex; + this.closeSlotDialog(); + + try { + const result = await window.api.material.setSlot(slot, material, hex, this.contextId || undefined); + if (!result.success) { + window.api?.loading?.showError(result.error || 'Failed to configure slot', 5000); + return; + } + window.api?.loading?.showSuccess(`Slot ${slot} → ${material} · ${colorName}`, 4000); + } catch (error) { + console.error('[IFSStation] Failed to set slot:', error); + window.api?.loading?.showError( + error instanceof Error ? error.message : 'Failed to configure slot', + 5000 + ); + } + } + + /** + * Open the existing Spoolman picker (slot-config mode) and, once a spool is + * chosen, pre-fill the open dialog by snapping its material/color to the + * fixed palette. The dialog stays open so the user can review and apply. + */ + private async startSpoolPick(): Promise { + if (!window.api?.spoolman) return; + + // Replace any stale listener; register a one-shot for the chosen spool. this.spoolPickedDisposer?.(); this.spoolPickedDisposer = window.api.spoolman.onSpoolPickedForSlot((spool: unknown) => { - // One-shot: dispose immediately so reopening the picker doesn't double-fire. this.spoolPickedDisposer?.(); this.spoolPickedDisposer = null; - void this.applyPickedSpool(spool as PickedSpool); + this.prefillFromSpool(spool as PickedSpool); }); try { @@ -521,55 +651,31 @@ export class IFSStationComponent extends BaseComponent { console.error('[IFSStation] Failed to open spool picker:', error); this.spoolPickedDisposer?.(); this.spoolPickedDisposer = null; - this.pendingSlot = null; } } /** - * Apply the picked spool to the pending slot: snap + configure via IPC, confirm - * with the user, then show the result. The station refreshes via polling. + * Snap a picked spool's material/color to the fixed palette and pre-fill the + * open dialog. Material that does not resolve is left as the current choice. */ - private async applyPickedSpool(spool: PickedSpool): Promise { - const slot = this.pendingSlot; - this.pendingSlot = null; - - if (slot === null || !spool || typeof spool.id !== 'number') { - return; - } - - if (!window.api?.material?.configureSlot) { - window.api?.loading?.showError('Material control is not available', 4000); - return; + private prefillFromSpool(spool: PickedSpool): void { + if (!this.dialogEl || this.pendingSlot === null || !spool) return; + + if (spool.material) { + const matched = nearestMaterial(spool.material); + if (matched) { + this.dialogMaterial = matched; + const select = this.dialogEl.querySelector('.ifs-dialog-material') as HTMLSelectElement | null; + if (select) select.value = matched; + } } - // Desktop confirm step before writing to the printer. - const spoolLabel = spool.name || `spool ${spool.id}`; - const confirmed = window.confirm( - `Set Slot ${slot} from "${spoolLabel}"?\n\n` + - `Its material and color will be snapped to the printer's fixed palette and applied to the slot.` - ); - if (!confirmed) { - return; + if (spool.colorHex) { + const snapped = nearestColor(spool.colorHex); + if (snapped) this.selectDialogColor(snapped.hex); } - try { - const result = await window.api.material.configureSlot(slot, spool.id, this.contextId || undefined); - - if (!result.success) { - window.api?.loading?.showError(result.error || 'Failed to configure slot', 5000); - return; - } - - const spoolName = result.spoolName || spool.name || `spool ${spool.id}`; - window.api?.loading?.showSuccess( - `Slot ${result.slot ?? slot} → ${result.material ?? 'material kept'} · ${result.colorName ?? ''}, from ${spoolName}`, - 4000 - ); - // Station UI refreshes on the next poll cycle. - } catch (error) { - console.error('[IFSStation] Failed to apply spool to slot:', error); - window.api?.loading?.showError(error instanceof Error ? error.message : 'Failed to configure slot', 5000); - } + this.updateDialogPreviewAndApply(); } /** @@ -588,9 +694,25 @@ export class IFSStationComponent extends BaseComponent { this.resizeObserver = null; } + this.closeSlotDialog(); + } + + /** + * Close the slot editor dialog (if open) and tear down its listeners. + */ + private closeSlotDialog(): void { + if (this.dialogEl) { + this.dialogEl.remove(); + this.dialogEl = null; + } + if (this.dialogKeyHandler) { + document.removeEventListener('keydown', this.dialogKeyHandler, true); + this.dialogKeyHandler = null; + } this.spoolPickedDisposer?.(); this.spoolPickedDisposer = null; - this.closeSlotEditor(); this.pendingSlot = null; + this.dialogColorHex = null; + this.dialogMaterial = ''; } } diff --git a/src/shared/types/global.d.ts b/src/shared/types/global.d.ts index a6bed6e..257ee8d 100644 --- a/src/shared/types/global.d.ts +++ b/src/shared/types/global.d.ts @@ -130,6 +130,12 @@ interface ConfigureSlotResult { // Material station control API interface interface MaterialAPI { configureSlot(slot: number, spoolId: number, contextId?: string): Promise; + setSlot( + slot: number, + materialName: string, + colorHex: string, + contextId?: string + ): Promise; } interface ConfigAPI { From 5d0127ae16f96219a1c9b7bc88387a888dfd22af Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Mon, 22 Jun 2026 21:26:14 -0400 Subject: [PATCH 07/93] fix(connection): route printer model on USB product ID Discovery model detection was name-based: detectPrinterFamily only matched "5m"/"ad5x", so a Creator 5 fell through to the legacy connection path and failed with "Failed to establish final connection" despite speaking the same modern HTTP + check-code protocol. Route on the authoritative, firmware-set USB product ID (discovery packet offset 0x88) instead, falling back to the immutable Machine Type (TypeName) only for manual IP connections - never the user-editable Machine Name. - DiscoveredPrinter now carries productId/productType; PrinterDiscoveryService propagates them from the ff-api discovery result (previously dropped). - Add NEW_API_PRODUCT_IDS map and detectPrinterFamilyFromId / detectPrinterModelTypeFromId; use them in ConnectionFlowManager. - Cover PID-first routing with PrinterUtils tests. Co-Authored-By: Claude Opus 4.8 --- src/main/managers/ConnectionFlowManager.ts | 10 ++- src/main/managers/PrinterBackendManager.ts | 9 +++ src/main/services/PrinterDiscoveryService.ts | 4 + src/main/utils/PrinterUtils.ts | 73 ++++++++++++++++++- src/main/utils/__tests__/PrinterUtils.test.ts | 54 ++++++++++++++ .../printer-backend/backend-operations.ts | 8 +- src/shared/types/printer.ts | 4 + 7 files changed, 156 insertions(+), 6 deletions(-) create mode 100644 src/main/utils/__tests__/PrinterUtils.test.ts diff --git a/src/main/managers/ConnectionFlowManager.ts b/src/main/managers/ConnectionFlowManager.ts index 9e54c6c..1f4be17 100644 --- a/src/main/managers/ConnectionFlowManager.ts +++ b/src/main/managers/ConnectionFlowManager.ts @@ -48,7 +48,9 @@ import { getSavedPrinterService } from '../services/SavedPrinterService.js'; import { getThumbnailRequestQueue } from '../services/ThumbnailRequestQueue.js'; import { detectPrinterFamily, + detectPrinterFamilyFromId, detectPrinterModelType, + detectPrinterModelTypeFromId, determineClientType, formatPrinterName, getConnectionErrorMessage, @@ -547,8 +549,10 @@ export class ConnectionFlowManager extends EventEmitter { return { success: false, error: tempResult.error || 'Failed to determine printer type' }; } - // Step 2: Detect printer family and requirements - const familyInfo = detectPrinterFamily(tempResult.typeName); + // Step 2: Detect printer family and requirements. + // Prefer the authoritative USB product ID from discovery; fall back to the + // (user-mutable) typeName for manual IP connections that carry no product ID. + const familyInfo = detectPrinterFamilyFromId(discoveredPrinter.productId, tempResult.typeName); const clientType = determineClientType(familyInfo.is5MFamily); this.emit('printer-type-detected', { @@ -565,7 +569,7 @@ export class ConnectionFlowManager extends EventEmitter { // Step 3: Extract and validate printer information this.loadingManager.updateMessage('Processing printer details...'); - const modelType = detectPrinterModelType(tempResult.typeName); + const modelType = detectPrinterModelTypeFromId(discoveredPrinter.productId, tempResult.typeName); // Extract serial number from temporary connection if not already present let serialNumber = discoveredPrinter.serialNumber; diff --git a/src/main/managers/PrinterBackendManager.ts b/src/main/managers/PrinterBackendManager.ts index c89dd7e..122772f 100644 --- a/src/main/managers/PrinterBackendManager.ts +++ b/src/main/managers/PrinterBackendManager.ts @@ -303,6 +303,15 @@ export class PrinterBackendManager extends EventEmitter { case 'ad5x': return new AD5XBackend(backendOptions); + case 'creator-5': + case 'creator-5-pro': + // Creator 5 / 5 Pro speak the modern HTTP + check-code protocol. Until a + // dedicated tool-changer backend exists, use the plain 5M backend: it + // covers connect / status / temps / job control without polling the + // IFS-specific endpoints the AD5X backend expects (the Creator 5 has a + // tool changer, not a material station). + return new Adventurer5MBackend(backendOptions); + default: // Fallback to generic legacy for unknown models console.warn(`Unknown printer model: ${modelType}, falling back to generic legacy backend`); diff --git a/src/main/services/PrinterDiscoveryService.ts b/src/main/services/PrinterDiscoveryService.ts index c65ae26..686d3b7 100644 --- a/src/main/services/PrinterDiscoveryService.ts +++ b/src/main/services/PrinterDiscoveryService.ts @@ -73,6 +73,8 @@ export class PrinterDiscoveryService extends EventEmitter { serialNumber: printer.serialNumber || '', commandPort: printer.commandPort, eventPort: printer.eventPort, + productId: printer.productId, + productType: printer.productType, model: 'Unknown', // Will be determined during connection status: 'Discovered', })); @@ -113,6 +115,8 @@ export class PrinterDiscoveryService extends EventEmitter { serialNumber: matchingPrinter.serialNumber || '', commandPort: matchingPrinter.commandPort, eventPort: matchingPrinter.eventPort, + productId: matchingPrinter.productId, + productType: matchingPrinter.productType, model: 'Unknown', status: 'Discovered', }; diff --git a/src/main/utils/PrinterUtils.ts b/src/main/utils/PrinterUtils.ts index 71a566a..f75475e 100644 --- a/src/main/utils/PrinterUtils.ts +++ b/src/main/utils/PrinterUtils.ts @@ -49,6 +49,23 @@ import { PrinterClientType, PrinterFamilyInfo } from '@shared/types/printer.js'; import { PrinterModelType } from '@shared/types/printer-backend/index.js'; +/** + * Canonical USB Product IDs (discovery packet offset 0x88 / firmware `/detail` + * pid field / FlashForge update-checker keys) for "new API" printers — those + * that speak the HTTP 8898 + check-code protocol. + * + * This is the authoritative, user-immutable model discriminator. Prefer it over + * the printer name, which the user can freely rename. `productType` (0x5A02) + * only identifies the 5M *family* and cannot tell these models apart. + */ +export const NEW_API_PRODUCT_IDS: Readonly> = { + 0x0023: 'adventurer-5m', + 0x0024: 'adventurer-5m-pro', + 0x0026: 'ad5x', + 0x0028: 'creator-5', + 0x0029: 'creator-5-pro', +}; + /** * Detect specific printer model type from typeName * Returns detailed model information for backend selection @@ -67,12 +84,50 @@ export const detectPrinterModelType = (typeName: string): PrinterModelType => { return 'adventurer-5m'; } else if (typeNameLower.includes('ad5x')) { return 'ad5x'; + } else if (typeNameLower.includes('creator 5 pro')) { + return 'creator-5-pro'; + } else if (typeNameLower.includes('creator 5')) { + return 'creator-5'; } // Default to generic legacy for all other printers return 'generic-legacy'; }; +/** + * Detect the model type preferring the authoritative USB product ID, falling + * back to the (user-mutable) typeName only when no product ID is available + * (e.g. manual IP connections that never went through UDP discovery). + */ +export const detectPrinterModelTypeFromId = ( + productId: number | undefined, + typeName: string +): PrinterModelType => { + if (productId !== undefined && productId in NEW_API_PRODUCT_IDS) { + return NEW_API_PRODUCT_IDS[productId]; + } + return detectPrinterModelType(typeName); +}; + +/** + * Detect printer family preferring the authoritative USB product ID, falling + * back to the typeName when no product ID is available. Any printer in + * {@link NEW_API_PRODUCT_IDS} is a new-API printer that requires a check code. + */ +export const detectPrinterFamilyFromId = ( + productId: number | undefined, + typeName: string +): PrinterFamilyInfo => { + if (productId !== undefined && productId in NEW_API_PRODUCT_IDS) { + return { + is5MFamily: true, + requiresCheckCode: true, + familyName: getModelDisplayName(NEW_API_PRODUCT_IDS[productId]), + }; + } + return detectPrinterFamily(typeName); +}; + /** * Check if printer supports dual API usage * Modern printers (5M family) can use both new and legacy APIs @@ -92,6 +147,10 @@ export const getModelDisplayName = (modelType: PrinterModelType): string => { return 'Adventurer 5M'; case 'ad5x': return 'AD5X'; + case 'creator-5': + return 'Creator 5'; + case 'creator-5-pro': + return 'Creator 5 Pro'; case 'generic-legacy': default: return 'Legacy Printer'; @@ -152,8 +211,14 @@ export const detectPrinterFamily = (typeName: string): PrinterFamilyInfo => { const typeNameLower = typeName.toLowerCase(); - // Check for 5M family indicators - const is5MFamily = typeNameLower.includes('5m') || typeNameLower.includes('ad5x'); + // Check for new-API ("5M family") indicators. Creator 5 / 5 Pro speak the + // same HTTP + check-code protocol, so they belong here too. This name-based + // path is the fallback for manual connections; discovery-based connections + // route on the authoritative USB product ID via detectPrinterFamilyFromId. + const is5MFamily = + typeNameLower.includes('5m') || + typeNameLower.includes('ad5x') || + typeNameLower.includes('creator 5'); if (is5MFamily) { let familyName = 'Adventurer 5M Family'; @@ -164,6 +229,10 @@ export const detectPrinterFamily = (typeName: string): PrinterFamilyInfo => { familyName = 'Adventurer 5M'; } else if (typeNameLower.includes('ad5x')) { familyName = 'AD5X'; + } else if (typeNameLower.includes('creator 5 pro')) { + familyName = 'Creator 5 Pro'; + } else if (typeNameLower.includes('creator 5')) { + familyName = 'Creator 5'; } return { diff --git a/src/main/utils/__tests__/PrinterUtils.test.ts b/src/main/utils/__tests__/PrinterUtils.test.ts new file mode 100644 index 0000000..9fa348f --- /dev/null +++ b/src/main/utils/__tests__/PrinterUtils.test.ts @@ -0,0 +1,54 @@ +/** + * @fileoverview Tests for product-ID-first printer family/model detection. + * + * The discovery USB product ID (offset 0x88) is the authoritative, immutable + * model discriminator. These tests lock in that it is preferred over the + * firmware Machine Type string, and that Creator 5 / 5 Pro route as new-API + * printers rather than falling through to the legacy path. + */ +import { + detectPrinterFamilyFromId, + detectPrinterModelTypeFromId, +} from '../PrinterUtils.js'; + +describe('detectPrinterModelTypeFromId', () => { + it('resolves modern models from the USB product ID', () => { + expect(detectPrinterModelTypeFromId(0x0023, '')).toBe('adventurer-5m'); + expect(detectPrinterModelTypeFromId(0x0024, '')).toBe('adventurer-5m-pro'); + expect(detectPrinterModelTypeFromId(0x0026, '')).toBe('ad5x'); + expect(detectPrinterModelTypeFromId(0x0028, '')).toBe('creator-5'); + expect(detectPrinterModelTypeFromId(0x0029, '')).toBe('creator-5-pro'); + }); + + it('prefers the product ID over the Machine Type string', () => { + // Even if a future firmware reported an odd type name, the PID wins. + expect(detectPrinterModelTypeFromId(0x0024, 'Adventurer 5M')).toBe('adventurer-5m-pro'); + }); + + it('falls back to the immutable Machine Type when no product ID is present', () => { + expect(detectPrinterModelTypeFromId(undefined, 'Adventurer 5M Pro')).toBe('adventurer-5m-pro'); + expect(detectPrinterModelTypeFromId(undefined, 'Creator 5 Pro')).toBe('creator-5-pro'); + expect(detectPrinterModelTypeFromId(undefined, 'Adventurer 3')).toBe('generic-legacy'); + }); +}); + +describe('detectPrinterFamilyFromId', () => { + it('classifies Creator 5 / 5 Pro as new-API printers requiring a check code', () => { + for (const pid of [0x0028, 0x0029]) { + const family = detectPrinterFamilyFromId(pid, ''); + expect(family.is5MFamily).toBe(true); + expect(family.requiresCheckCode).toBe(true); + } + }); + + it('classifies all known modern PIDs as 5M family', () => { + for (const pid of [0x0023, 0x0024, 0x0026, 0x0028, 0x0029]) { + expect(detectPrinterFamilyFromId(pid, '').is5MFamily).toBe(true); + } + }); + + it('falls back to the Machine Type for manual (no-PID) connections', () => { + expect(detectPrinterFamilyFromId(undefined, 'Creator 5').is5MFamily).toBe(true); + expect(detectPrinterFamilyFromId(undefined, 'Adventurer 4').is5MFamily).toBe(false); + }); +}); diff --git a/src/shared/types/printer-backend/backend-operations.ts b/src/shared/types/printer-backend/backend-operations.ts index d086db5..4117b04 100644 --- a/src/shared/types/printer-backend/backend-operations.ts +++ b/src/shared/types/printer-backend/backend-operations.ts @@ -24,7 +24,13 @@ import { MaterialStationStatus, PrinterFeatureSet } from './printer-features.js' /** * Printer model types supported by the backend system */ -export type PrinterModelType = 'generic-legacy' | 'adventurer-5m' | 'adventurer-5m-pro' | 'ad5x'; +export type PrinterModelType = + | 'generic-legacy' + | 'adventurer-5m' + | 'adventurer-5m-pro' + | 'ad5x' + | 'creator-5' + | 'creator-5-pro'; /** * Backend initialization options diff --git a/src/shared/types/printer.ts b/src/shared/types/printer.ts index b001408..eaaffab 100644 --- a/src/shared/types/printer.ts +++ b/src/shared/types/printer.ts @@ -67,6 +67,10 @@ export interface DiscoveredPrinter { readonly firmwareVersion?: string; readonly commandPort?: number; readonly eventPort?: number; + /** USB product ID from the discovery packet (offset 0x88). Authoritative model id. */ + readonly productId?: number; + /** Product type from the discovery packet (e.g. 0x5A02 = 5M family). */ + readonly productType?: number; } /** From bbce79a79b2ba4e739e9aa23bca4259612433218 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:57:09 -0400 Subject: [PATCH 08/93] feat(creator5): add Creator 5 / 5 Pro backend, tool-temp card, and routing Route the Creator 5 series to a dedicated backend and surface its per-tool temperatures in the UI. Builds on @ghosttypes/ff-api 1.3.4. - Creator5Backend extends AD5XBackend: inherits the 4-slot material station and dual HTTP + TCP transport, and adds per-tool nozzle temps in status, built-in camera, a Creator 5 Pro filtration override (its /product under-reports the fans), door-sensor gating (Pro only), and native /printGcode job starting. - Route creator-5 / creator-5-pro to Creator5Backend (was the interim 5M backend). - Add a tool-temps grid component showing the 4 nozzle temperatures; register it in the component catalog and both component factories. - Thread toolTemps through PrinterStatus and PrinterDataTransformer so the card (and the web UI's status data) receive per-tool temperatures. - Bump @ghosttypes/ff-api to ^1.3.4. Co-Authored-By: Claude Opus 4.8 --- package.json | 2 +- pnpm-lock.yaml | 133 +++++++++--- src/main/managers/PrinterBackendManager.ts | 12 +- src/main/printer-backends/Creator5Backend.ts | 196 ++++++++++++++++++ src/main/services/PrinterDataTransformer.ts | 38 +++- src/renderer/src/renderer/gridController.ts | 3 + .../ui/component-dialog/component-dialog.ts | 3 + src/renderer/src/ui/components/index.ts | 1 + .../src/ui/components/tool-temps/index.ts | 10 + .../ui/components/tool-temps/tool-temps.css | 97 +++++++++ .../ui/components/tool-temps/tool-temps.ts | 110 ++++++++++ src/shared/component-definitions.ts | 12 ++ src/shared/types/polling.ts | 6 + 13 files changed, 588 insertions(+), 35 deletions(-) create mode 100644 src/main/printer-backends/Creator5Backend.ts create mode 100644 src/renderer/src/ui/components/tool-temps/index.ts create mode 100644 src/renderer/src/ui/components/tool-temps/tool-temps.css create mode 100644 src/renderer/src/ui/components/tool-temps/tool-temps.ts diff --git a/package.json b/package.json index 7d2a9ac..c24540a 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ } }, "dependencies": { - "@ghosttypes/ff-api": "^1.3.2", + "@ghosttypes/ff-api": "^1.3.4", "@parallel-7/slicer-meta": "1.3.0", "electron-log": "^5.4.3", "electron-updater": "^6.8.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 70ce180..62eef89 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,8 +30,8 @@ importers: .: dependencies: '@ghosttypes/ff-api': - specifier: ^1.3.2 - version: 1.3.2 + specifier: ^1.3.4 + version: 1.3.4 '@parallel-7/slicer-meta': specifier: 1.3.0 version: 1.3.0 @@ -116,7 +116,7 @@ importers: version: 26.8.1(electron-builder-squirrel-windows@26.5.0) electron-vite: specifier: ^4.0.1 - version: 4.0.1(vite@7.3.3(@types/node@20.19.35)(jiti@2.6.1)(tsx@4.21.0)) + version: 4.0.1(vite@7.3.3(@types/node@20.19.35)(jiti@2.7.0)(tsx@4.21.0)) identity-obj-proxy: specifier: ^3.0.0 version: 3.0.0 @@ -146,7 +146,7 @@ importers: version: 5.9.3 vite: specifier: ^7.3.2 - version: 7.3.3(@types/node@20.19.35)(jiti@2.6.1)(tsx@4.21.0) + version: 7.3.3(@types/node@20.19.35)(jiti@2.7.0)(tsx@4.21.0) packages: @@ -1242,8 +1242,8 @@ packages: cpu: [x64] os: [win32] - '@ghosttypes/ff-api@1.3.2': - resolution: {integrity: sha512-FRm+pQUik18tjxZmfCgy+rFQHTcoRQpfsK+Xtu1s+RU0YGzqLnx6TaIf3me18Gyif7FE07N8wKivyDKkQZf6Mg==, tarball: https://npm.pkg.github.com/download/@ghosttypes/ff-api/1.3.2/8038c85264ee52e84beedb28dc401c568618f50e} + '@ghosttypes/ff-api@1.3.4': + resolution: {integrity: sha512-ABBs/Jme//Kyrvpz7puvFCBuvjfIOFONoYcWyFolX94zF8uh5lKOWqdu6QkHmyV+YJmSfKbcR78rCf+rzrFskg==, tarball: https://npm.pkg.github.com/download/@ghosttypes/ff-api/1.3.4/7d83ca1de9d752cd9dad611d23746e8282e8d9e0} '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -1600,6 +1600,9 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -2448,8 +2451,8 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} forwarded@0.2.0: @@ -2468,6 +2471,10 @@ packages: resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} engines: {node: '>=14.14'} + fs-extra@11.3.5: + resolution: {integrity: sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==} + engines: {node: '>=14.14'} + fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -2593,6 +2600,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} @@ -2917,6 +2928,10 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2961,6 +2976,9 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + jsonfile@6.2.1: + resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -3100,6 +3118,10 @@ packages: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} @@ -3175,6 +3197,10 @@ packages: resolution: {integrity: sha512-8QwIZqikRvDIkXS2S93LjzhsSPJuIbfaMETWH+Bx8oOT9Sa9UsUtBFQlc3gBNd1+QINjaTloitXr1W3dQLi9Iw==} engines: {node: '>=22.12.0'} + node-abi@4.31.0: + resolution: {integrity: sha512-Erq5w/t3syw3s4sDsUaX4QttIdBPsGKTT1DTRsCkTonGggczhlDKm/wDX3o+HPJpQ41EjXCbcmXf0tgr5YZJXw==} + engines: {node: '>=22.12.0'} + node-addon-api@1.7.2: resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==} @@ -3535,6 +3561,9 @@ packages: sanitize-filename@1.6.3: resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==} + sanitize-filename@1.6.4: + resolution: {integrity: sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg==} + sax@1.5.0: resolution: {integrity: sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==} engines: {node: '>=11.0.0'} @@ -4096,6 +4125,10 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} + engines: {node: '>=12'} + yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} @@ -5060,14 +5093,14 @@ snapshots: detect-libc: 2.1.2 got: 11.8.6 graceful-fs: 4.2.11 - node-abi: 4.26.0 + node-abi: 4.31.0 node-api-version: 0.2.1 node-gyp: 11.5.0 ora: 5.4.1 read-binary-file-arch: 1.0.6 semver: 7.7.4 tar: 7.5.12 - yargs: 17.7.2 + yargs: 17.7.3 transitivePeerDependencies: - supports-color @@ -5105,7 +5138,7 @@ snapshots: dependencies: cross-dirname: 0.1.0 debug: 4.4.3 - fs-extra: 11.3.4 + fs-extra: 11.3.5 minimist: 1.2.8 postject: 1.0.0-alpha.6 transitivePeerDependencies: @@ -5268,10 +5301,10 @@ snapshots: '@esbuild/win32-x64@0.27.3': optional: true - '@ghosttypes/ff-api@1.3.2': + '@ghosttypes/ff-api@1.3.4': dependencies: axios: 1.16.1 - form-data: 4.0.5 + form-data: 4.0.6 transitivePeerDependencies: - debug - supports-color @@ -5733,6 +5766,10 @@ snapshots: dependencies: '@types/ms': 2.1.0 + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + '@types/estree@1.0.8': {} '@types/express-serve-static-core@4.19.8': @@ -5938,11 +5975,11 @@ snapshots: fs-extra: 10.1.0 hosted-git-info: 4.1.0 isbinaryfile: 5.0.7 - jiti: 2.6.1 + jiti: 2.7.0 js-yaml: 4.1.1 json5: 2.2.3 lazy-val: 1.0.5 - minimatch: 10.2.4 + minimatch: 10.2.5 plist: 3.1.0 resedit: 1.7.2 semver: 7.7.4 @@ -6021,7 +6058,7 @@ snapshots: axios@1.16.1: dependencies: follow-redirects: 1.16.0 - form-data: 4.0.5 + form-data: 4.0.6 https-proxy-agent: 5.0.1 proxy-from-env: 2.1.0 transitivePeerDependencies: @@ -6197,7 +6234,7 @@ snapshots: builder-util@26.4.1: dependencies: 7zip-bin: 5.2.0 - '@types/debug': 4.1.12 + '@types/debug': 4.1.13 app-builder-bin: 5.0.0-alpha.12 builder-util-runtime: 9.5.1 chalk: 4.1.2 @@ -6207,7 +6244,7 @@ snapshots: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 js-yaml: 4.1.1 - sanitize-filename: 1.6.3 + sanitize-filename: 1.6.4 source-map-support: 0.5.21 stat-mode: 1.0.0 temp-file: 3.4.0 @@ -6560,7 +6597,7 @@ snapshots: builder-util: 26.4.1 builder-util-runtime: 9.5.1 chalk: 4.1.2 - form-data: 4.0.5 + form-data: 4.0.6 fs-extra: 10.1.0 lazy-val: 1.0.5 mime: 2.6.0 @@ -6573,7 +6610,7 @@ snapshots: builder-util: 26.8.1 builder-util-runtime: 9.5.1 chalk: 4.1.2 - form-data: 4.0.5 + form-data: 4.0.6 fs-extra: 10.1.0 lazy-val: 1.0.5 mime: 2.6.0 @@ -6595,7 +6632,7 @@ snapshots: transitivePeerDependencies: - supports-color - electron-vite@4.0.1(vite@7.3.3(@types/node@20.19.35)(jiti@2.6.1)(tsx@4.21.0)): + electron-vite@4.0.1(vite@7.3.3(@types/node@20.19.35)(jiti@2.7.0)(tsx@4.21.0)): dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) @@ -6603,7 +6640,7 @@ snapshots: esbuild: 0.25.12 magic-string: 0.30.21 picocolors: 1.1.1 - vite: 7.3.3(@types/node@20.19.35)(jiti@2.6.1)(tsx@4.21.0) + vite: 7.3.3(@types/node@20.19.35)(jiti@2.7.0)(tsx@4.21.0) transitivePeerDependencies: - supports-color @@ -6667,7 +6704,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 es6-error@4.1.1: optional: true @@ -6873,12 +6910,12 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.5: + form-data@4.0.6: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 es-set-tostringtag: 2.1.0 - hasown: 2.0.2 + hasown: 2.0.4 mime-types: 2.1.35 forwarded@0.2.0: {} @@ -6897,6 +6934,13 @@ snapshots: jsonfile: 6.2.0 universalify: 2.0.1 + fs-extra@11.3.5: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + optional: true + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.11 @@ -7052,6 +7096,10 @@ snapshots: dependencies: function-bind: 1.1.2 + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + hosted-git-info@4.1.0: dependencies: lru-cache: 6.0.0 @@ -7573,6 +7621,8 @@ snapshots: jiti@2.6.1: {} + jiti@2.7.0: {} + js-tokens@4.0.0: {} js-yaml@4.1.1: @@ -7629,6 +7679,13 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jsonfile@6.2.1: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + optional: true + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -7748,6 +7805,10 @@ snapshots: dependencies: brace-expansion: 5.0.6 + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.6 + minimatch@3.1.5: dependencies: brace-expansion: 1.1.13 @@ -7817,6 +7878,10 @@ snapshots: dependencies: semver: 7.7.4 + node-abi@4.31.0: + dependencies: + semver: 7.7.4 + node-addon-api@1.7.2: optional: true @@ -8202,6 +8267,10 @@ snapshots: dependencies: truncate-utf8-bytes: 1.0.2 + sanitize-filename@1.6.4: + dependencies: + truncate-utf8-bytes: 1.0.2 + sax@1.5.0: {} saxes@6.0.0: @@ -8614,7 +8683,7 @@ snapshots: extsprintf: 1.4.1 optional: true - vite@7.3.3(@types/node@20.19.35)(jiti@2.6.1)(tsx@4.21.0): + vite@7.3.3(@types/node@20.19.35)(jiti@2.7.0)(tsx@4.21.0): dependencies: esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.4) @@ -8625,7 +8694,7 @@ snapshots: optionalDependencies: '@types/node': 20.19.35 fsevents: 2.3.3 - jiti: 2.6.1 + jiti: 2.7.0 tsx: 4.21.0 w3c-xmlserializer@5.0.0: @@ -8712,6 +8781,16 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yargs@17.7.3: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yauzl@2.10.0: dependencies: buffer-crc32: 0.2.13 diff --git a/src/main/managers/PrinterBackendManager.ts b/src/main/managers/PrinterBackendManager.ts index 122772f..41e87c3 100644 --- a/src/main/managers/PrinterBackendManager.ts +++ b/src/main/managers/PrinterBackendManager.ts @@ -47,6 +47,7 @@ import { EventEmitter } from 'events'; import { AD5XBackend } from '../printer-backends/AD5XBackend.js'; import { Adventurer5MBackend } from '../printer-backends/Adventurer5MBackend.js'; import { Adventurer5MProBackend } from '../printer-backends/Adventurer5MProBackend.js'; +import { Creator5Backend } from '../printer-backends/Creator5Backend.js'; import { BasePrinterBackend } from '../printer-backends/BasePrinterBackend.js'; import { GenericLegacyBackend } from '../printer-backends/GenericLegacyBackend.js'; import { detectPrinterModelType, getModelDisplayName } from '../utils/PrinterUtils.js'; @@ -305,12 +306,11 @@ export class PrinterBackendManager extends EventEmitter { case 'creator-5': case 'creator-5-pro': - // Creator 5 / 5 Pro speak the modern HTTP + check-code protocol. Until a - // dedicated tool-changer backend exists, use the plain 5M backend: it - // covers connect / status / temps / job control without polling the - // IFS-specific endpoints the AD5X backend expects (the Creator 5 has a - // tool changer, not a material station). - return new Adventurer5MBackend(backendOptions); + // Creator 5 / 5 Pro = "AD5X + per-tool temps": same 4-slot material + // station and dual HTTP + TCP protocol, plus a 4-nozzle tool array and + // (on the Pro) camera/LED/filtration. Creator5Backend extends the AD5X + // backend and gates the Pro-only capabilities. + return new Creator5Backend(backendOptions); default: // Fallback to generic legacy for unknown models diff --git a/src/main/printer-backends/Creator5Backend.ts b/src/main/printer-backends/Creator5Backend.ts new file mode 100644 index 0000000..1680130 --- /dev/null +++ b/src/main/printer-backends/Creator5Backend.ts @@ -0,0 +1,196 @@ +/** + * @fileoverview Backend implementation for Creator 5 / Creator 5 Pro printers. + * + * The Creator 5 series is functionally "AD5X + per-tool temperatures": it has the + * same 4-slot material station and material-mapping print flow as the AD5X, plus a + * 4-nozzle tool array and (on the Pro) 5M-Pro-style camera/LED/filtration hardware. + * + * This backend therefore extends {@link AD5XBackend} to inherit the material-station + * machinery (monitoring, slot configuration, multi-color job starting, recent-job + * handling) and the dual HTTP + TCP transport, and layers on: + * - Per-tool nozzle temperatures (`toolTemps`) surfaced in status. + * - Camera enabled (both Creator 5 and Creator 5 Pro have a built-in camera; the + * stream URL is detected at runtime from the printer's `cameraStreamUrl`). + * - Filtration / aux fan forced on for the Creator 5 Pro, whose `/product` response + * under-reports the fan control states despite the hardware being present. + * - Door-sensor capability gated to the Creator 5 Pro only (the plain Creator 5 has + * no real sensor, so its door status is cosmetic and must not be surfaced). + * + * Key exports: + * - Creator5Backend class: Backend for Creator 5 / Creator 5 Pro printers + */ + +import { + type Creator5MaterialMapping, + type FFMachineInfo, +} from '@ghosttypes/ff-api'; +import { + JobOperationParams, + JobStartResult, + PrinterFeatureSet, +} from '@shared/types/printer-backend/index.js'; +import { AD5XBackend } from './AD5XBackend.js'; + +/** + * Backend implementation for the Creator 5 / Creator 5 Pro. + * Extends the AD5X backend (shared material station + dual API) and adds the + * Creator 5's per-tool temperatures and Pro-only hardware capabilities. + */ +export class Creator5Backend extends AD5XBackend { + /** + * Whether this specific printer is a Creator 5 Pro (vs a plain Creator 5). + * Drives the Pro-only capabilities: real door sensor and filtration/aux fan. + */ + private isCreator5Pro(): boolean { + return this.modelType === 'creator-5-pro'; + } + + /** + * Child-specific base features for the Creator 5 series. + * + * Mirrors the AD5X material-station feature set, but enables the built-in + * camera (present on both Creator 5 and Creator 5 Pro). LED and filtration are + * resolved by {@link getBaseFeatures} from the product endpoint (with a Pro + * filtration override applied there). + */ + protected getChildBaseFeatures(): PrinterFeatureSet { + const features = super.getChildBaseFeatures(); + + return { + ...features, + // Both Creator 5 and Creator 5 Pro have a built-in camera; the OEM stream + // URL is populated at runtime from the printer's reported cameraStreamUrl. + camera: { + ...features.camera, + builtin: true, + }, + }; + } + + /** + * Resolve full feature set, then apply Creator 5 Pro hardware overrides. + * + * The base {@link DualAPIBackend.getBaseFeatures} derives filtration from the + * product endpoint, but the Creator 5 Pro under-reports its fan control states + * (both 0) despite shipping with 5M-Pro-style filtration / aux fan. Force it on + * by model so the control surfaces. The plain Creator 5 keeps the product-derived + * value. + */ + protected getBaseFeatures(): PrinterFeatureSet { + const features = super.getBaseFeatures(); + + if (this.isCreator5Pro()) { + return { + ...features, + filtration: { + available: true, + controllable: true, + reason: 'Creator 5 Pro has built-in filtration / aux fan', + }, + }; + } + + return features; + } + + /** + * Surface Creator 5-specific status fields on top of the AD5X/base status. + * + * Adds the per-tool nozzle temperature array and the door-sensor capability so + * the renderer can show a 4-tool temperature grid and only present door status + * when a real sensor exists (Creator 5 Pro). + */ + protected getAdditionalStatusFields(machineInfo: unknown): Record { + const base = super.getAdditionalStatusFields(machineInfo); + const info = machineInfo as Partial | null; + + return { + ...base, + // Per-tool current/target temperatures (4 entries on the Creator 5 series). + toolTemps: info?.ToolTemps ?? [], + // Capability flags for the renderer to gate UI. + isCreator5Pro: this.isCreator5Pro(), + hasDoorSensor: info?.HasDoorSensor ?? this.isCreator5Pro(), + }; + } + + /** + * Start a job on the Creator 5 / Creator 5 Pro. + * + * Overrides {@link AD5XBackend.startJob} to use the Creator 5-native start + * command: the Creator 5 performs material matching at print-start + * (`POST /printGcode`) rather than at upload time. File uploads reuse the shared + * upload path; starting an already-uploaded local file uses `startCreator5Job` + * with optional per-tool material mappings. + */ + public async startJob(params: JobOperationParams): Promise { + try { + // File upload case (optionally auto-start). Material matching for a + // multi-tool file is done via a follow-up start with mappings. + if (params.filePath) { + const success = await this.fiveMClient.jobControl.uploadFile( + params.filePath, + params.startNow, + params.leveling + ); + if (!success) { + throw new Error('Failed to upload and start job'); + } + return { + success: true, + fileName: params.fileName || params.filePath, + started: params.startNow, + timestamp: new Date(), + }; + } + + if (!params.fileName) { + throw new Error('fileName or filePath is required'); + } + + // Upload-only request (start handled separately by the caller). + if (!params.startNow) { + return { + success: true, + fileName: params.fileName, + started: false, + timestamp: new Date(), + }; + } + + const materialMappings = params.additionalParams?.materialMappings as + | Creator5MaterialMapping[] + | undefined; + + const success = await this.fiveMClient.jobControl.startCreator5Job({ + fileName: params.fileName, + levelingBeforePrint: params.leveling, + materialMappings: + materialMappings && materialMappings.length > 0 ? materialMappings : undefined, + }); + + if (!success) { + throw new Error('Failed to start Creator 5 job'); + } + + return { + success: true, + fileName: params.fileName, + started: true, + timestamp: new Date(), + }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + fileName: params.fileName || '', + started: false, + timestamp: new Date(), + }; + } + } + + protected getMaterialStationSlotCount(): number { + return 4; // Creator 5 material station has 4 slots + } +} diff --git a/src/main/services/PrinterDataTransformer.ts b/src/main/services/PrinterDataTransformer.ts index 7b18fb0..4518fba 100644 --- a/src/main/services/PrinterDataTransformer.ts +++ b/src/main/services/PrinterDataTransformer.ts @@ -21,7 +21,13 @@ * or malformed data gracefully. */ -import type { CurrentJobInfo, MaterialSlot, MaterialStationStatus, PrinterStatus } from '@shared/types/polling.js'; +import type { + CurrentJobInfo, + MaterialSlot, + MaterialStationStatus, + PrinterStatus, + TemperatureData, +} from '@shared/types/polling.js'; import { secondsToMinutes } from '@shared/utils/time.utils.js'; import { hasValue, @@ -79,6 +85,10 @@ export class PrinterDataTransformer { const nozzleTemp = safeExtractNumber(backendData, 'nozzleTemperature', 0); const nozzleTarget = safeExtractNumber(backendData, 'nozzleTargetTemperature', 0); + // Per-tool nozzle temperatures (Creator 5 series). The backend surfaces these + // as `toolTemps: { current, set }[]`; map to the UI TemperatureData shape. + const toolTemps = this.extractToolTemps(backendData); + // Extract current job info const currentJobName = safeExtractString(backendData, 'currentJob', ''); const currentJob = this.extractCurrentJob(backendData, state, currentJobName); @@ -115,6 +125,7 @@ export class PrinterDataTransformer { isHeating: nozzleTarget > 0 && Math.abs(nozzleTemp - nozzleTarget) > 2, }, }, + ...(toolTemps.length > 0 ? { toolTemps } : {}), fans: { coolingFan: coolingFanSpeed, chamberFan: chamberFanSpeed, @@ -301,6 +312,31 @@ export class PrinterDataTransformer { /** * Extract filtration status from backend data */ + /** + * Extract per-tool nozzle temperatures from the backend status. + * + * The Creator 5 backend surfaces `toolTemps` as an array of `{ current, set }` + * (ff-api Temperature). Map each to the UI TemperatureData shape. Returns an + * empty array for single-nozzle printers that don't report it. + */ + private extractToolTemps(backendData: Record): TemperatureData[] { + const raw = backendData.toolTemps; + if (!Array.isArray(raw)) { + return []; + } + + return raw.map((entry) => { + const tool = isValidObject(entry) ? entry : {}; + const current = safeExtractNumber(tool, 'current', 0); + const target = safeExtractNumber(tool, 'set', 0); + return { + current, + target, + isHeating: target > 0 && Math.abs(current - target) > 2, + }; + }); + } + private extractFiltrationStatus(backendData: Record): { hasFiltration?: boolean; filtrationMode?: 'external' | 'internal' | 'none'; diff --git a/src/renderer/src/renderer/gridController.ts b/src/renderer/src/renderer/gridController.ts index 9b06efa..d6546fb 100644 --- a/src/renderer/src/renderer/gridController.ts +++ b/src/renderer/src/renderer/gridController.ts @@ -23,6 +23,7 @@ import { PrinterStatusComponent, SpoolmanComponent, TemperatureControlsComponent, + ToolTempsComponent, } from '../ui/components/index.js'; import { getComponentDefinition } from '../ui/gridstack/ComponentRegistry.js'; import { editModeController } from '../ui/gridstack/EditModeController.js'; @@ -433,6 +434,8 @@ export class RendererGridController { return new SpoolmanComponent(container); case 'ifs-station': return new IFSStationComponent(container); + case 'tool-temps': + return new ToolTempsComponent(container); default: console.error(`Unknown component ID: ${componentId}`); return null; diff --git a/src/renderer/src/ui/component-dialog/component-dialog.ts b/src/renderer/src/ui/component-dialog/component-dialog.ts index c35d88a..caded76 100644 --- a/src/renderer/src/ui/component-dialog/component-dialog.ts +++ b/src/renderer/src/ui/component-dialog/component-dialog.ts @@ -36,6 +36,7 @@ import { PrinterStatusComponent, SpoolmanComponent, TemperatureControlsComponent, + ToolTempsComponent, } from '../components/index.js'; import { getComponentDefinition } from '../gridstack/ComponentRegistry.js'; import { parseLogEntry } from '../shared/log-panel/index.js'; @@ -194,6 +195,8 @@ function createComponentInstance(componentId: string, container: HTMLElement) { return new SpoolmanComponent(container); case 'ifs-station': return new IFSStationComponent(container); + case 'tool-temps': + return new ToolTempsComponent(container); default: console.error(`[ComponentDialog] Unknown component ID: ${componentId}`); return null; diff --git a/src/renderer/src/ui/components/index.ts b/src/renderer/src/ui/components/index.ts index fdd5731..9926a80 100644 --- a/src/renderer/src/ui/components/index.ts +++ b/src/renderer/src/ui/components/index.ts @@ -38,3 +38,4 @@ export { PrinterTabsComponent } from './printer-tabs/index.js'; // Spoolman Integration Component export { SpoolmanComponent } from './spoolman/index.js'; export { TemperatureControlsComponent } from './temperature-controls/index.js'; +export { ToolTempsComponent } from './tool-temps/index.js'; diff --git a/src/renderer/src/ui/components/tool-temps/index.ts b/src/renderer/src/ui/components/tool-temps/index.ts new file mode 100644 index 0000000..83e882b --- /dev/null +++ b/src/renderer/src/ui/components/tool-temps/index.ts @@ -0,0 +1,10 @@ +/** + * @fileoverview Tool Temperatures Component Exports + * + * Central export point for the per-tool nozzle temperature grid component + * (Creator 5 series). + * + * @module ui/components/tool-temps + */ + +export { ToolTempsComponent } from './tool-temps.js'; diff --git a/src/renderer/src/ui/components/tool-temps/tool-temps.css b/src/renderer/src/ui/components/tool-temps/tool-temps.css new file mode 100644 index 0000000..16c9898 --- /dev/null +++ b/src/renderer/src/ui/components/tool-temps/tool-temps.css @@ -0,0 +1,97 @@ +/** + * @fileoverview Tool Temperatures Component Styles + * + * Responsive grid of per-tool nozzle temperature cells for multi-tool printers + * (Creator 5 series). Visual language mirrors the IFS material-station card. + */ + +.component-tool-temps { + width: 100%; + height: 100%; +} + +.tool-temps { + width: 100%; + height: 100%; + box-sizing: border-box; + display: flex; + flex-direction: column; +} + +.tool-temps-unavailable { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + padding: 8px; + color: var(--text-color-muted); + font-size: 0.85em; +} + +.tool-temps-grid { + flex: 1; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(72px, 1fr)); + gap: 8px; + padding: 8px; + box-sizing: border-box; +} + +.tool-temp-cell { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 4px; + padding: 8px 4px; + border: 1px solid var(--border-color); + border-radius: 6px; + background: var(--card-bg); + transition: var(--transition-normal); +} + +.tool-temp-cell.is-active { + border-color: var(--accent-color); +} + +.tool-temp-cell.is-heating { + border-color: #ff7a45; + box-shadow: 0 0 6px rgba(255, 122, 69, 0.5); +} + +.tool-temp-label { + font-size: 0.78em; + font-weight: 600; + color: var(--text-color-muted); + letter-spacing: 0.04em; +} + +.tool-temp-value { + display: flex; + align-items: baseline; + gap: 2px; + color: var(--text-color); + font-variant-numeric: tabular-nums; +} + +.tool-temp-current { + font-size: 1.1em; + font-weight: 600; +} + +.tool-temp-cell.is-heating .tool-temp-current { + color: #ff7a45; +} + +.tool-temp-sep, +.tool-temp-target { + color: var(--text-color-muted); + font-size: 0.9em; +} + +.tool-temp-unit { + font-size: 0.7em; + color: var(--text-color-muted); + margin-left: 1px; +} diff --git a/src/renderer/src/ui/components/tool-temps/tool-temps.ts b/src/renderer/src/ui/components/tool-temps/tool-temps.ts new file mode 100644 index 0000000..5c8be61 --- /dev/null +++ b/src/renderer/src/ui/components/tool-temps/tool-temps.ts @@ -0,0 +1,110 @@ +/** + * @fileoverview Tool Temperatures Component + * + * GridStack component that displays per-tool nozzle temperatures for multi-tool + * printers (Creator 5 series — 4 nozzles). Renders a responsive grid of tool + * cells, each showing the current and target temperature and a heating state, + * mirroring the visual language of the IFS material-station card. + * + * Data source: `pollingData.printerStatus.toolTemps` (one entry per nozzle). + * Single-nozzle printers don't report this, so the card shows an "unavailable" + * state for them. + * + * @module ui/components/tool-temps + */ + +import type { PrinterStatus, TemperatureData } from '@shared/types/polling.js'; +import { BaseComponent } from '../base/component.js'; +import type { ComponentUpdateData } from '../base/types.js'; +import './tool-temps.css'; + +/** + * Displays per-tool nozzle temperatures in a grid (Creator 5 series). + */ +export class ToolTempsComponent extends BaseComponent { + public readonly componentId = 'tool-temps'; + + public readonly templateHTML = ` +
+
+ Per-tool temperatures are not available for this printer. +
+
+
+ `; + + private gridEl: HTMLElement | null = null; + private unavailableEl: HTMLElement | null = null; + /** Number of tool cells currently rendered, to avoid rebuilding every poll. */ + private renderedCount = -1; + + protected async setupEventListeners(): Promise { + this.gridEl = this.findElement('[data-role="grid"]'); + this.unavailableEl = this.findElement('[data-role="unavailable"]'); + } + + public update(data: ComponentUpdateData): void { + try { + const printerStatus = data.pollingData?.printerStatus as PrinterStatus | null | undefined; + const isConnected = data.pollingData?.isConnected ?? false; + const toolTemps = printerStatus?.toolTemps ?? []; + + const available = isConnected && toolTemps.length > 0; + this.setAvailability(available); + + if (available) { + this.renderTools(toolTemps); + } + + this.updateState(data); + } catch (error) { + console.error(`Error updating ${this.componentId}:`, error); + } + } + + private setAvailability(available: boolean): void { + if (this.unavailableEl) { + this.unavailableEl.style.display = available ? 'none' : 'flex'; + } + if (this.gridEl) { + this.gridEl.style.display = available ? 'grid' : 'none'; + } + } + + /** + * Render (or update) one cell per tool. Rebuilds the cell DOM only when the + * tool count changes; otherwise updates text/state in place. + */ + private renderTools(toolTemps: TemperatureData[]): void { + if (!this.gridEl) return; + + if (this.renderedCount !== toolTemps.length) { + this.gridEl.innerHTML = toolTemps + .map( + (_, i) => ` +
+
T${i}
+
+ -- + / + -- + °C +
+
` + ) + .join(''); + this.renderedCount = toolTemps.length; + } + + toolTemps.forEach((tool, i) => { + const cell = this.gridEl?.querySelector(`.tool-temp-cell[data-tool="${i}"]`); + if (!cell) return; + const current = cell.querySelector('[data-role="current"]'); + const target = cell.querySelector('[data-role="target"]'); + if (current) current.textContent = `${Math.round(tool.current)}`; + if (target) target.textContent = `${Math.round(tool.target)}`; + cell.classList.toggle('is-heating', tool.isHeating); + cell.classList.toggle('is-active', tool.target > 0); + }); + } +} diff --git a/src/shared/component-definitions.ts b/src/shared/component-definitions.ts index b5268ab..7d2f6d0 100644 --- a/src/shared/component-definitions.ts +++ b/src/shared/component-definitions.ts @@ -155,4 +155,16 @@ export const COMPONENT_REGISTRY_DATA: ReadonlyArray = [ required: false, singleton: true, }, + + { + id: 'tool-temps', + name: 'Tool Temperatures', + icon: 'thermometer', + defaultSize: { w: 4, h: 2 }, + minSize: { w: 2, h: 2 }, + category: 'main', + description: 'Per-tool nozzle temperatures (Creator 5 series)', + required: false, + singleton: true, + }, ]; diff --git a/src/shared/types/polling.ts b/src/shared/types/polling.ts index 55f3e37..5a59ded 100644 --- a/src/shared/types/polling.ts +++ b/src/shared/types/polling.ts @@ -146,6 +146,12 @@ export interface CumulativeStats { export interface PrinterStatus { state: PrinterState; temperatures: PrinterTemperatures; + /** + * Per-tool nozzle temperatures for multi-tool printers (e.g. Creator 5 series, + * one entry per nozzle). Undefined/empty on single-nozzle printers, which use + * {@link PrinterTemperatures.extruder} instead. + */ + toolTemps?: TemperatureData[]; fans: FanStatus; filtration: FiltrationStatus; settings: PrinterSettings; From 12c639d2be8d56dcfedc6b0b35790f1ac3996c77 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:58:33 -0400 Subject: [PATCH 09/93] docs(changelog): add 1.0.5-alpha.1 notes (Creator 5 support) Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8179790..69b690a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.5-alpha.1] - 2026-06-24 + +First alpha of the 1.0.5 cycle, adding initial Creator 5 / Creator 5 Pro support. + +### Creator 5 / Creator 5 Pro +- New `Creator5Backend` routes the Creator 5 and Creator 5 Pro to a dedicated backend that reuses the AD5X 4-slot material station and dual HTTP + TCP transport, with the Creator 5's per-tool nozzle temperatures, built-in camera, and native print-start material matching +- New **Tool Temperatures** grid component shows all four nozzle temperatures; add it from the component picker +- Creator 5 Pro capability gating: filtration / aux fan and the real door sensor are enabled for the Pro; the plain Creator 5 correctly hides the (sensorless) door status +- Built on `@ghosttypes/ff-api` 1.3.4, which adds Creator 5 detail parsing, per-tool temps, and the native `/printGcode` start-job command + ## [1.0.4] - 2026-05-31 The 1.0.4 stable release consolidates the 1.0.4-alpha cycle: a major new Calibration Assistant, a complete camera-streaming rework on go2rtc, a full security hardening pass, and a modern testing and tooling foundation. From 3dce956ee912614901c2afa2803914f177969e66 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Wed, 24 Jun 2026 20:23:46 -0400 Subject: [PATCH 10/93] feat(creator5): HTTP-only connection, updated material station The Creator 5 / 5 Pro are HTTP-only (no legacy TCP on 8899), which is what was breaking the old TCP-first connect. This wires them up properly and cleans up the material handling around them. - Detect C5/5 Pro by USB product ID, use the FiveMClient in httpOnly mode (ff-api ^1.3.6) - Route temperature control over HTTP when there's no TCP client - Add C5-specific filament palette (24 colors, 21 materials) - Renamed ifs-station to material-station Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 6 +- package.json | 2 +- pnpm-lock.yaml | 10 +- src/main/ipc/handlers/control-handlers.ts | 64 +++-- src/main/ipc/handlers/dialog-handlers.ts | 2 +- src/main/ipc/handlers/material-handlers.ts | 21 +- src/main/managers/ConnectionFlowManager.ts | 9 +- src/main/printer-backends/AD5XBackend.ts | 8 +- src/main/printer-backends/Creator5Backend.ts | 47 +++- src/main/printer-backends/DualAPIBackend.ts | 60 ++++- .../ConnectionEstablishmentService.ts | 103 +++++--- .../services/MainProcessPollingCoordinator.ts | 1 + src/main/services/PrinterDataTransformer.ts | 3 + .../ConnectionEstablishmentService.test.ts | 2 +- src/main/utils/PrinterUtils.ts | 21 ++ src/main/windows/WindowFactory.ts | 3 +- src/main/windows/WindowManager.ts | 1 - .../factories/ComponentDialogWindowFactory.ts | 2 + .../windows/factories/DialogWindowFactory.ts | 4 - src/main/windows/shared/WindowTypes.ts | 6 +- src/renderer/src/renderer/gridController.ts | 6 +- .../component-dialog-preload.ts | 1 - .../ui/component-dialog/component-dialog.ts | 6 +- .../src/ui/components/ifs-station/index.ts | 11 - src/renderer/src/ui/components/index.ts | 4 +- .../ui/components/material-station/index.ts | 17 ++ .../material-station.css} | 186 +++++++-------- .../material-station.ts} | 220 +++++++++--------- .../types.ts | 20 +- .../src/ui/components/spoolman/spoolman.css | 2 +- .../ui/components/tool-temps/tool-temps.css | 2 +- .../ui/components/tool-temps/tool-temps.ts | 2 +- .../__tests__/defaults.migration.test.ts | 59 +++++ src/renderer/src/ui/gridstack/defaults.ts | 28 ++- ...ingle-color-confirmation-dialog-preload.ts | 2 +- ...ngle-color-confirmation-dialog-renderer.ts | 8 +- src/shared/__tests__/ifs-palette.test.ts | 136 ----------- src/shared/__tests__/palette.test.ts | 190 +++++++++++++++ src/shared/ad5x-palette.ts | 41 ++++ src/shared/component-definitions.ts | 6 +- src/shared/creator5-palette.ts | 53 +++++ .../{ifs-palette.ts => palette-core.ts} | 128 +++++----- src/shared/palette.ts | 35 +++ src/shared/types/polling.ts | 8 + .../types/printer-backend/printer-features.ts | 8 + 45 files changed, 1026 insertions(+), 528 deletions(-) delete mode 100644 src/renderer/src/ui/components/ifs-station/index.ts create mode 100644 src/renderer/src/ui/components/material-station/index.ts rename src/renderer/src/ui/components/{ifs-station/ifs-station.css => material-station/material-station.css} (81%) rename src/renderer/src/ui/components/{ifs-station/ifs-station.ts => material-station/material-station.ts} (72%) rename src/renderer/src/ui/components/{ifs-station => material-station}/types.ts (57%) create mode 100644 src/renderer/src/ui/gridstack/__tests__/defaults.migration.test.ts delete mode 100644 src/shared/__tests__/ifs-palette.test.ts create mode 100644 src/shared/__tests__/palette.test.ts create mode 100644 src/shared/ad5x-palette.ts create mode 100644 src/shared/creator5-palette.ts rename src/shared/{ifs-palette.ts => palette-core.ts} (52%) create mode 100644 src/shared/palette.ts diff --git a/CLAUDE.md b/CLAUDE.md index e32fdbc..e7f0716 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # FlashForgeUI-Electron Development Guide -**Last Updated:** 2026-03-06 17:54 ET (America/New_York) +**Last Updated:** 2026-05-31 13:40 ET (America/New_York) This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. @@ -104,6 +104,10 @@ For detailed architectural information, see the comprehensive reference document 13. **Desktop E2E boundaries**: use `tests/e2e/electron/desktop-smoke.spec.ts` for live `%APPDATA%` smoke coverage and `tests/e2e/electron/desktop-emulator.spec.ts` for isolated emulator-backed lifecycle coverage. On Windows, prefer the dedicated `package.json` scripts over ad hoc Playwright grep invocations. +14. **Release builds are unsigned (no code-signing cert)**: there is no Windows (or macOS) code-signing certificate, so every release artifact - both CI and local `pnpm build:win` - is `NotSigned`. The `signtool.exe` lines in the local build log run but produce no valid Authenticode signature. This is expected, not a regression; Windows users get the normal SmartScreen "unknown publisher" prompt. Don't chase a "missing signature" as a bug. + +15. **Release channel is derived from the `package.json` version**: `electron-builder-config.cjs` parses the prerelease suffix - a `-alpha.N` version yields channel `alpha`/`alpha.yml` (prerelease), a bare `X.Y.Z` yields channel `latest`/`latest.yml` (stable). Bumping the version is all that's needed to flip the channel; don't hardcode it. The release workflow (`.github/workflows/release.yml`, `workflow_dispatch`) reads notes from the matching `## [] - ` CHANGELOG section, and `softprops/action-gh-release` keyed on the tag will publish an existing **draft** of that tag *keeping the draft's body* (it does not overwrite with the templated notes) - so don't pre-create a draft if you want the workflow's templated notes. + --- ## Key File Locations diff --git a/package.json b/package.json index c24540a..621dea9 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ } }, "dependencies": { - "@ghosttypes/ff-api": "^1.3.4", + "@ghosttypes/ff-api": "^1.3.6", "@parallel-7/slicer-meta": "1.3.0", "electron-log": "^5.4.3", "electron-updater": "^6.8.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 62eef89..eb74944 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,8 +30,8 @@ importers: .: dependencies: '@ghosttypes/ff-api': - specifier: ^1.3.4 - version: 1.3.4 + specifier: ^1.3.6 + version: 1.3.6 '@parallel-7/slicer-meta': specifier: 1.3.0 version: 1.3.0 @@ -1242,8 +1242,8 @@ packages: cpu: [x64] os: [win32] - '@ghosttypes/ff-api@1.3.4': - resolution: {integrity: sha512-ABBs/Jme//Kyrvpz7puvFCBuvjfIOFONoYcWyFolX94zF8uh5lKOWqdu6QkHmyV+YJmSfKbcR78rCf+rzrFskg==, tarball: https://npm.pkg.github.com/download/@ghosttypes/ff-api/1.3.4/7d83ca1de9d752cd9dad611d23746e8282e8d9e0} + '@ghosttypes/ff-api@1.3.6': + resolution: {integrity: sha512-kKfNR65hPQiROY16dX1By4dtgqZZDScLs9ZJcknylhxftk9rPt3x9ujmq44ltirGagDyajqv7qeJiDiODm0Teg==, tarball: https://npm.pkg.github.com/download/@ghosttypes/ff-api/1.3.6/65c937f41c67d6f2c413756e4b2fc82f8242f7a5} '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -5301,7 +5301,7 @@ snapshots: '@esbuild/win32-x64@0.27.3': optional: true - '@ghosttypes/ff-api@1.3.4': + '@ghosttypes/ff-api@1.3.6': dependencies: axios: 1.16.1 form-data: 4.0.6 diff --git a/src/main/ipc/handlers/control-handlers.ts b/src/main/ipc/handlers/control-handlers.ts index 774b98c..cc3b81a 100644 --- a/src/main/ipc/handlers/control-handlers.ts +++ b/src/main/ipc/handlers/control-handlers.ts @@ -40,6 +40,16 @@ function getLegacyClient(backend: BasePrinterBackend): FlashForgeClient | null { return null; } +/** + * Helper to get the HTTP (FiveMClient) client from a backend, if the primary + * client is a FiveMClient. Used to route control over HTTP for HTTP-only printers + * (Creator 5 / 5 Pro) that have no legacy TCP client. + */ +function getFiveMClient(backend: BasePrinterBackend): FiveMClient | null { + const client = backend.getPrimaryClient(); + return client instanceof FiveMClient ? client : null; +} + /** * Register all printer control related IPC handlers */ @@ -63,12 +73,19 @@ export function registerControlHandlers(backendManager: PrinterBackendManager): return { success: false, error: 'Backend not available' }; } + // Dual-API printers use the TCP G-code client; HTTP-only printers + // (Creator 5 / 5 Pro) route through the FiveMClient (temperatureCtl_cmd). const legacyClient = getLegacyClient(backend); - if (!legacyClient) { - return { success: false, error: 'Temperature control not available' }; + let result: boolean; + if (legacyClient) { + result = await legacyClient.setBedTemp(temperature); + } else { + const fiveMClient = getFiveMClient(backend); + if (!fiveMClient) { + return { success: false, error: 'Temperature control not available' }; + } + result = await fiveMClient.tempControl.setBedTemp(temperature); } - - const result = await legacyClient.setBedTemp(temperature); console.log(`Set bed temperature to ${temperature}°C`, result); return { success: result, data: result }; } catch (error) { @@ -96,11 +113,16 @@ export function registerControlHandlers(backendManager: PrinterBackendManager): } const legacyClient = getLegacyClient(backend); - if (!legacyClient) { - return { success: false, error: 'Temperature control not available' }; + let result: boolean; + if (legacyClient) { + result = await legacyClient.setExtruderTemp(temperature); + } else { + const fiveMClient = getFiveMClient(backend); + if (!fiveMClient) { + return { success: false, error: 'Temperature control not available' }; + } + result = await fiveMClient.tempControl.setExtruderTemp(temperature); } - - const result = await legacyClient.setExtruderTemp(temperature); console.log(`Set extruder temperature to ${temperature}°C`, result); return { success: result, data: result }; } catch (error) { @@ -128,11 +150,16 @@ export function registerControlHandlers(backendManager: PrinterBackendManager): } const legacyClient = getLegacyClient(backend); - if (!legacyClient) { - return { success: false, error: 'Temperature control not available' }; + let result: boolean; + if (legacyClient) { + result = await legacyClient.cancelBedTemp(); + } else { + const fiveMClient = getFiveMClient(backend); + if (!fiveMClient) { + return { success: false, error: 'Temperature control not available' }; + } + result = await fiveMClient.tempControl.cancelBedTemp(); } - - const result = await legacyClient.cancelBedTemp(); console.log('Turned off bed temperature', result); return { success: result, data: result }; } catch (error) { @@ -160,11 +187,16 @@ export function registerControlHandlers(backendManager: PrinterBackendManager): } const legacyClient = getLegacyClient(backend); - if (!legacyClient) { - return { success: false, error: 'Temperature control not available' }; + let result: boolean; + if (legacyClient) { + result = await legacyClient.cancelExtruderTemp(); + } else { + const fiveMClient = getFiveMClient(backend); + if (!fiveMClient) { + return { success: false, error: 'Temperature control not available' }; + } + result = await fiveMClient.tempControl.cancelExtruderTemp(); } - - const result = await legacyClient.cancelExtruderTemp(); console.log('Turned off extruder temperature', result); return { success: result, data: result }; } catch (error) { diff --git a/src/main/ipc/handlers/dialog-handlers.ts b/src/main/ipc/handlers/dialog-handlers.ts index 0d102f5..8be0e74 100644 --- a/src/main/ipc/handlers/dialog-handlers.ts +++ b/src/main/ipc/handlers/dialog-handlers.ts @@ -8,7 +8,7 @@ * - Input dialog (generic user input prompts) * - Job management dialogs (uploader, picker) * - Send commands dialog (G-code/command execution) - * - Material dialogs (IFS, material info, matching, single-color confirmation) + * - Material dialogs (material info, matching, single-color confirmation) * - Generic window controls (minimize/close for sub-windows) * * Key exports: diff --git a/src/main/ipc/handlers/material-handlers.ts b/src/main/ipc/handlers/material-handlers.ts index c54c14b..5b3e269 100644 --- a/src/main/ipc/handlers/material-handlers.ts +++ b/src/main/ipc/handlers/material-handlers.ts @@ -9,16 +9,19 @@ * Key exports: * - registerMaterialHandlers(): Registers material station IPC handlers * + * Applies to printers with a material station (AD5X and the Creator 5 / 5 Pro); + * the fixed palette is selected per-printer via `@shared/palette`. + * * IPC Channels: * - `material:configure-slot` - Snap a Spoolman spool's material/color onto the - * AD5X fixed palette and apply it to a slot via the printer's `msConfig_cmd`. + * printer's fixed palette and apply it to a slot via the printer's `msConfig_cmd`. * - `material:set-slot` - Apply an explicit material + color (already chosen from * the fixed palette by the renderer) to a slot. Spoolman-independent. * * @module ipc/handlers/material-handlers */ -import { nearestColor, nearestMaterial } from '@shared/ifs-palette.js'; +import { getPaletteForModel } from '@shared/palette.js'; import { ipcMain } from 'electron'; import { getConfigManager } from '../../managers/ConfigManager.js'; import type { PrinterBackendManager } from '../../managers/PrinterBackendManager.js'; @@ -58,12 +61,12 @@ interface ConfigureSlotResult { /** * Request payload for `material:set-slot` — an explicit, Spoolman-independent * slot write. The renderer has already chosen `materialName`/`colorHex` from the - * fixed AD5X palette via the manual slot editor. + * printer's fixed palette via the manual slot editor. */ interface SetSlotRequest { /** Target slot number (1-4). */ slot: number; - /** Material name to write (one of the recognized AD5X materials). */ + /** Material name to write (one of the printer's recognized materials). */ materialName: string; /** Color hex to write (with or without leading "#"). */ colorHex: string; @@ -117,13 +120,19 @@ export function registerMaterialHandlers(backendManager: PrinterBackendManager): return { success: false, error: 'Spool has no color in Spoolman', spoolName }; } - const snappedColor = nearestColor(rawColor); + // Snap onto the printer's own fixed palette (the Creator 5 series uses a + // different palette than the AD5X). Fall back to the AD5X palette if the + // model can't be resolved. + const modelType = backendManager.getBackendForContext(contextId)?.getCapabilities().modelType; + const palette = getPaletteForModel(modelType); + + const snappedColor = palette.nearestColor(rawColor); if (!snappedColor) { return { success: false, error: `Could not interpret spool color "${rawColor}"`, spoolName }; } // Resolve material: keep the slot's current material when unrecognized. - const snappedMaterial = filament.material ? nearestMaterial(filament.material) : null; + const snappedMaterial = filament.material ? palette.nearestMaterial(filament.material) : null; let materialToApply = snappedMaterial; if (!materialToApply) { diff --git a/src/main/managers/ConnectionFlowManager.ts b/src/main/managers/ConnectionFlowManager.ts index 1f4be17..1f33127 100644 --- a/src/main/managers/ConnectionFlowManager.ts +++ b/src/main/managers/ConnectionFlowManager.ts @@ -639,7 +639,8 @@ export class ConnectionFlowManager extends EventEmitter { tempResult.typeName, familyInfo.is5MFamily, checkCode, - forceLegacyMode + forceLegacyMode, + modelType ); if (!connectionResult) { @@ -906,13 +907,15 @@ export class ConnectionFlowManager extends EventEmitter { eventPort: detailsWithDefaults.httpPort, }; - // Establish connection + // Establish connection. Prefer the saved (immutable) modelType so HTTP-only + // models reconnect over HTTP without attempting the dead legacy TCP channel. const connectionResult = await this.connectionService.establishFinalConnection( discoveredPrinter, detailsWithDefaults.printerModel, familyInfo.is5MFamily, detailsWithDefaults.CheckCode, - forceLegacyMode + forceLegacyMode, + detailsWithDefaults.modelType ); if (!connectionResult) { diff --git a/src/main/printer-backends/AD5XBackend.ts b/src/main/printer-backends/AD5XBackend.ts index c445aaf..9eb5f09 100644 --- a/src/main/printer-backends/AD5XBackend.ts +++ b/src/main/printer-backends/AD5XBackend.ts @@ -334,10 +334,14 @@ export class AD5XBackend extends DualAPIBackend { } /** - * Get material station status (supported on AD5X) + * Get material station status (supported on AD5X and the Creator 5 series, + * which inherits this backend). Stamps the printer model so the polling layer + * and renderer can select the correct fixed filament palette (Creator 5 uses a + * different palette than the AD5X — see `@shared/palette`). */ public getMaterialStationStatus(): MaterialStationStatus | null { - return extractMaterialStationStatus(this.lastMachineInfo); + const status = extractMaterialStationStatus(this.lastMachineInfo); + return status ? { ...status, printerModelType: this.modelType } : null; } /** diff --git a/src/main/printer-backends/Creator5Backend.ts b/src/main/printer-backends/Creator5Backend.ts index 1680130..3b16b25 100644 --- a/src/main/printer-backends/Creator5Backend.ts +++ b/src/main/printer-backends/Creator5Backend.ts @@ -22,6 +22,7 @@ import { type Creator5MaterialMapping, + FiveMClient, type FFMachineInfo, } from '@ghosttypes/ff-api'; import { @@ -35,8 +36,28 @@ import { AD5XBackend } from './AD5XBackend.js'; * Backend implementation for the Creator 5 / Creator 5 Pro. * Extends the AD5X backend (shared material station + dual API) and adds the * Creator 5's per-tool temperatures and Pro-only hardware capabilities. + * + * Unlike the other dual-API backends, the Creator 5 series is **HTTP-only**: the + * printer runs no legacy TCP server (no port 8899), so there is no secondary + * FlashForgeClient. The FiveMClient is created in `httpOnly` mode and is the entire + * connection. TCP-only operations inherited from DualAPIBackend (raw G-code, + * homing, legacy status fallback) are unavailable; see the overrides below. */ export class Creator5Backend extends AD5XBackend { + /** + * HTTP-only client initialization. The base {@link DualAPIBackend.initializeClients} + * requires a secondary FlashForgeClient and throws without one; the Creator 5 has + * no TCP channel, so we validate only the primary FiveMClient here and leave the + * legacy client unset. + */ + protected initializeClients(): void { + if (!(this.primaryClient instanceof FiveMClient)) { + throw new Error('Creator5Backend requires FiveMClient as primary client'); + } + this.fiveMClient = this.primaryClient; + // No secondaryClient / legacyClient: the Creator 5 series is HTTP-only. + } + /** * Whether this specific printer is a Creator 5 Pro (vs a plain Creator 5). * Drives the Pro-only capabilities: real door sensor and filtration/aux fan. @@ -58,11 +79,27 @@ export class Creator5Backend extends AD5XBackend { return { ...features, - // Both Creator 5 and Creator 5 Pro have a built-in camera; the OEM stream - // URL is populated at runtime from the printer's reported cameraStreamUrl. - camera: { - ...features.camera, - builtin: true, + // Both Creator 5 and Creator 5 Pro have a built-in camera; it is enabled at + // runtime from the printer's reported `cameraStreamUrl` (same path as the 5M + // Pro), so no static feature flag is needed here. + // The Creator 5 series is HTTP-only and exposes NO raw G-code / M-code + // passthrough: the firmware's only command surface is the HTTP /control + // command set, and there is no legacy TCP channel and no gcode_cmd/rawCmd + // route (Ghidra RE of firmwareExe 1.9.2 — creator5-analysis §5). Override + // the AD5X default (which advertises legacy-API G-code) so the UI does not + // surface a manual-command / G-code console affordance the printer can't + // honor. (sendGCode already guards the absent legacy client at runtime.) + gcodeCommands: { + available: false, + usesLegacyAPI: false, + supportedCommands: [], + }, + // Status comes solely from the HTTP /detail endpoint — there is no legacy + // TCP status path on these printers. + statusMonitoring: { + ...features.statusMonitoring, + usesNewAPI: true, + usesLegacyAPI: false, }, }; } diff --git a/src/main/printer-backends/DualAPIBackend.ts b/src/main/printer-backends/DualAPIBackend.ts index 42b8d0d..7b6de7f 100644 --- a/src/main/printer-backends/DualAPIBackend.ts +++ b/src/main/printer-backends/DualAPIBackend.ts @@ -215,6 +215,17 @@ export abstract class DualAPIBackend extends BasePrinterBackend { public async executeGCodeCommand(command: string): Promise { const startTime = Date.now(); + // HTTP-only backends (Creator 5 / 5 Pro) have no TCP channel for raw G-code. + if (!this.legacyClient) { + return { + success: false, + command, + error: 'Raw G-code is unavailable on this printer (HTTP-only, no TCP channel)', + executionTime: 0, + timestamp: new Date(), + }; + } + try { // G-code commands always use legacy API const response = await this.legacyClient.sendRawCmd(command); @@ -354,6 +365,22 @@ export abstract class DualAPIBackend extends BasePrinterBackend { */ protected async getPrinterStatusLegacy(originalError: unknown): Promise { void originalError; + // HTTP-only backends have no legacy client to fall back to. + if (!this.legacyClient) { + return { + success: false, + error: originalError instanceof Error ? originalError.message : String(originalError), + timestamp: new Date(), + status: { + printerState: 'error', + bedTemperature: 0, + nozzleTemperature: 0, + progress: 0, + currentLayer: undefined, + totalLayers: undefined, + }, + }; + } try { const printerInfo = await this.legacyClient.getPrinterInfo(); @@ -549,8 +576,15 @@ export abstract class DualAPIBackend extends BasePrinterBackend { data: 'Job paused', timestamp: new Date(), }; - } catch (_error) { - // Fallback to legacy API + } catch (error) { + // Fallback to legacy API (unavailable on HTTP-only backends) + if (!this.legacyClient) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + timestamp: new Date(), + }; + } try { await this.legacyClient.sendRawCmd('M25'); return { @@ -584,8 +618,15 @@ export abstract class DualAPIBackend extends BasePrinterBackend { data: 'Job resumed', timestamp: new Date(), }; - } catch (_error) { - // Fallback to legacy API + } catch (error) { + // Fallback to legacy API (unavailable on HTTP-only backends) + if (!this.legacyClient) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + timestamp: new Date(), + }; + } try { await this.legacyClient.sendRawCmd('M24'); return { @@ -619,8 +660,15 @@ export abstract class DualAPIBackend extends BasePrinterBackend { data: 'Job cancelled', timestamp: new Date(), }; - } catch (_error) { - // Fallback to legacy API + } catch (error) { + // Fallback to legacy API (unavailable on HTTP-only backends) + if (!this.legacyClient) { + return { + success: false, + error: error instanceof Error ? error.message : String(error), + timestamp: new Date(), + }; + } try { await this.legacyClient.sendRawCmd('M26'); return { diff --git a/src/main/services/ConnectionEstablishmentService.ts b/src/main/services/ConnectionEstablishmentService.ts index e9a0b4e..5cb0d5c 100644 --- a/src/main/services/ConnectionEstablishmentService.ts +++ b/src/main/services/ConnectionEstablishmentService.ts @@ -18,25 +18,18 @@ * conjunction with ConnectionFlowManager for complete connection workflows. */ -import { FiveMClient, FlashForgeClient } from '@ghosttypes/ff-api'; +import { FiveMClient, type FiveMClientConnectionOptions, FlashForgeClient } from '@ghosttypes/ff-api'; import { DiscoveredPrinter, ExtendedPrinterInfo, TemporaryConnectionResult } from '@shared/types/printer.js'; +import type { PrinterModelType } from '@shared/types/printer-backend/index.js'; import { EventEmitter } from 'events'; -import { detectPrinterFamily, getConnectionErrorMessage } from '../utils/PrinterUtils.js'; - -type PortAwareFlashForgeClientConstructor = new ( - hostname: string, - options?: { port?: number } -) => FlashForgeClient; - -type PortAwareFiveMClientConstructor = new ( - ipAddress: string, - serialNumber: string, - checkCode: string, - options?: { - httpPort?: number; - tcpPort?: number; - } -) => FiveMClient; +import { + detectPrinterFamily, + detectPrinterModelType, + detectPrinterModelTypeFromId, + getConnectionErrorMessage, + getModelDisplayName, + isHttpOnlyModel, +} from '../utils/PrinterUtils.js'; // Connection clients interface for dual API support interface ConnectionClients { @@ -56,26 +49,29 @@ export class ConnectionEstablishmentService extends EventEmitter { } private createLegacyClient(printer: Pick): FlashForgeClient { - const legacyCtor = FlashForgeClient as unknown as PortAwareFlashForgeClientConstructor; if (printer.commandPort !== undefined) { - return new legacyCtor(printer.ipAddress, { port: printer.commandPort }); + return new FlashForgeClient(printer.ipAddress, { port: printer.commandPort }); } - return new legacyCtor(printer.ipAddress); + return new FlashForgeClient(printer.ipAddress); } - private createFiveMClient(printer: DiscoveredPrinter, checkCode: string): FiveMClient { - const modernCtor = FiveMClient as unknown as PortAwareFiveMClientConstructor; - const options = - printer.commandPort !== undefined || printer.eventPort !== undefined + private createFiveMClient( + printer: DiscoveredPrinter, + checkCode: string, + httpOnly = false + ): FiveMClient { + const hasPortOverride = printer.commandPort !== undefined || printer.eventPort !== undefined; + // Only build an options object when something needs to be passed. HTTP-only + // mode (Creator 5 / 5 Pro) is set so the client never opens the TCP channel. + const options: FiveMClientConnectionOptions | undefined = + hasPortOverride || httpOnly ? { httpPort: printer.eventPort, tcpPort: printer.commandPort, + httpOnly, } : undefined; - if (options) { - return new modernCtor(printer.ipAddress, printer.serialNumber, checkCode, options); - } - return new modernCtor(printer.ipAddress, printer.serialNumber, checkCode); + return new FiveMClient(printer.ipAddress, printer.serialNumber, checkCode, options); } /** @@ -95,6 +91,26 @@ export class ConnectionEstablishmentService extends EventEmitter { public async createTemporaryConnection(printer: DiscoveredPrinter): Promise { this.emit('temporary-connection-started', printer); + // HTTP-only models (Creator 5 / 5 Pro) run no legacy TCP server, so the usual + // ~M601/~M115 probe can't work. When discovery's USB product ID identifies such + // a model, synthesize the type info (model name + the serial/name from the + // discovery packet) and skip the TCP probe entirely. + const idModelType = detectPrinterModelTypeFromId(printer.productId, ''); + if (isHttpOnlyModel(idModelType)) { + const typeName = getModelDisplayName(idModelType); + console.log(`Temporary connection - HTTP-only model detected via product ID: ${typeName}`); + this.emit('printer-type-detected', { typeName, familyInfo: detectPrinterFamily(typeName) }); + return { + success: true, + typeName, + printerInfo: { + Name: printer.name, + SerialNumber: printer.serialNumber, + TypeName: typeName, + } as unknown as ExtendedPrinterInfo, + }; + } + try { // Always use legacy API for type detection const tempClient = this.createLegacyClient(printer); @@ -179,13 +195,18 @@ export class ConnectionEstablishmentService extends EventEmitter { typeName: string, is5MFamily: boolean, checkCode: string, - forceLegacyMode: boolean + forceLegacyMode: boolean, + modelType?: PrinterModelType ): Promise { this.emit('final-connection-started', { printer, typeName }); try { if (is5MFamily && !forceLegacyMode) { - return await this.establishDualAPIConnection(printer, checkCode); + // HTTP-only models (Creator 5 / 5 Pro) get a single HTTP client and no + // secondary TCP client. Fall back to the type name when no model type was + // passed (manual IP connections that never resolved a product ID). + const resolvedModelType = modelType ?? detectPrinterModelType(typeName); + return await this.establishDualAPIConnection(printer, checkCode, isHttpOnlyModel(resolvedModelType)); } else { return await this.establishLegacyConnection(printer); } @@ -199,13 +220,18 @@ export class ConnectionEstablishmentService extends EventEmitter { /** * Establish dual API connection for 5M family printers */ - private async establishDualAPIConnection(printer: DiscoveredPrinter, checkCode: string): Promise { - console.log('Creating dual API connection for 5M family printer'); + private async establishDualAPIConnection( + printer: DiscoveredPrinter, + checkCode: string, + httpOnly = false + ): Promise { + console.log(`Creating ${httpOnly ? 'HTTP-only' : 'dual'} API connection for 5M family printer`); console.log('Connection details:', { ipAddress: printer.ipAddress, serialNumber: printer.serialNumber, name: printer.name, hasValidSerial: !!(printer.serialNumber && printer.serialNumber.trim() !== ''), + httpOnly, }); // Validate that we have a valid serial number for FiveMClient @@ -215,7 +241,7 @@ export class ConnectionEstablishmentService extends EventEmitter { } // Primary client: FiveMClient for new API operations - const primaryClient = this.createFiveMClient(printer, checkCode); + const primaryClient = this.createFiveMClient(printer, checkCode, httpOnly); try { console.log('Initializing FiveMClient...'); @@ -234,6 +260,17 @@ export class ConnectionEstablishmentService extends EventEmitter { } console.log('FiveMClient control initialized successfully'); + // HTTP-only models (Creator 5 / 5 Pro) have no legacy TCP server — there is + // no secondary client to create. The HTTP client is the whole connection. + if (httpOnly) { + console.log('HTTP-only connection established (no secondary TCP client)'); + this.emit('dual-api-connection-established', { + ipAddress: printer.ipAddress, + serialNumber: printer.serialNumber, + }); + return { primaryClient }; + } + // Add a small delay to ensure primary client is fully ready await new Promise((resolve) => setTimeout(resolve, 500)); diff --git a/src/main/services/MainProcessPollingCoordinator.ts b/src/main/services/MainProcessPollingCoordinator.ts index e756f31..f7b8561 100644 --- a/src/main/services/MainProcessPollingCoordinator.ts +++ b/src/main/services/MainProcessPollingCoordinator.ts @@ -204,6 +204,7 @@ export class MainProcessPollingCoordinator extends EventEmitter { activeSlot: materialStationRaw.activeSlot, errorMessage: materialStationRaw.errorMessage, lastUpdate: new Date(), + printerModelType: materialStationRaw.printerModelType, }; } diff --git a/src/main/services/PrinterDataTransformer.ts b/src/main/services/PrinterDataTransformer.ts index 4518fba..e61d77f 100644 --- a/src/main/services/PrinterDataTransformer.ts +++ b/src/main/services/PrinterDataTransformer.ts @@ -165,6 +165,8 @@ export class PrinterDataTransformer { const activeSlot = safeExtractNumber(backendData, 'activeSlot', -1); const errorMessage = safeExtractString(backendData, 'errorMessage', ''); const slots = safeExtractArray(backendData, 'slots', []); + // Propagate the owning model so the renderer can pick the right palette. + const printerModelType = safeExtractString(backendData, 'printerModelType', '') || undefined; const transformedSlots: MaterialSlot[] = slots .filter(isValidObject) @@ -176,6 +178,7 @@ export class PrinterDataTransformer { activeSlot: activeSlot >= 0 ? activeSlot : null, errorMessage: errorMessage || null, lastUpdate: new Date(), + printerModelType: printerModelType as MaterialStationStatus['printerModelType'], }; } diff --git a/src/main/services/__tests__/ConnectionEstablishmentService.test.ts b/src/main/services/__tests__/ConnectionEstablishmentService.test.ts index d67d726..02f4365 100644 --- a/src/main/services/__tests__/ConnectionEstablishmentService.test.ts +++ b/src/main/services/__tests__/ConnectionEstablishmentService.test.ts @@ -257,7 +257,7 @@ describe('ConnectionEstablishmentService', () => { '192.168.1.130', 'SN-PORTS', '7777', - { httpPort: 19098, tcpPort: 19099 }, + { httpPort: 19098, tcpPort: 19099, httpOnly: false }, ]); expect(flashForgeClientInstances[0].args).toEqual(['192.168.1.130', { port: 19099 }]); }); diff --git a/src/main/utils/PrinterUtils.ts b/src/main/utils/PrinterUtils.ts index f75475e..ebf4c0d 100644 --- a/src/main/utils/PrinterUtils.ts +++ b/src/main/utils/PrinterUtils.ts @@ -66,6 +66,27 @@ export const NEW_API_PRODUCT_IDS: Readonly> = { 0x0029: 'creator-5-pro', }; +/** + * Model types that speak ONLY the HTTP API (no legacy TCP server on port 8899). + * + * The Creator 5 / 5 Pro are Klipper-based and run only the HTTP `OrcaServer` + * (port 8898) — they have no `~M601`/`~M115` TCP control channel. Connections to + * these models must skip the legacy TCP temporary connection and the secondary + * FlashForgeClient, and the FiveMClient must be created in `httpOnly` mode. + */ +const HTTP_ONLY_MODEL_TYPES: ReadonlySet = new Set([ + 'creator-5', + 'creator-5-pro', +]); + +/** + * Whether the given model type is HTTP-only (no legacy TCP control channel). + * @param modelType The detected printer model type. + * @returns True for Creator 5 / 5 Pro; false for all dual-API and legacy models. + */ +export const isHttpOnlyModel = (modelType: PrinterModelType): boolean => + HTTP_ONLY_MODEL_TYPES.has(modelType); + /** * Detect specific printer model type from typeName * Returns detailed model information for backend selection diff --git a/src/main/windows/WindowFactory.ts b/src/main/windows/WindowFactory.ts index 992aad5..2965f2a 100644 --- a/src/main/windows/WindowFactory.ts +++ b/src/main/windows/WindowFactory.ts @@ -40,7 +40,6 @@ * - createMaterialMatchingDialog: Material configuration with mapping result * - createSingleColorConfirmationDialog: Print validation with boolean result * - createMaterialInfoDialog: Material slot information display - * - createIFSDialog: Material station management display * - createConnectChoiceDialog: Connection method selection * - createPrinterConnectedWarningDialog: Connection conflict warning * @@ -65,7 +64,7 @@ * @exports InputDialogOptions - Type for input dialog configuration * @exports createSettingsWindow, createStatusWindow, createLogDialog - Core window functions * @exports createInputDialog, createMaterialMatchingDialog, createSingleColorConfirmationDialog, - * createMaterialInfoDialog, createIFSDialog, createConnectChoiceDialog, + * createMaterialInfoDialog, createConnectChoiceDialog, * createPrinterConnectedWarningDialog - Dialog window functions * @exports createJobUploaderWindow, createJobPickerWindow, createPrinterSelectionWindow, * createSendCommandsWindow - Utility window functions diff --git a/src/main/windows/WindowManager.ts b/src/main/windows/WindowManager.ts index 5905417..8817cf3 100644 --- a/src/main/windows/WindowManager.ts +++ b/src/main/windows/WindowManager.ts @@ -37,7 +37,6 @@ * - PRINTER_SELECTION: Printer management window * - JOB_PICKER: File selection from printer * - SEND_COMMANDS: Direct command interface - * - IFS_DIALOG: Material station display * - MATERIAL_INFO_DIALOG: Material slot information * - MATERIAL_MATCHING_DIALOG: Material configuration * - SINGLE_COLOR_CONFIRMATION_DIALOG: Print validation diff --git a/src/main/windows/factories/ComponentDialogWindowFactory.ts b/src/main/windows/factories/ComponentDialogWindowFactory.ts index 63146a7..285a6c1 100644 --- a/src/main/windows/factories/ComponentDialogWindowFactory.ts +++ b/src/main/windows/factories/ComponentDialogWindowFactory.ts @@ -54,6 +54,8 @@ const COMPONENT_DIALOG_SIZES: Record 'log-panel': { width: 850, height: 650 }, 'controls-grid': { width: 600, height: 500 }, 'filtration-controls': { width: 500, height: 400 }, + // Material station: roomy enough for the 4-slot grid + per-slot editor modal. + 'material-station': { width: 600, height: 700 }, // Default size for unknown components default: { width: 600, height: 500 }, }; diff --git a/src/main/windows/factories/DialogWindowFactory.ts b/src/main/windows/factories/DialogWindowFactory.ts index f0c6a45..7e2a74c 100644 --- a/src/main/windows/factories/DialogWindowFactory.ts +++ b/src/main/windows/factories/DialogWindowFactory.ts @@ -24,7 +24,6 @@ * - Create material matching dialogs for printer material configuration and return material mappings * - Create single color confirmation dialogs for print job validation and return boolean confirmation * - Create material info dialogs for displaying material station slot information (void return) - * - Create IFS dialogs for material station display and management (void return) * - Create auto-connect choice dialogs for saved printer selection and return user choice * - Create connect choice dialogs for connection method selection and return selected method * - Create printer connected warning dialogs when attempting to connect while already connected @@ -37,7 +36,6 @@ * - Material Matching Dialog: Promise - Returns material mappings or null if cancelled * - Single Color Confirmation: Promise - Returns true if confirmed, false if cancelled * - Material Info Dialog: void - Display-only, no return value - * - IFS Dialog: void - Display-only, no return value * - Auto-Connect Choice: Promise - Returns action choice or null if cancelled * - Connect Choice: Promise - Returns action choice or null if cancelled * - Printer Connected Warning: Promise - Returns true to continue, false to cancel @@ -56,7 +54,6 @@ * - Material Matching: 700x650 (min 600x550), non-resizable, frameless, transparent * - Single Color Confirmation: 450x500 (min 400x450), non-resizable, frameless, transparent * - Material Info: 600x500 (min 450x400), non-resizable, frameless, transparent - * - IFS Dialog: 600x700 (min 600x650), non-resizable, frameless, transparent * - Auto-Connect Choice: 500x480 (min 450x420), non-resizable, frameless, transparent * - Connect Choice: 480x450 (min 450x400), non-resizable, frameless, transparent * - Printer Connected Warning: 450x380 (min 400x350), non-resizable, frameless, transparent @@ -65,7 +62,6 @@ * @exports createMaterialMatchingDialog - Create material matching dialog for printer configuration * @exports createSingleColorConfirmationDialog - Create single color confirmation for print validation * @exports createMaterialInfoDialog - Create material info dialog for slot information - * @exports createIFSDialog - Create IFS dialog for material station management * @exports createAutoConnectChoiceDialog - Create auto-connect choice dialog for saved printers * @exports createConnectChoiceDialog - Create connect choice dialog for connection method * @exports createPrinterConnectedWarningDialog - Create warning dialog for existing connections diff --git a/src/main/windows/shared/WindowTypes.ts b/src/main/windows/shared/WindowTypes.ts index 3c663ab..0fa5ae8 100644 --- a/src/main/windows/shared/WindowTypes.ts +++ b/src/main/windows/shared/WindowTypes.ts @@ -172,7 +172,11 @@ export type WindowType = | { kind: 'PrinterSelection' } | { kind: 'JobPicker'; data: JobPickerInitData } | { kind: 'SendCommands' } - | { kind: 'IFSDialog' } + // Pop-out of the Material Station grid component (AD5X IFS + Creator 5 / 5 Pro). + // Unlike the bespoke Material* dialogs below, this is served by the generic + // component-dialog path: `component-dialog:open` IPC -> createComponentDialog( + // 'material-station'). Replaces the never-wired legacy 'IFSDialog' kind. + | { kind: 'MaterialStation' } | { kind: 'MaterialInfo'; data: unknown } | { kind: 'MaterialMatching'; data: MaterialMatchingDialogData } | { kind: 'SingleColorConfirmation'; data: SingleColorConfirmationDialogData } diff --git a/src/renderer/src/renderer/gridController.ts b/src/renderer/src/renderer/gridController.ts index d6546fb..0d329ad 100644 --- a/src/renderer/src/renderer/gridController.ts +++ b/src/renderer/src/renderer/gridController.ts @@ -16,9 +16,9 @@ import { ControlsGridComponent, componentManager, FiltrationControlsComponent, - IFSStationComponent, JobStatsComponent, LogPanelComponent, + MaterialStationComponent, ModelPreviewComponent, PrinterStatusComponent, SpoolmanComponent, @@ -432,8 +432,8 @@ export class RendererGridController { } case 'spoolman-tracker': return new SpoolmanComponent(container); - case 'ifs-station': - return new IFSStationComponent(container); + case 'material-station': + return new MaterialStationComponent(container); case 'tool-temps': return new ToolTempsComponent(container); default: diff --git a/src/renderer/src/ui/component-dialog/component-dialog-preload.ts b/src/renderer/src/ui/component-dialog/component-dialog-preload.ts index 19b5e1e..f21250e 100644 --- a/src/renderer/src/ui/component-dialog/component-dialog-preload.ts +++ b/src/renderer/src/ui/component-dialog/component-dialog-preload.ts @@ -208,7 +208,6 @@ const validSendChannels = [ 'open-about-dialog', 'open-printer-selection', 'open-job-uploader', - 'open-ifs-dialog', 'window-minimize', 'window-maximize', 'window-close', diff --git a/src/renderer/src/ui/component-dialog/component-dialog.ts b/src/renderer/src/ui/component-dialog/component-dialog.ts index caded76..6fb22aa 100644 --- a/src/renderer/src/ui/component-dialog/component-dialog.ts +++ b/src/renderer/src/ui/component-dialog/component-dialog.ts @@ -29,9 +29,9 @@ import { CameraPreviewComponent, ControlsGridComponent, FiltrationControlsComponent, - IFSStationComponent, JobStatsComponent, LogPanelComponent, + MaterialStationComponent, ModelPreviewComponent, PrinterStatusComponent, SpoolmanComponent, @@ -193,8 +193,8 @@ function createComponentInstance(componentId: string, container: HTMLElement) { return new FiltrationControlsComponent(container); case 'spoolman-tracker': return new SpoolmanComponent(container); - case 'ifs-station': - return new IFSStationComponent(container); + case 'material-station': + return new MaterialStationComponent(container); case 'tool-temps': return new ToolTempsComponent(container); default: diff --git a/src/renderer/src/ui/components/ifs-station/index.ts b/src/renderer/src/ui/components/ifs-station/index.ts deleted file mode 100644 index 73cdc66..0000000 --- a/src/renderer/src/ui/components/ifs-station/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @fileoverview IFS Station Component Exports - * - * Central export point for IFS (Intelligent Filament System) component and related types. - * Provides the IFSStationComponent class for displaying material station status on AD5X printers. - * - * @module ui/components/ifs-station - */ - -export { IFSStationComponent } from './ifs-station.js'; -export type { IFSComponentState, IFSLayoutMode, MaterialSlot, MaterialStationStatus } from './types.js'; diff --git a/src/renderer/src/ui/components/index.ts b/src/renderer/src/ui/components/index.ts index 9926a80..d1a12cc 100644 --- a/src/renderer/src/ui/components/index.ts +++ b/src/renderer/src/ui/components/index.ts @@ -24,8 +24,8 @@ export { ComponentManager, componentManager } from './ComponentManager.js'; export { CameraPreviewComponent } from './camera-preview/index.js'; export { ControlsGridComponent } from './controls-grid/index.js'; export { FiltrationControlsComponent } from './filtration-controls/index.js'; -// IFS Material Station Component -export { IFSStationComponent } from './ifs-station/index.js'; +// Material Station Component (AD5X + Creator 5 / 5 Pro) +export { MaterialStationComponent } from './material-station/index.js'; export { JobInfoComponent } from './job-info/index.js'; // Individual components - All 10 Phase 1 components export { JobStatsComponent } from './job-stats/index.js'; diff --git a/src/renderer/src/ui/components/material-station/index.ts b/src/renderer/src/ui/components/material-station/index.ts new file mode 100644 index 0000000..a0e2c9f --- /dev/null +++ b/src/renderer/src/ui/components/material-station/index.ts @@ -0,0 +1,17 @@ +/** + * @fileoverview Material Station Component Exports + * + * Central export point for the material-station component and related types. + * Provides the MaterialStationComponent class for displaying material-station + * status on printers that have one (AD5X IFS + Creator 5 / 5 Pro). + * + * @module ui/components/material-station + */ + +export { MaterialStationComponent } from './material-station.js'; +export type { + MaterialStationComponentState, + MaterialStationLayoutMode, + MaterialSlot, + MaterialStationStatus, +} from './types.js'; diff --git a/src/renderer/src/ui/components/ifs-station/ifs-station.css b/src/renderer/src/ui/components/material-station/material-station.css similarity index 81% rename from src/renderer/src/ui/components/ifs-station/ifs-station.css rename to src/renderer/src/ui/components/material-station/material-station.css index 944afc9..e111e81 100644 --- a/src/renderer/src/ui/components/ifs-station/ifs-station.css +++ b/src/renderer/src/ui/components/material-station/material-station.css @@ -1,7 +1,7 @@ /** - * @fileoverview IFS Material Station Component Styles + * @fileoverview Material Station Component Styles * - * Styling for the IFS (Intelligent Filament System) material station component + * Styling for the material station component (AD5X IFS + Creator 5 / 5 Pro) * with responsive layouts for different grid cell sizes. Supports horizontal, * vertical, square, and compact layout modes. * @@ -17,14 +17,14 @@ ============================================================================ */ /* Ensure the component container fills its parent */ -.component-ifs-station { +.component-material-station { width: 100%; height: 100%; display: flex; flex-direction: column; } -.ifs-component { +.ms-component { width: 100%; height: 100%; flex: 1; @@ -41,7 +41,7 @@ overflow: hidden; } -.ifs-state { +.ms-state { display: none; flex-direction: column; align-items: center; @@ -55,18 +55,18 @@ UNAVAILABLE STATE (non-AD5X printers) ============================================================================ */ -.ifs-unavailable { +.ms-unavailable { text-align: center; } -.ifs-icon { +.ms-icon { width: 48px; height: 48px; opacity: 0.4; color: var(--text-color-muted); } -.ifs-message { +.ms-message { color: var(--text-color-muted); font-size: 13px; line-height: 1.5; @@ -79,11 +79,11 @@ DISCONNECTED STATE ============================================================================ */ -.ifs-disconnected { +.ms-disconnected { text-align: center; } -.ifs-disconnected .ifs-icon { +.ms-disconnected .ms-icon { color: var(--theme-warning, #ff9800); opacity: 0.7; } @@ -92,12 +92,12 @@ ACTIVE STATE ============================================================================ */ -.ifs-active { +.ms-active { gap: 8px; padding: 4px; } -.ifs-header { +.ms-header { display: flex; align-items: center; justify-content: space-between; @@ -106,7 +106,7 @@ flex-shrink: 0; } -.ifs-title { +.ms-title { font-size: 12px; font-weight: 600; color: var(--text-color-muted); @@ -114,7 +114,7 @@ letter-spacing: 0.5px; } -.ifs-active-indicator { +.ms-active-indicator { font-size: 11px; color: var(--theme-primary); font-weight: 500; @@ -122,7 +122,7 @@ transition: opacity 0.2s ease; } -.ifs-active-indicator.visible { +.ms-active-indicator.visible { opacity: 1; } @@ -130,7 +130,7 @@ SLOTS CONTAINER - BASE STYLES ============================================================================ */ -.ifs-slots-container { +.ms-slots-container { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; @@ -145,7 +145,7 @@ INDIVIDUAL SLOT STYLES ============================================================================ */ -.ifs-slot { +.ms-slot { display: flex; flex-direction: column; align-items: center; @@ -161,17 +161,17 @@ overflow: hidden; } -.ifs-slot:hover { +.ms-slot:hover { background: color-mix(in srgb, var(--surface-elevated, var(--theme-surface)) 90%, var(--theme-primary)); border-color: var(--border-color-light, var(--border-color)); } -.ifs-slot.active { +.ms-slot.active { border-color: var(--theme-primary); box-shadow: 0 0 8px color-mix(in srgb, var(--theme-primary) 30%, transparent); } -.ifs-slot.empty { +.ms-slot.empty { opacity: 0.6; } @@ -179,7 +179,7 @@ SPOOL VISUAL ============================================================================ */ -.ifs-spool { +.ms-spool { width: 40px; height: 40px; border-radius: 50%; @@ -195,15 +195,15 @@ transition: transform 0.2s ease, background-color 0.2s ease; } -.ifs-slot:hover .ifs-spool { +.ms-slot:hover .ms-spool { transform: scale(1.05); } -.ifs-slot.active .ifs-spool { +.ms-slot.active .ms-spool { border-color: var(--theme-primary); } -.ifs-spool-center { +.ms-spool-center { width: 12px; height: 12px; border-radius: 50%; @@ -215,7 +215,7 @@ SLOT INFO ============================================================================ */ -.ifs-slot-info { +.ms-slot-info { display: flex; flex-direction: column; align-items: center; @@ -224,14 +224,14 @@ width: 100%; } -.ifs-slot-label { +.ms-slot-label { font-size: 10px; font-weight: 600; color: var(--text-color); white-space: nowrap; } -.ifs-slot-material { +.ms-slot-material { font-size: 9px; color: var(--text-color-muted); padding: 2px 6px; @@ -243,12 +243,12 @@ max-width: 100%; } -.ifs-slot.has-material .ifs-slot-material { +.ms-slot.has-material .ms-slot-material { background: color-mix(in srgb, var(--theme-primary) 15%, transparent); color: var(--theme-primary); } -.ifs-slot.empty .ifs-slot-material { +.ms-slot.empty .ms-slot-material { font-style: italic; } @@ -256,27 +256,27 @@ LAYOUT: HORIZONTAL (wide container) ============================================================================ */ -.ifs-component.layout-horizontal { +.ms-component.layout-horizontal { padding: 8px; } -.ifs-component.layout-horizontal .ifs-header { +.ms-component.layout-horizontal .ms-header { display: none; } -.ifs-component.layout-horizontal .ifs-slots-container { +.ms-component.layout-horizontal .ms-slots-container { grid-template-columns: repeat(4, 1fr); grid-template-rows: 1fr; } -.ifs-component.layout-horizontal .ifs-slot { +.ms-component.layout-horizontal .ms-slot { flex-direction: column; padding: 4px; gap: 2px; } /* Dynamic spool sizing - scales with available height */ -.ifs-component.layout-horizontal .ifs-spool { +.ms-component.layout-horizontal .ms-spool { width: auto; height: 50%; max-height: 44px; @@ -285,23 +285,23 @@ flex-shrink: 1; } -.ifs-component.layout-horizontal .ifs-spool-center { +.ms-component.layout-horizontal .ms-spool-center { width: 30%; height: 30%; min-width: 6px; min-height: 6px; } -.ifs-component.layout-horizontal .ifs-slot-info { +.ms-component.layout-horizontal .ms-slot-info { gap: 1px; min-height: 0; } -.ifs-component.layout-horizontal .ifs-slot-label { +.ms-component.layout-horizontal .ms-slot-label { font-size: 9px; } -.ifs-component.layout-horizontal .ifs-slot-material { +.ms-component.layout-horizontal .ms-slot-material { font-size: 8px; padding: 1px 4px; } @@ -310,38 +310,38 @@ LAYOUT: VERTICAL (tall container) ============================================================================ */ -.ifs-component.layout-vertical .ifs-slots-container { +.ms-component.layout-vertical .ms-slots-container { grid-template-columns: 1fr; grid-template-rows: repeat(4, 1fr); } -.ifs-component.layout-vertical .ifs-slot { +.ms-component.layout-vertical .ms-slot { flex-direction: row; justify-content: flex-start; padding: 6px 12px; gap: 10px; } -.ifs-component.layout-vertical .ifs-slot-info { +.ms-component.layout-vertical .ms-slot-info { align-items: flex-start; flex: 1; } -.ifs-component.layout-vertical .ifs-spool { +.ms-component.layout-vertical .ms-spool { width: 36px; height: 36px; } -.ifs-component.layout-vertical .ifs-spool-center { +.ms-component.layout-vertical .ms-spool-center { width: 10px; height: 10px; } -.ifs-component.layout-vertical .ifs-slot-label { +.ms-component.layout-vertical .ms-slot-label { font-size: 11px; } -.ifs-component.layout-vertical .ifs-slot-material { +.ms-component.layout-vertical .ms-slot-material { font-size: 10px; } @@ -349,7 +349,7 @@ LAYOUT: SQUARE (2x2 grid - default) ============================================================================ */ -.ifs-component.layout-square .ifs-slots-container { +.ms-component.layout-square .ms-slots-container { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; } @@ -358,43 +358,43 @@ LAYOUT: COMPACT (small container) ============================================================================ */ -.ifs-component.layout-compact { +.ms-component.layout-compact { padding: 6px; } -.ifs-component.layout-compact .ifs-header { +.ms-component.layout-compact .ms-header { display: none; } -.ifs-component.layout-compact .ifs-slots-container { +.ms-component.layout-compact .ms-slots-container { grid-template-columns: repeat(4, 1fr); grid-template-rows: 1fr; gap: 4px; } -.ifs-component.layout-compact .ifs-slot { +.ms-component.layout-compact .ms-slot { padding: 4px; gap: 2px; } -.ifs-component.layout-compact .ifs-spool { +.ms-component.layout-compact .ms-spool { width: 24px; height: 24px; border-width: 2px; } -.ifs-component.layout-compact .ifs-spool-center { +.ms-component.layout-compact .ms-spool-center { width: 6px; height: 6px; border-width: 1px; } -.ifs-component.layout-compact .ifs-slot-info { +.ms-component.layout-compact .ms-slot-info { display: none; } /* Show slot number as overlay in compact mode */ -.ifs-component.layout-compact .ifs-slot::after { +.ms-component.layout-compact .ms-slot::after { content: attr(data-slot); position: absolute; bottom: 2px; @@ -404,7 +404,7 @@ font-weight: 600; } -.ifs-component.layout-compact .ifs-slot { +.ms-component.layout-compact .ms-slot { position: relative; } @@ -412,13 +412,13 @@ UNAVAILABLE/DISCONNECTED STATES - SIZE ADJUSTMENTS ============================================================================ */ -.ifs-component.layout-compact .ifs-unavailable .ifs-icon, -.ifs-component.layout-compact .ifs-disconnected .ifs-icon { +.ms-component.layout-compact .ms-unavailable .ms-icon, +.ms-component.layout-compact .ms-disconnected .ms-icon { width: 32px; height: 32px; } -.ifs-component.layout-compact .ifs-message { +.ms-component.layout-compact .ms-message { font-size: 11px; } @@ -435,13 +435,13 @@ } } -.ifs-slot.active { +.ms-slot.active { animation: pulse-glow 2s ease-in-out infinite; } /* Disable animation when prefers-reduced-motion */ @media (prefers-reduced-motion: reduce) { - .ifs-slot.active { + .ms-slot.active { animation: none; } } @@ -451,13 +451,13 @@ ============================================================================ */ /* Slots are clickable when the editor flow is available */ -.ifs-slot { +.ms-slot { cursor: pointer; } /* ---- Slot editor dialog (manual material/color picker) ---- */ -.ifs-dialog-backdrop { +.ms-dialog-backdrop { position: fixed; inset: 0; z-index: 10000; @@ -467,10 +467,10 @@ padding: 16px; background: color-mix(in srgb, var(--theme-background, #000) 55%, transparent); backdrop-filter: blur(2px); - animation: ifs-dialog-fade 0.12s ease-out; + animation: ms-dialog-fade 0.12s ease-out; } -@keyframes ifs-dialog-fade { +@keyframes ms-dialog-fade { from { opacity: 0; } @@ -479,7 +479,7 @@ } } -.ifs-dialog { +.ms-dialog { display: flex; flex-direction: column; width: 100%; @@ -490,10 +490,10 @@ border: 1px solid var(--border-color); border-radius: 12px; box-shadow: 0 12px 40px color-mix(in srgb, var(--theme-background, #000) 60%, black); - animation: ifs-dialog-pop 0.14s ease-out; + animation: ms-dialog-pop 0.14s ease-out; } -@keyframes ifs-dialog-pop { +@keyframes ms-dialog-pop { from { transform: translateY(8px) scale(0.98); opacity: 0; @@ -504,7 +504,7 @@ } } -.ifs-dialog-header { +.ms-dialog-header { display: flex; align-items: center; justify-content: space-between; @@ -513,13 +513,13 @@ border-bottom: 1px solid var(--border-color); } -.ifs-dialog-title { +.ms-dialog-title { font-size: 14px; font-weight: 600; color: var(--theme-text, var(--text-color)); } -.ifs-dialog-close { +.ms-dialog-close { display: flex; align-items: center; justify-content: center; @@ -535,12 +535,12 @@ transition: background 0.15s ease, color 0.15s ease; } -.ifs-dialog-close:hover { +.ms-dialog-close:hover { color: var(--theme-text, var(--text-color)); background: var(--surface-muted, color-mix(in srgb, var(--theme-text, #fff) 10%, transparent)); } -.ifs-dialog-body { +.ms-dialog-body { display: flex; flex-direction: column; gap: 16px; @@ -548,13 +548,13 @@ overflow-y: auto; } -.ifs-dialog-field { +.ms-dialog-field { display: flex; flex-direction: column; gap: 8px; } -.ifs-dialog-label { +.ms-dialog-label { font-size: 11px; font-weight: 600; text-transform: uppercase; @@ -562,7 +562,7 @@ color: var(--text-color-muted); } -.ifs-dialog-material { +.ms-dialog-material { width: 100%; padding: 8px 10px; font-size: 13px; @@ -573,18 +573,18 @@ cursor: pointer; } -.ifs-dialog-material:focus { +.ms-dialog-material:focus { outline: none; border-color: var(--theme-primary); } -.ifs-swatch-grid { +.ms-swatch-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; } -.ifs-swatch { +.ms-swatch { position: relative; aspect-ratio: 1 / 1; padding: 0; @@ -595,16 +595,16 @@ transition: transform 0.1s ease, box-shadow 0.1s ease; } -.ifs-swatch:hover { +.ms-swatch:hover { transform: scale(1.08); } -.ifs-swatch.selected { +.ms-swatch.selected { box-shadow: 0 0 0 2px var(--surface-elevated, var(--theme-surface)), 0 0 0 4px var(--theme-primary); } -.ifs-swatch-check { +.ms-swatch-check { position: absolute; inset: 0; display: none; @@ -616,17 +616,17 @@ text-shadow: 0 0 2px rgba(0, 0, 0, 0.9), 0 0 3px rgba(0, 0, 0, 0.7); } -.ifs-swatch.selected .ifs-swatch-check { +.ms-swatch.selected .ms-swatch-check { display: flex; } -.ifs-dialog-preview { +.ms-dialog-preview { font-size: 12px; color: var(--text-color-muted); min-height: 16px; } -.ifs-dialog-footer { +.ms-dialog-footer { display: flex; align-items: center; justify-content: space-between; @@ -635,13 +635,13 @@ border-top: 1px solid var(--border-color); } -.ifs-dialog-footer-right { +.ms-dialog-footer-right { display: flex; gap: 8px; margin-left: auto; } -.ifs-dialog-footer button { +.ms-dialog-footer button { font-size: 12px; font-weight: 500; padding: 7px 14px; @@ -650,37 +650,37 @@ transition: background 0.15s ease, opacity 0.15s ease; } -.ifs-dialog-cancel { +.ms-dialog-cancel { color: var(--theme-text, var(--text-color)); background: var(--surface-muted, transparent); border: 1px solid var(--border-color); } -.ifs-dialog-cancel:hover { +.ms-dialog-cancel:hover { background: color-mix(in srgb, var(--theme-text, #fff) 10%, transparent); } -.ifs-dialog-spoolman { +.ms-dialog-spoolman { color: var(--theme-text, var(--text-color)); background: color-mix(in srgb, var(--theme-primary) 14%, transparent); border: 1px solid color-mix(in srgb, var(--theme-primary) 40%, transparent); } -.ifs-dialog-spoolman:hover { +.ms-dialog-spoolman:hover { background: color-mix(in srgb, var(--theme-primary) 26%, transparent); } -.ifs-dialog-apply { +.ms-dialog-apply { color: #fff; background: var(--theme-primary); border: 1px solid var(--theme-primary); } -.ifs-dialog-apply:hover:not(:disabled) { +.ms-dialog-apply:hover:not(:disabled) { background: color-mix(in srgb, var(--theme-primary) 85%, black); } -.ifs-dialog-apply:disabled { +.ms-dialog-apply:disabled { opacity: 0.45; cursor: not-allowed; } diff --git a/src/renderer/src/ui/components/ifs-station/ifs-station.ts b/src/renderer/src/ui/components/material-station/material-station.ts similarity index 72% rename from src/renderer/src/ui/components/ifs-station/ifs-station.ts rename to src/renderer/src/ui/components/material-station/material-station.ts index 310bb21..c2b4dad 100644 --- a/src/renderer/src/ui/components/ifs-station/ifs-station.ts +++ b/src/renderer/src/ui/components/material-station/material-station.ts @@ -1,8 +1,8 @@ /** - * @fileoverview IFS Material Station Component + * @fileoverview Material Station Component * - * GridStack component for displaying the Intelligent Filament System (IFS) - * material station status on AD5X printers. Shows real-time slot status, + * GridStack component for displaying material-station status on printers that + * have one (the AD5X IFS and the Creator 5 / 5 Pro). Shows real-time slot status, * filament types, colors, and active slot information with responsive layouts * that adapt to different grid cell sizes. * @@ -11,17 +11,18 @@ * - Responsive layouts: horizontal, vertical, square, compact * - Real-time material slot visualization with color coding * - Active slot highlighting - * - Per-context availability (only AD5X printers with material station) + * - Per-context availability (printers with a material station: AD5X + Creator 5 / 5 Pro) + * - Per-model fixed palette in the slot editor (AD5X vs Creator 5 — see @shared/palette) * - * @module ui/components/ifs-station + * @module ui/components/material-station */ -import { IFS_COLORS, IFS_MATERIALS, nearestColor, nearestMaterial } from '@shared/ifs-palette.js'; +import { getPaletteForModel, type Palette } from '@shared/palette.js'; import type { MaterialStationStatus } from '@shared/types/polling.js'; import { BaseComponent } from '../base/component.js'; import type { ComponentUpdateData } from '../base/types.js'; -import type { IFSLayoutMode, MaterialSlot } from './types.js'; -import './ifs-station.css'; +import type { MaterialSlot, MaterialStationLayoutMode } from './types.js'; +import './material-station.css'; /** Shape of a spool handed back from the Spoolman picker (a subset of ActiveSpoolData). */ interface PickedSpool { @@ -32,66 +33,66 @@ interface PickedSpool { } /** - * IFS Material Station component - * Displays material station status for AD5X printers with responsive layouts + * Material Station component + * Displays material station status (AD5X + Creator 5 / 5 Pro) with responsive layouts */ -export class IFSStationComponent extends BaseComponent { - public readonly componentId = 'ifs-station'; +export class MaterialStationComponent extends BaseComponent { + public readonly componentId = 'material-station'; public readonly templateHTML = ` -
+
-
- -

IFS not available on this printer

+
+ +

Material station not available on this printer

-
- -

Material station disconnected

+
+ +

Material station disconnected

-
-
- Material Station - +
+
+ Material Station +
-
-
-
-
+
+
+
+
-
- Slot 1 - Empty +
+ Slot 1 + Empty
-
-
-
+
+
+
-
- Slot 2 - Empty +
+ Slot 2 + Empty
-
-
-
+
+
+
-
- Slot 3 - Empty +
+ Slot 3 + Empty
-
-
-
+
+
+
-
- Slot 4 - Empty +
+ Slot 4 + Empty
@@ -104,8 +105,7 @@ export class IFSStationComponent extends BaseComponent { private isConnected = false; private slots: MaterialSlot[] = []; private activeSlot: number | null = null; - private errorMessage: string | null = null; - private currentLayout: IFSLayoutMode = 'square'; + private currentLayout: MaterialStationLayoutMode = 'square'; // DOM references private unavailableView: HTMLElement | null = null; @@ -117,6 +117,13 @@ export class IFSStationComponent extends BaseComponent { // ResizeObserver for responsive layout private resizeObserver: ResizeObserver | null = null; + /** + * Fixed filament palette for the connected printer, refreshed from polling data. + * The Creator 5 / 5 Pro use a different palette than the AD5X; defaults to the + * AD5X palette until the model is known. See `@shared/palette`. + */ + private palette: Palette = getPaletteForModel(null); + // Slot editor state private contextId: string | null = null; /** Slot (1-4) currently being edited, or null when the dialog is closed. */ @@ -137,11 +144,11 @@ export class IFSStationComponent extends BaseComponent { */ protected async setupEventListeners(): Promise { // Cache DOM references - this.unavailableView = this.findElementByClass('ifs-unavailable'); - this.disconnectedView = this.findElementByClass('ifs-disconnected'); - this.activeView = this.findElementByClass('ifs-active'); - this.slotsContainer = this.findElementByClass('ifs-slots-container'); - this.activeIndicator = this.findElementByClass('ifs-active-indicator'); + this.unavailableView = this.findElementByClass('ms-unavailable'); + this.disconnectedView = this.findElementByClass('ms-disconnected'); + this.activeView = this.findElementByClass('ms-active'); + this.slotsContainer = this.findElementByClass('ms-slots-container'); + this.activeIndicator = this.findElementByClass('ms-active-indicator'); // Initialize Lucide icons this.initializeIcons(); @@ -165,7 +172,7 @@ export class IFSStationComponent extends BaseComponent { if (!this.slotsContainer) return; this.slotsContainer.addEventListener('click', (event) => { - const slotEl = (event.target as HTMLElement)?.closest('.ifs-slot') as HTMLElement | null; + const slotEl = (event.target as HTMLElement)?.closest('.ms-slot') as HTMLElement | null; if (!slotEl) return; const slotAttr = slotEl.getAttribute('data-slot'); const slot = slotAttr ? Number.parseInt(slotAttr, 10) : NaN; @@ -226,7 +233,10 @@ export class IFSStationComponent extends BaseComponent { this.isConnected = materialStation?.connected ?? false; this.slots = materialStation?.slots ?? []; this.activeSlot = materialStation?.activeSlot ?? null; - this.errorMessage = materialStation?.errorMessage ?? null; + + // Select the model's fixed palette (Creator 5 differs from AD5X). Falls back + // to the AD5X palette when the model is absent from the payload. + this.palette = getPaletteForModel(materialStation?.printerModelType); // Track the active printer context for slot-config IPC calls (falls back to // the active context server-side when null). @@ -237,7 +247,7 @@ export class IFSStationComponent extends BaseComponent { this.updateState(data); this.updateView(); } catch (error) { - console.error(`[IFSStation] Error updating component:`, error); + console.error(`[MaterialStation] Error updating component:`, error); } } @@ -258,7 +268,7 @@ export class IFSStationComponent extends BaseComponent { * - Dialog: Always 2x2 square layout * - Grid: Dynamic based on container size */ - private determineLayout(): IFSLayoutMode { + private determineLayout(): MaterialStationLayoutMode { // Dialogs always use square layout if (this.isInDialog()) { return 'square'; @@ -315,7 +325,7 @@ export class IFSStationComponent extends BaseComponent { this.currentLayout = newLayout; // Update CSS class on container - const component = this.container?.querySelector('.ifs-component'); + const component = this.container?.querySelector('.ms-component'); if (component) { component.classList.remove('layout-horizontal', 'layout-vertical', 'layout-square', 'layout-compact'); component.classList.add(`layout-${newLayout}`); @@ -349,7 +359,7 @@ export class IFSStationComponent extends BaseComponent { private renderSlots(): void { if (!this.slotsContainer) return; - // AD5X has 4 slots with 1-based IDs (1, 2, 3, 4) + // AD5X and Creator 5 both expose 4 slots with 1-based IDs (1, 2, 3, 4). for (let slotNumber = 1; slotNumber <= 4; slotNumber++) { const slotElement = this.slotsContainer.querySelector(`[data-slot="${slotNumber}"]`); if (!slotElement) continue; @@ -376,8 +386,8 @@ export class IFSStationComponent extends BaseComponent { * Render a single material slot */ private renderSingleSlot(element: HTMLElement, slotNumber: number, data?: MaterialSlot): void { - const spoolElement = element.querySelector('.ifs-spool') as HTMLElement; - const materialElement = element.querySelector('.ifs-slot-material') as HTMLElement; + const spoolElement = element.querySelector('.ms-spool') as HTMLElement; + const materialElement = element.querySelector('.ms-slot-material') as HTMLElement; // Reset classes element.classList.remove('empty', 'active', 'has-material'); @@ -432,48 +442,48 @@ export class IFSStationComponent extends BaseComponent { // Seed selections from the slot's current material/color, snapped to the palette. const current = this.slots.find((s) => s.slotId === slot && !s.isEmpty); - const matchedMaterial = current?.materialType ? nearestMaterial(current.materialType) : null; - this.dialogMaterial = matchedMaterial ?? IFS_MATERIALS[0] ?? 'PLA'; - const matchedColor = current?.materialColor ? nearestColor(current.materialColor) : null; + const matchedMaterial = current?.materialType ? this.palette.nearestMaterial(current.materialType) : null; + this.dialogMaterial = matchedMaterial ?? this.palette.materials[0] ?? 'PLA'; + const matchedColor = current?.materialColor ? this.palette.nearestColor(current.materialColor) : null; this.dialogColorHex = matchedColor?.hex ?? null; const backdrop = document.createElement('div'); - backdrop.className = 'ifs-dialog-backdrop'; + backdrop.className = 'ms-dialog-backdrop'; const dialog = document.createElement('div'); - dialog.className = 'ifs-dialog'; + dialog.className = 'ms-dialog'; dialog.setAttribute('role', 'dialog'); dialog.setAttribute('aria-modal', 'true'); - const materialOptions = IFS_MATERIALS.map( + const materialOptions = this.palette.materials.map( (m) => `` ).join(''); - const swatches = IFS_COLORS.map( + const swatches = this.palette.colors.map( (c) => - `` + `` ).join(''); dialog.innerHTML = ` -
- Configure Slot ${slot} - +
+ Configure Slot ${slot} +
-
-
+ + + + + + + + + + + +
diff --git a/src/main/webui/static/shared/icons.ts b/src/main/webui/static/shared/icons.ts index 5c6f04b..90a6ee3 100644 --- a/src/main/webui/static/shared/icons.ts +++ b/src/main/webui/static/shared/icons.ts @@ -74,5 +74,8 @@ export function hydrateLucideIcons(iconNames: string[], root: Document | Element } export function initializeLucideIcons(): void { - hydrateLucideIcons(['settings', 'lock', 'package', 'search', 'circle', 'plus'], document); + hydrateLucideIcons( + ['settings', 'lock', 'package', 'search', 'circle', 'plus', 'folder', 'gauge', 'power'], + document + ); } diff --git a/src/main/webui/static/webui.css b/src/main/webui/static/webui.css index c365a95..6156ac2 100644 --- a/src/main/webui/static/webui.css +++ b/src/main/webui/static/webui.css @@ -65,7 +65,7 @@ --warning-alpha-40: color-mix(in srgb, var(--warning-color) 40%, transparent); /* Surface/Background utilities */ - --overlay-bg: var(--overlay-bg); + --overlay-bg: rgba(0, 0, 0, 0.6); --surface-muted: color-mix(in srgb, var(--theme-text) 10%, var(--theme-surface)); --text-on-primary: #ffffff; } @@ -2031,3 +2031,1356 @@ body { text-align: left; } } + +/* ============================================================================ + FILE MANAGER (SFTP printer files) + ============================================================================ */ + +.fm-modal-content { + position: relative; + display: flex; + flex-direction: column; + height: min(720px, 90vh); +} + +.fm-modal-body { + display: flex; + flex-direction: column; + flex: 1; + overflow: hidden; +} + +.fm-tabs { + display: flex; + align-items: center; + gap: 8px; + border-bottom: 1px solid var(--border-color); + padding-bottom: 8px; + flex-shrink: 0; +} + +.fm-tab { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 16px; + background: transparent; + border: 1px solid transparent; + border-radius: 6px; + color: var(--text-color-secondary); + font-size: 0.95rem; + cursor: pointer; + transition: background-color var(--transition-fast), border-color var(--transition-fast); +} + +.fm-tab:hover { + background: var(--card-bg-hover); + color: var(--text-color); +} + +.fm-tab.active { + background: var(--primary-alpha-20); + border-color: var(--theme-primary); + color: var(--text-color); +} + +.fm-tab .lucide-icon { + width: 16px; + height: 16px; +} + +.fm-tabs-spacer { + flex: 1; +} + +.fm-toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 10px 0; + flex-shrink: 0; + min-height: 48px; +} + +.fm-toolbar-actions { + display: flex; + align-items: center; + gap: 8px; + margin-left: auto; +} + +.fm-toolbar-btn { + display: flex; + align-items: center; + gap: 6px; + padding: 6px 12px; + background: var(--theme-surface); + border: 1px solid var(--border-color); + border-radius: 6px; + color: var(--text-color); + font-size: 0.85rem; + cursor: pointer; + transition: background-color var(--transition-fast), border-color var(--transition-fast); +} + +.fm-toolbar-btn:hover:not(:disabled) { + background: var(--card-bg-hover); + border-color: var(--border-color-focus); +} + +.fm-toolbar-btn:disabled { + opacity: 0.5; + cursor: default; +} + +.fm-toolbar-btn .lucide-icon { + width: 15px; + height: 15px; +} + +.fm-toolbar-btn.danger { + background: color-mix(in srgb, var(--error-color) 18%, var(--theme-surface)); + border-color: color-mix(in srgb, var(--error-color) 60%, var(--border-color)); +} + +.fm-toolbar-btn.danger:hover:not(:disabled) { + background: color-mix(in srgb, var(--error-color) 32%, var(--theme-surface)); +} + +.fm-breadcrumb { + display: flex; + align-items: center; + gap: 4px; + flex-wrap: wrap; + font-size: 0.85rem; + color: var(--text-color-secondary); + min-width: 0; +} + +.fm-breadcrumb button { + background: none; + border: none; + color: var(--theme-primary); + cursor: pointer; + font-size: 0.85rem; + padding: 4px 6px; + border-radius: 4px; +} + +.fm-breadcrumb button:hover { + background: var(--card-bg-hover); +} + +.fm-breadcrumb .crumb-current { + padding: 4px 6px; + color: var(--text-color); + font-weight: 500; +} + +.fm-breadcrumb .lucide-icon { + width: 13px; + height: 13px; + opacity: 0.6; +} + +.fm-body { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; + padding-bottom: 12px; +} + +.fm-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + gap: 14px; + padding: 4px 4px 12px 4px; + overflow-y: auto; + flex: 1; + align-content: start; +} + +.fm-item { + background-color: var(--theme-surface); + border: 1px solid var(--border-color); + border-radius: 8px; + padding: 12px 10px 10px 10px; + display: flex; + flex-direction: column; + align-items: center; + position: relative; + transition: background-color var(--transition-fast), border-color var(--transition-fast); +} + +.fm-item:hover { + background-color: var(--card-bg-hover); + border-color: var(--border-color-focus); +} + +.fm-item.selected { + background-color: var(--primary-alpha-15); + border-color: var(--theme-primary); +} + +.fm-item.directory { + cursor: pointer; +} + +.fm-item.pending { + opacity: 0.45; + pointer-events: none; +} + +.fm-item-controls { + position: absolute; + top: 6px; + right: 6px; + display: flex; + gap: 4px; + opacity: 0; + transition: opacity var(--transition-fast); + z-index: 5; +} + +.fm-item:hover .fm-item-controls, +.fm-item.selected .fm-item-controls { + opacity: 1; +} + +.fm-item-btn { + width: 26px; + height: 26px; + display: flex; + align-items: center; + justify-content: center; + background: color-mix(in srgb, var(--theme-background) 80%, transparent); + border: 1px solid var(--border-color); + border-radius: 6px; + color: var(--text-color); + cursor: pointer; + transition: background-color var(--transition-fast), border-color var(--transition-fast); + padding: 0; +} + +.fm-item-btn:hover { + background: var(--card-bg-hover); + border-color: var(--border-color-focus); +} + +.fm-item-btn.delete:hover { + background: color-mix(in srgb, var(--error-color) 30%, var(--theme-surface)); + border-color: var(--error-color); +} + +.fm-item-btn .lucide-icon { + width: 14px; + height: 14px; +} + +.fm-item-check { + position: absolute; + top: 6px; + left: 6px; + width: 22px; + height: 22px; + display: flex; + align-items: center; + justify-content: center; + background: color-mix(in srgb, var(--theme-background) 80%, transparent); + border: 1px solid var(--border-color); + border-radius: 6px; + color: transparent; + cursor: pointer; + opacity: 0; + transition: opacity var(--transition-fast), background-color var(--transition-fast); + z-index: 5; + padding: 0; +} + +.fm-item:hover .fm-item-check, +.fm-item.selected .fm-item-check { + opacity: 1; +} + +.fm-item.selected .fm-item-check { + background: var(--theme-primary); + border-color: var(--theme-primary); + color: var(--text-on-primary); +} + +.fm-item-check .lucide-icon { + width: 13px; + height: 13px; +} + +.fm-thumbnail { + width: 110px; + height: 110px; + display: flex; + justify-content: center; + align-items: center; + background-color: var(--surface-muted); + border-radius: 6px; + margin-bottom: 8px; + overflow: hidden; +} + +.fm-thumbnail img { + max-width: 100%; + max-height: 100%; +} + +.fm-thumbnail .lucide-icon { + width: 42px; + height: 42px; + opacity: 0.35; +} + +.fm-thumbnail .thumb-spinner { + width: 22px; + height: 22px; + border: 2px solid color-mix(in srgb, var(--text-color) 20%, transparent); + border-top-color: var(--theme-primary); + border-radius: 50%; + animation: fm-spin 0.9s linear infinite; +} + +.fm-name { + font-size: 0.82rem; + color: var(--text-color); + text-align: center; + word-break: break-word; + line-height: 1.3; + max-height: 2.6em; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; +} + +.fm-size { + font-size: 0.72rem; + color: var(--text-color-muted); + margin-top: 4px; +} + +.fm-state { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 14px; + padding: 24px; + text-align: center; +} + +.fm-state-text { + color: var(--text-color-secondary); + font-size: 0.95rem; + max-width: 480px; + line-height: 1.5; +} + +.fm-state-icon.lucide-icon, +.fm-state .fm-state-icon { + width: 40px; + height: 40px; + color: var(--text-color-muted); +} + +.fm-state .loading-spinner, +.reboot-overlay-panel .loading-spinner { + width: 36px; + height: 36px; + border: 3px solid color-mix(in srgb, var(--text-color) 15%, transparent); + border-top-color: var(--theme-primary); + border-radius: 50%; + animation: fm-spin 0.9s linear infinite; +} + +@keyframes fm-spin { + to { + transform: rotate(360deg); + } +} + +.fm-footer { + justify-content: space-between; +} + +.fm-summary { + font-size: 0.85rem; + color: var(--text-color-secondary); +} + +.fm-overlay { + position: absolute; + inset: 0; + background: color-mix(in srgb, var(--theme-background) 65%, transparent); + display: flex; + align-items: center; + justify-content: center; + z-index: 100; + border-radius: inherit; +} + +.fm-overlay-panel { + background: var(--theme-surface); + border: 1px solid var(--border-color); + border-radius: 10px; + box-shadow: var(--shadow-lg); + width: min(440px, calc(100% - 48px)); + padding: 20px; + display: flex; + flex-direction: column; + gap: 16px; +} + +.fm-overlay-title { + display: flex; + align-items: center; + gap: 10px; + font-size: 1.05rem; + font-weight: 600; + color: var(--text-color); +} + +.fm-overlay-title .lucide-icon { + width: 18px; + height: 18px; +} + +.fm-overlay-body { + color: var(--text-color-secondary); + font-size: 0.9rem; + line-height: 1.5; + max-height: 220px; + overflow-y: auto; +} + +.fm-overlay-body ul { + margin: 8px 0 0 0; + padding-left: 18px; +} + +.fm-overlay-body li { + word-break: break-word; +} + +.fm-overlay-actions { + display: flex; + justify-content: flex-end; + gap: 10px; +} + +.fm-rename-row { + display: flex; + align-items: center; + gap: 6px; +} + +.fm-rename-row input { + flex: 1; + padding: 8px 10px; + background: var(--surface-muted); + border: 1px solid var(--border-color); + border-radius: 6px; + color: var(--text-color); + font-size: 0.9rem; + outline: none; +} + +.fm-rename-row input:focus { + border-color: var(--border-color-focus); +} + +.fm-rename-ext { + color: var(--text-color-muted); + font-size: 0.9rem; + white-space: nowrap; +} + +.fm-rename-error { + margin-top: 8px; + color: var(--error-color); + font-size: 0.82rem; +} + +/* Destructive variant of the shared primary button (delete / reboot). */ +.primary-btn.danger { + background-color: var(--error-color); + border-color: var(--error-color); + color: var(--text-on-primary); +} + +.primary-btn.danger:hover:not(:disabled) { + background-color: color-mix(in srgb, var(--error-color) 85%, black); +} + +/* ============================================================================ + SSH SETTINGS SECTION (settings modal) + ============================================================================ */ + +.ssh-settings-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 12px; + margin: 12px 0; +} + +.ssh-settings-grid label { + display: flex; + flex-direction: column; + gap: 6px; + font-size: 0.88rem; + color: var(--text-color-secondary); +} + +.ssh-settings-grid input { + padding: 8px 10px; + background: var(--surface-muted); + border: 1px solid var(--border-color); + border-radius: 6px; + color: var(--text-color); + font-size: 0.9rem; + outline: none; +} + +.ssh-settings-grid input:focus { + border-color: var(--border-color-focus); +} + +/* ============================================================================ + REBOOT OVERLAY + ============================================================================ */ + +.reboot-overlay { + position: fixed; + inset: 0; + background: var(--overlay-bg); + display: flex; + align-items: center; + justify-content: center; + z-index: 1200; +} + +.reboot-overlay-panel { + background: var(--theme-surface); + border: 1px solid var(--border-color); + border-radius: 12px; + box-shadow: var(--shadow-lg); + width: min(420px, calc(100% - 48px)); + padding: 28px 24px; + display: flex; + flex-direction: column; + align-items: center; + gap: 14px; + text-align: center; +} + +.reboot-overlay-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--text-color); +} + +.reboot-overlay-message { + font-size: 0.9rem; + color: var(--text-color-secondary); + line-height: 1.5; + min-height: 1.4em; +} + +.reboot-result-icon.lucide-icon, +.reboot-result-icon { + width: 40px; + height: 40px; +} + +.reboot-result-icon.success { + color: var(--success-color); +} + +.reboot-result-icon.error { + color: var(--error-color); +} + +.reboot-overlay-actions { + display: flex; + gap: 10px; + justify-content: center; +} + + +/* ============================================================================ + CALIBRATION ASSISTANT + ============================================================================ */ + +.cal-modal-content { + position: relative; + display: flex; + flex-direction: column; + width: min(1100px, 96vw); + max-width: min(1100px, 96vw); + height: min(820px, 94vh); + max-height: 94vh; +} + +.cal-modal-body { + display: flex; + flex-direction: column; + flex: 1; + gap: 12px; + overflow: hidden; +} + +/* Header indicators */ +.cal-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 12px; + background-color: var(--surface-muted); + border-radius: 8px; + flex-shrink: 0; +} + +.cal-context-indicator { + font-size: 14px; + color: var(--text-color-secondary); +} + +.cal-ssh-indicator { + display: flex; + align-items: center; + gap: 8px; + font-size: 13px; + color: var(--text-color-secondary); +} + +.cal-ssh-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background-color: var(--error-color); +} + +.cal-ssh-dot.connected { + background-color: var(--success-color); +} + +/* Tabs */ +.cal-tabs { + display: flex; + gap: 4px; + background-color: var(--surface-muted); + padding: 4px; + border-radius: 8px; + flex-shrink: 0; +} + +.cal-tab-button { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 14px; + background: transparent; + border: none; + border-radius: 6px; + color: var(--text-color-secondary); + font-size: 13px; + font-weight: 500; + cursor: pointer; + transition: background-color var(--transition-fast), color var(--transition-fast); +} + +.cal-tab-button svg { + width: 16px; + height: 16px; +} + +.cal-tab-button:hover { + background-color: var(--card-bg-hover); + color: var(--text-color); +} + +.cal-tab-button[aria-selected="true"] { + background-color: var(--theme-primary); + color: var(--text-on-primary); +} + +/* Panels */ +.cal-tab-panels { + flex: 1; + overflow: hidden; +} + +.cal-tab-panel { + height: 100%; + overflow: auto; +} + +.cal-tab-panel[hidden] { + display: none; +} + +.cal-panel-layout { + display: grid; + grid-template-columns: 1fr 300px; + gap: 12px; + min-height: 100%; +} + +.cal-panel-main { + display: flex; + flex-direction: column; + gap: 12px; + min-width: 0; +} + +.cal-panel-sidebar { + display: flex; + flex-direction: column; + gap: 16px; + background-color: var(--surface-muted); + border-radius: 8px; + padding: 14px; + overflow-y: auto; +} + +@media (max-width: 900px) { + .cal-panel-layout { + grid-template-columns: 1fr; + } +} + +/* Mesh + shaper visualization containers */ +.cal-mesh-container, +.cal-shaper-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background-color: var(--surface-muted); + border-radius: 8px; + padding: 14px; +} + +#cal-mesh-canvas, +#cal-shaper-canvas { + max-width: 100%; + height: auto; + border-radius: 4px; +} + +.cal-mesh-stats { + display: flex; + gap: 24px; + margin-top: 12px; + padding: 8px 16px; + background-color: var(--card-bg); + border-radius: 6px; +} + +.cal-stat-item { + display: flex; + flex-direction: column; + align-items: center; +} + +.cal-stat-label { + font-size: 11px; + color: var(--text-color-secondary); + text-transform: uppercase; +} + +.cal-stat-value { + font-size: 15px; + font-weight: 600; + color: var(--text-color); + font-family: monospace; +} + +.cal-controls-row { + display: flex; + gap: 10px; + align-items: center; + flex-wrap: wrap; +} + +.cal-profile-select, +.cal-export-select { + padding: 8px 12px; + background-color: var(--card-bg); + border: 1px solid var(--border-color); + border-radius: 6px; + color: var(--text-color); + font-size: 13px; +} + +.cal-profile-select { + flex: 1; + max-width: 220px; +} + +.cal-profile-select:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +/* Buttons */ +.cal-control-button { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 9px 14px; + background-color: var(--card-bg); + border: 1px solid var(--border-color); + border-radius: 6px; + color: var(--text-color); + font-size: 13px; + font-weight: 500; + cursor: pointer; + transition: background-color var(--transition-fast), border-color var(--transition-fast); +} + +.cal-control-button svg { + width: 16px; + height: 16px; +} + +.cal-control-button:hover:not(:disabled) { + background-color: var(--card-bg-hover); +} + +.cal-control-button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.cal-control-button.primary { + background-color: var(--theme-primary); + border-color: var(--theme-primary); + color: var(--text-on-primary); +} + +.cal-control-button.primary:hover:not(:disabled) { + background-color: var(--theme-primary-hover); +} + +.cal-control-button.danger { + background-color: var(--error-color); + border-color: var(--error-color); + color: var(--text-on-primary); +} + +.cal-control-button.danger:hover:not(:disabled) { + filter: brightness(0.9); +} + +/* Section titles */ +.cal-section-title { + font-size: 14px; + font-weight: 600; + color: var(--text-color); + margin: 0 0 12px 0; +} + +.cal-subsection-title { + font-size: 13px; + font-weight: 500; + color: var(--text-color-secondary); + margin: 0 0 8px 0; +} + +/* Workflow stages */ +.cal-workflow-section { + padding-bottom: 16px; + border-bottom: 1px solid var(--border-color); +} + +.cal-workflow-stages { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 14px; +} + +.cal-workflow-stage { + display: flex; + align-items: center; + gap: 10px; + padding: 9px 12px; + background-color: var(--card-bg); + border: 1px solid transparent; + border-radius: 6px; + transition: background-color var(--transition-fast); +} + +.cal-workflow-stage.active { + background-color: var(--primary-alpha-20); + border-color: var(--theme-primary); +} + +.cal-workflow-stage.completed .cal-stage-icon svg { + stroke: var(--success-color); +} + +.cal-stage-icon svg { + width: 16px; + height: 16px; + stroke: var(--text-color-secondary); +} + +.cal-stage-label { + font-size: 13px; + color: var(--text-color); +} + +/* Results */ +.cal-results-section[hidden] { + display: none; +} + +.cal-adjustments-container { + margin-bottom: 14px; +} + +.cal-adjustments-list { + display: flex; + flex-direction: column; + gap: 8px; +} + +.cal-adjustment-item { + display: flex; + justify-content: space-between; + align-items: center; + gap: 8px; + padding: 9px 12px; + background-color: var(--card-bg); + border-radius: 6px; + font-size: 13px; +} + +.cal-adjustment-corner { + font-weight: 500; + color: var(--text-color); +} + +.cal-adjustment-value { + font-family: monospace; + color: var(--theme-primary); +} + +.cal-adjustment-value.cw { + color: var(--success-color); +} + +.cal-adjustment-value.ccw { + color: var(--warning-color); +} + +.cal-improvement-display { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 12px; + background-color: color-mix(in srgb, var(--success-color) 10%, transparent); + border: 1px solid var(--success-color); + border-radius: 8px; + margin: 14px 0; +} + +.cal-improvement-label { + font-size: 14px; + color: var(--text-color); +} + +.cal-improvement-value { + font-size: 22px; + font-weight: 700; + color: var(--success-color); +} + +/* Input shaper sidebar */ +.cal-axis-selector { + display: flex; + gap: 8px; + margin-top: 12px; +} + +.cal-axis-button { + padding: 8px 24px; + background-color: var(--card-bg); + border: 1px solid var(--border-color); + border-radius: 6px; + color: var(--text-color-secondary); + font-size: 13px; + font-weight: 500; + cursor: pointer; + transition: background-color var(--transition-fast), color var(--transition-fast); +} + +.cal-axis-button.active { + background-color: var(--theme-primary); + border-color: var(--theme-primary); + color: var(--text-on-primary); +} + +.cal-axis-button:hover:not(.active) { + background-color: var(--card-bg-hover); + color: var(--text-color); +} + +.cal-shaper-results-section, +.cal-shaper-comparison-section { + padding-bottom: 14px; + border-bottom: 1px solid var(--border-color); +} + +.cal-shaper-recommendation { + padding: 12px; + background-color: var(--card-bg); + border-radius: 8px; +} + +.cal-shaper-details { + margin-top: 10px; + font-size: 12px; + color: var(--text-color-secondary); + display: grid; + gap: 4px; +} + +.cal-empty-state { + color: var(--text-color-secondary); + font-size: 13px; + text-align: center; + padding: 20px; +} + +.cal-shaper-comparison { + display: flex; + flex-direction: column; + gap: 8px; +} + +.cal-shaper-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 9px 12px; + background-color: var(--card-bg); + border: 1px solid transparent; + border-radius: 6px; +} + +.cal-shaper-item.recommended { + border-color: var(--success-color); +} + +.cal-shaper-name { + font-size: 13px; + font-weight: 500; + color: var(--text-color); +} + +.cal-shaper-freq { + font-size: 12px; + font-family: monospace; + color: var(--text-color-secondary); +} + +.cal-shaper-config-output { + margin-top: 8px; + padding: 12px; + background-color: var(--darker-bg); + border: 1px solid var(--border-color); + border-radius: 6px; + font-size: 12px; + color: var(--text-color); + white-space: pre-wrap; + word-break: break-word; + min-height: 100px; +} + +.cal-shaper-config-actions { + display: flex; + gap: 8px; + margin-top: 10px; + flex-wrap: wrap; +} + +/* SSH tab */ +.cal-ssh-panel { + max-width: 620px; + padding: 4px; +} + +.cal-info-text { + font-size: 13px; + color: var(--text-color-secondary); + line-height: 1.5; + margin-bottom: 12px; +} + +.cal-ssh-fields { + margin-top: 14px; + padding: 14px; + background-color: var(--surface-muted); + border-radius: 8px; +} + +.cal-input-group { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: 12px; +} + +.cal-input-group:last-child { + margin-bottom: 0; +} + +.cal-input-group label { + font-size: 13px; + font-weight: 500; + color: var(--text-color); +} + +.cal-input { + padding: 9px 12px; + background-color: var(--card-bg); + border: 1px solid var(--border-color); + border-radius: 6px; + color: var(--text-color); + font-size: 13px; + transition: border-color var(--transition-fast); +} + +.cal-input:focus { + outline: none; + border-color: var(--border-color-focus); +} + +.cal-ssh-buttons { + display: flex; + gap: 10px; + margin-top: 14px; + flex-wrap: wrap; +} + +.cal-ssh-test-result { + margin-top: 12px; + padding: 10px 12px; + border-radius: 6px; + font-size: 13px; + min-height: 20px; + color: var(--text-color-secondary); +} + +.cal-ssh-test-result.success { + background-color: color-mix(in srgb, var(--success-color) 10%, transparent); + color: var(--success-color); +} + +.cal-ssh-test-result.error { + background-color: color-mix(in srgb, var(--error-color) 10%, transparent); + color: var(--error-color); +} + +/* History tab */ +.cal-history-panel { + padding: 4px; +} + +.cal-history-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 14px; +} + +.cal-history-header .cal-section-title { + margin-bottom: 0; +} + +.cal-history-list { + display: flex; + flex-direction: column; + gap: 10px; +} + +.cal-history-item { + display: flex; + justify-content: space-between; + align-items: flex-start; + padding: 14px; + background-color: var(--surface-muted); + border-radius: 8px; +} + +.cal-history-item-main { + display: flex; + flex-direction: column; + gap: 4px; +} + +.cal-history-item-type { + font-size: 14px; + font-weight: 600; + color: var(--text-color); +} + +.cal-history-item-summary { + font-size: 13px; + color: var(--text-color-secondary); +} + +.cal-history-item-date { + font-size: 12px; + color: var(--text-color-muted); +} + +/* Footer */ +.cal-footer { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.cal-status-message { + flex: 1; + min-width: 0; + font-size: 13px; + color: var(--text-color-secondary); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.cal-footer-actions { + display: flex; + align-items: center; + gap: 10px; +} + +.cal-footer-actions .secondary-btn { + display: inline-flex; + align-items: center; + gap: 6px; +} + +.cal-footer-actions .lucide-icon { + width: 16px; + height: 16px; + flex-shrink: 0; +} + +.cal-export-format { + display: flex; + align-items: center; + gap: 8px; + font-size: 12px; + color: var(--text-color-secondary); + text-transform: uppercase; + letter-spacing: 0.04em; +} + +/* Visual recommendations overlay (nested inside the modal content) */ +.cal-overlay { + position: absolute; + inset: 0; + background-color: var(--overlay-bg); + display: flex; + align-items: center; + justify-content: center; + border-radius: 12px; + z-index: 10; +} + +.cal-overlay.hidden { + display: none; +} + +.cal-overlay-panel { + width: min(92%, 720px); + max-height: 92%; + overflow: auto; + background-color: var(--card-bg); + border: 1px solid var(--border-color); + border-radius: 12px; + box-shadow: var(--shadow-lg); +} + +.cal-overlay-title { + display: flex; + align-items: center; + gap: 8px; + padding: 12px 16px; + background-color: var(--surface-muted); + font-weight: 600; + color: var(--text-color); +} + +.cal-overlay-title svg { + width: 18px; + height: 18px; + color: var(--theme-primary); +} + +.cal-overlay-title .close-btn { + margin-left: auto; +} + +.cal-overlay-body { + padding: 16px; + display: flex; + flex-direction: column; + gap: 12px; +} + +#cal-rec-canvas { + width: 100%; + height: auto; + border-radius: 8px; +} + +.cal-rec-legend { + display: flex; + gap: 16px; + flex-wrap: wrap; + font-size: 12px; + color: var(--text-color-secondary); +} + +.cal-legend-item { + display: flex; + align-items: center; + gap: 6px; +} + +.cal-legend-swatch { + width: 12px; + height: 12px; + border-radius: 3px; +} + +.cal-legend-swatch.cw { + background-color: var(--success-color); +} + +.cal-legend-swatch.ccw { + background-color: var(--warning-color); +} + +.cal-legend-swatch.tape { + background-color: var(--theme-secondary); +} + diff --git a/src/shared/types/printer-power.ts b/src/shared/types/printer-power.ts index fb94c71..ac669b4 100644 --- a/src/shared/types/printer-power.ts +++ b/src/shared/types/printer-power.ts @@ -2,8 +2,8 @@ * @fileoverview Shared IPC types for the remote "Reboot Printer" feature. * * Consumed by the main-process handler (`printer-power-handlers.ts`), the - * preload bridge, and the renderer's reboot overlay controller. Desktop only — - * WebUI parity is deferred. + * preload bridge, the renderer's reboot overlay controller, and the WebUI + * (REBOOT_STATUS WebSocket broadcasts + the printer-power route). * * Key exports: * - RebootPhase: lifecycle phase pushed over the 'printer:reboot-status' channel. diff --git a/src/shared/types/web-api.types.ts b/src/shared/types/web-api.types.ts index 0118e01..26d9802 100644 --- a/src/shared/types/web-api.types.ts +++ b/src/shared/types/web-api.types.ts @@ -12,6 +12,8 @@ * payloads, and related transport shapes used by both the WebUI server and static client. */ +import type { RebootStatusPayload } from './printer-power.js'; + // ============================================================================ // AUTHENTICATION TYPES // ============================================================================ @@ -55,7 +57,7 @@ export interface ActiveSpoolData { * WebSocket message types for real-time communication */ export interface WebSocketMessage { - type: 'AUTH_SUCCESS' | 'STATUS_UPDATE' | 'ERROR' | 'COMMAND_RESULT' | 'PONG' | 'SPOOLMAN_UPDATE'; + type: 'AUTH_SUCCESS' | 'STATUS_UPDATE' | 'ERROR' | 'COMMAND_RESULT' | 'PONG' | 'SPOOLMAN_UPDATE' | 'REBOOT_STATUS'; timestamp: string; status?: PrinterStatusData | null; error?: string; @@ -64,6 +66,7 @@ export interface WebSocketMessage { success?: boolean; contextId?: string; spool?: ActiveSpoolData | null; + reboot?: RebootStatusPayload; } /** From 7aea273c9f4c3707991a38645547d3abf18a3a57 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Thu, 23 Jul 2026 19:25:08 -0400 Subject: [PATCH 39/93] fix(linux): make start-at-boot, start-minimized, and package sandboxing work (#75) --- .gitattributes | 5 + CHANGELOG.md | 27 +++ README.md | 13 +- assets/linux/afterInstall.sh | 97 ++++++++--- assets/linux/afterRemove.sh | 42 +++-- assets/linux/apparmor-profile | 31 ++++ docs/README.md | 78 ++++++++- electron-builder-config.cjs | 11 ++ scripts/linux/after-pack.cjs | 115 +++++++++++++ src/main/index.ts | 48 +++++- src/main/services/AutoLaunchService.ts | 66 +++++-- src/main/services/TrayService.ts | 162 ++++++++++++++++++ .../__tests__/AutoLaunchService.test.ts | 92 +++++++++- 13 files changed, 714 insertions(+), 73 deletions(-) create mode 100644 .gitattributes create mode 100644 assets/linux/apparmor-profile create mode 100644 scripts/linux/after-pack.cjs create mode 100644 src/main/services/TrayService.ts diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d9d1a09 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# Shell scripts and Linux packaging data must keep LF endings regardless of the checkout platform. +# With core.autocrlf=true on Windows these files would otherwise be checked out with CRLF, and a +# packaged postinst starting with `#!/bin/bash\r` fails on Linux with "bad interpreter". +*.sh text eol=lf +assets/linux/apparmor-profile text eol=lf diff --git a/CHANGELOG.md b/CHANGELOG.md index b23279d..62d5d43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Reboot - New **Reboot** action in the hamburger menu for the Adventurer 5M / 5M Pro / AD5X, performed over SSH. A full-screen overlay tracks the whole lifecycle (rebooting -> waiting -> reconnecting services -> back online) and proactively restarts the camera stream, so the printer reconnects seamlessly without leaving the tab in an error state. +### WebUI +- The full SSH toolset now works in the browser: the file manager, the calibration assistant, SSH settings editing, and remote reboot match what the desktop app can do. Passwords are write-only — they can be changed but never read back from the browser. +- Reboot progress now broadcasts over the WebUI socket, so a reboot started from the desktop app shows its lifecycle in any open browser session (and vice versa). +- Fixed the calibration dialog being too narrow and its export button rendering comically large. +- Fixed see-through popup backgrounds caused by a broken style definition. +- Updated the slicer file reader to its latest version. + +### Diagnostics & Updates +- Debug mode now captures all main-process console output (plus renderer log-panel messages) to a new `console-.log`, alongside the targeted `debug-*.log` instrumentation channel. Console logs are also exposed through the WebUI debug routes (list / download / latest). +- `electron-log` is now mocked globally in Jest, so tests no longer pollute the real `main.log`. +- The release workflow now uploads `.exe.blockmap` assets so differential updates work (retrofitted for v1.0.4 and v1.0.5-alpha.8 manually). +- `UpdateChannel` now defaults to match the installed build (alpha installs track the alpha channel) unless explicitly chosen, and `disableWebInstaller` is set to silence the electron-updater warning. + +### Start at Boot +- Refactored the Linux "start with system" implementation (follow-up to the #75 boot feature). Electron's native login-item API is Windows/macOS only, so Linux now gets a proper freedesktop autostart entry in `~/.config/autostart/`, resolved against the stable AppImage path rather than its temporary mount point. The entry also carries `TryExec` and `Icon`, and escapes literal `%` correctly. +- Fixed "start minimized" doing nothing visible on Linux. The window was being minimized before it had ever been mapped, which leaves no taskbar button at all; it is now shown first and minimized once ready. +- "Start minimized" now applies only to sessions the system auto-launched. Launching the app yourself always shows the window — previously the setting also hid manual launches, which looked like the app failing to start. +- Added a system tray icon (Show / Quit) as a reliable way back to the window, since some desktop environments — Wayland sessions in particular — ignore requests from an app to minimize itself. + +### Linux Packaging +- Fixed the `.deb` and `.rpm` packages not installing an AppArmor profile. Ubuntu 23.10+ blocks unprivileged user namespaces, and without the profile Chromium has no usable sandbox and the app does not start at all on Ubuntu 24.04+. The custom post-install script had been silently replacing electron-builder's own template, which also dropped the `chrome-sandbox` permission handling. +- The AppImage now detects when it has no usable sandbox and falls back to `--no-sandbox` so it still launches on Ubuntu 24.04+. The `.deb`/`.rpm` packages are unaffected and remain fully sandboxed; on Ubuntu 24.04+ they are the recommended download. +- Documented Linux autostart behavior, the sandbox situation, and headless start-at-boot via a systemd user unit in the user guide. + +### Dependencies +- Patched all eight open Dependabot security advisories (#190–#199): bumped `js-yaml` and `tar`, and added overrides for `shell-quote` (critical), `form-data`, and `esbuild`; bumped `vite`, `tsx`, and `@babel/core`. No application source changes. + ## [1.0.5-alpha.8] - 2026-07-05 ### WebUI diff --git a/README.md b/README.md index 2cec983..5fb874f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ![Platforms](https://img.shields.io/badge/Platforms-Win%20%7C%20macOS%20%7C%20Linux-3178c6?style=flat) ![Downloads](https://img.shields.io/github/downloads/Parallel-7/FlashForgeUI-Electron/total?style=flat&color=brightgreen) -![Version](https://img.shields.io/badge/Version-1.0.4--alpha.4-orange?style=flat) +![Version](https://img.shields.io/github/v/release/Parallel-7/FlashForgeUI-Electron?include_prereleases&style=flat&color=orange&label=Version) ![License](https://img.shields.io/badge/License-MIT-blue?style=flat) **Monitor and control your printer from your desktop or any device on your network — with more features than any official FlashForge software, completely free.** @@ -29,8 +29,6 @@ FlashForgeUI connects directly to your FlashForge printer over your local network — no cloud account required. Watch live camera and temperature data, start and manage prints, control LEDs and filtration, and keep an eye on multiple printers at once. When you're away from your desk, the built-in WebUI gives you the same control from your phone or any browser, and headless mode lets you run it as a lightweight always-on server. -It works with everything from the latest Adventurer 5M / 5M Pro / AD5X to older legacy models, automatically picking the right way to talk to each printer. -
## How It Compares @@ -65,6 +63,9 @@ It works with everything from the latest Adventurer 5M / 5M Pro / AD5X to older | **[Spoolman Integration](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Spoolman-Integration)** | Track filament usage automatically and assign spools per printer | | **[Notifications](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Notifications)** | Desktop and Discord alerts for print completion, cooldown, and more | | **Hardware Controls** | Temperature, LED, and filtration control • axis homing • clear platform • direct command terminal | +| **Printer File Manager** | Browse, rename, and delete files stored on the printer and on USB, with thumbnail previews — desktop and WebUI • 5M / 5M Pro / AD5X, requires SSH access via [FlashForge-EasySSH](https://github.com/Parallel-7/FlashForge-EasySSH) | +| **Calibration Assistant** | Read and analyze on-printer calibration data to help diagnose print quality — same models and SSH requirement as the file manager | +| **Start with System** | Optionally launch at login on Windows, macOS, and Linux — start minimized to the tray and let prints run unattended | | **[Customizable UI](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Customizing-the-Desktop-UI)** | Drag-and-drop layouts, light/dark themes, and custom color palettes on both desktop and WebUI |
@@ -75,6 +76,8 @@ It works with everything from the latest Adventurer 5M / 5M Pro / AD5X to older | Printer | Support | Material Station | Notes | | --- | --- | --- | --- | +| **Creator 5 Pro** | Full | Yes (4 slots) | HTTP-only API | +| **Creator 5** | Full | Yes (4 slots) | HTTP-only API | | **AD5X** | Full | Yes (4 slots) | Multi-material 3MF printing | | **Adventurer 5M Pro** | Full | No | Includes filtration control | | **Adventurer 5M** | Full | No | | @@ -92,7 +95,7 @@ It works with everything from the latest Adventurer 5M / 5M Pro / AD5X to older | Step | Instructions | | --- | --- | | **1. Download** | Grab the [latest release](https://github.com/Parallel-7/FlashForgeUI-Electron/releases/latest) for your platform | -| **2. Install** | **Windows:** run the `.exe` installer
**macOS:** open the `.dmg` and drag to Applications
**Linux:** use the `.AppImage`, `.deb`, or `.rpm` package | +| **2. Install** | **Windows:** run the `.exe` installer
**macOS:** open the `.dmg` and drag to Applications
**Linux:** install the `.deb` or `.rpm`, or run the `.AppImage` directly — on Ubuntu 24.04+ prefer the `.deb`, see [Linux Notes](docs/README.md#linux-notes) | | **3. Connect** | Launch the app, use auto-discovery or enter your printer's IP, and add the [pairing code](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/1.-Pairing-your-printer) if prompted | | **4. Configure** | Optional: set up [remote access](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/WebUI-Setup), [Discord alerts](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Notifications), [Spoolman](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Spoolman-Integration), and [custom cameras](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Custom-Camera-Setup) | @@ -121,7 +124,7 @@ pnpm build:linux # package Linux artifacts ![Electron](https://img.shields.io/badge/Electron-39.8.10-47848f?style=flat&logo=electron) ![TypeScript](https://img.shields.io/badge/TypeScript-5.9.3-3178c6?style=flat&logo=typescript) -![Vite](https://img.shields.io/badge/Vite-7.3.2-646cff?style=flat&logo=vite) +![Vite](https://img.shields.io/badge/Vite-7.3.6-646cff?style=flat&logo=vite) ![Express](https://img.shields.io/badge/Express-5.2.1-000000?style=flat&logo=express) ## License diff --git a/assets/linux/afterInstall.sh b/assets/linux/afterInstall.sh index 70c849e..401391b 100644 --- a/assets/linux/afterInstall.sh +++ b/assets/linux/afterInstall.sh @@ -1,42 +1,85 @@ #!/bin/bash -# Post-installation script for FlashForgeUI -# This script runs after the package is installed - -# Set proper permissions for the application -chmod +x /opt/FlashForgeUI/FlashForgeUI || true - -# Create desktop entry if it doesn't exist -if [ ! -f /usr/share/applications/FlashForgeUI.desktop ]; then - cat > /usr/share/applications/FlashForgeUI.desktop << EOF -[Desktop Entry] -Name=FlashForgeUI -Comment=Monitoring and Control software for FlashForge printers -Exec=/opt/FlashForgeUI/FlashForgeUI -Icon=FlashForgeUI -Type=Application -Categories=Utility; -StartupNotify=true -EOF -fi - -# Update desktop database -if command -v update-desktop-database >/dev/null 2>&1; then +# Post-installation script for FlashForgeUI (deb / rpm). +# +# IMPORTANT: supplying this file via `deb.afterInstall` / `rpm.afterInstall` REPLACES +# electron-builder's own after-install template wholesale - it is not merged. Everything upstream +# does must therefore be reproduced here, or it silently stops happening. This script is a copy of +# app-builder-lib/templates/linux/after-install.tpl with the FlashForgeUI-specific legacy cleanup +# appended at the end. When bumping electron-builder, diff that template against this file. +# +# The two upstream behaviors that matter most, and that a previous hand-written version of this +# script dropped: +# 1. Installing the AppArmor profile. Ubuntu 23.10+ ships +# kernel.apparmor_restrict_unprivileged_userns=1, which blocks unprivileged user namespaces +# and therefore Chromium's namespace sandbox. Without a profile granting `userns`, the app +# does not start at all on Ubuntu 24.04+. +# 2. Setting the SUID bit on chrome-sandbox when the kernel has no working user namespaces +# (e.g. Debian defaults), so Chromium can fall back to the SUID sandbox. + +if type update-alternatives >/dev/null 2>&1; then + # Remove previous link if it doesn't use update-alternatives + if [ -L '/usr/bin/FlashForgeUI' ] && [ -e '/usr/bin/FlashForgeUI' ] && [ "$(readlink '/usr/bin/FlashForgeUI')" != '/etc/alternatives/FlashForgeUI' ]; then + rm -f '/usr/bin/FlashForgeUI' + fi + update-alternatives --install '/usr/bin/FlashForgeUI' 'FlashForgeUI' '/opt/FlashForgeUI/FlashForgeUI' 100 || ln -sf '/opt/FlashForgeUI/FlashForgeUI' '/usr/bin/FlashForgeUI' +else + ln -sf '/opt/FlashForgeUI/FlashForgeUI' '/usr/bin/FlashForgeUI' +fi + +# Check if user namespaces are supported by the kernel and working with a quick test: +if ! { [ -L /proc/self/ns/user ] && unshare --user true; }; then + # Use SUID chrome-sandbox only on systems without user namespaces: + chmod 4755 '/opt/FlashForgeUI/chrome-sandbox' || true +else + chmod 0755 '/opt/FlashForgeUI/chrome-sandbox' || true +fi + +if hash update-mime-database 2>/dev/null; then + update-mime-database /usr/share/mime || true +fi + +if hash update-desktop-database 2>/dev/null; then update-desktop-database /usr/share/applications || true fi -# Create symlink in /usr/local/bin for CLI access (optional) -if [ ! -f /usr/local/bin/FlashForgeUI ]; then - ln -sf /opt/FlashForgeUI/FlashForgeUI /usr/local/bin/FlashForgeUI || true +# Install apparmor profile. (Ubuntu 24+) +# First check if the version of AppArmor running on the device supports our profile. +# This is in order to keep backwards compatibility with Ubuntu 22.04 which does not support abi/4.0. +# In that case, we just skip installing the profile since the app runs fine without it on 22.04. +# +# Those apparmor_parser flags are akin to performing a dry run of loading a profile. +# https://wiki.debian.org/AppArmor/HowToUse#Dumping_profiles +if apparmor_status --enabled > /dev/null 2>&1; then + APPARMOR_PROFILE_SOURCE='/opt/FlashForgeUI/resources/apparmor-profile' + APPARMOR_PROFILE_TARGET='/etc/apparmor.d/FlashForgeUI' + if apparmor_parser --skip-kernel-load --debug "$APPARMOR_PROFILE_SOURCE" > /dev/null 2>&1; then + cp -f "$APPARMOR_PROFILE_SOURCE" "$APPARMOR_PROFILE_TARGET" + + # Updating the current AppArmor profile is not possible and probably not meaningful in a + # chroot'ed environment (e.g. image builders for client machines). + if ! { [ -x '/usr/bin/ischroot' ] && /usr/bin/ischroot; } && hash apparmor_parser 2>/dev/null; then + # Extra flags taken from dh_apparmor: by using '-W -T' we ensure that any abstraction + # updates are also pulled in. + apparmor_parser --replace --write-cache --skip-read-cache "$APPARMOR_PROFILE_TARGET" + fi + else + echo "Skipping the installation of the AppArmor profile as this version of AppArmor does not seem to support the bundled profile" + fi fi -# Clean up old flashforge-ui-ts entries from previous installations +# --- FlashForgeUI-specific: clean up artifacts of the pre-rename flashforge-ui-ts packages --- + if [ -f /usr/share/applications/flashforge-ui-ts.desktop ]; then rm -f /usr/share/applications/flashforge-ui-ts.desktop || true fi if [ -L /usr/local/bin/flashforge-ui-ts ]; then rm -f /usr/local/bin/flashforge-ui-ts || true fi +# Older FlashForgeUI packages symlinked into /usr/local/bin; /usr/bin (handled above via +# update-alternatives) is the correct location, so drop the stale duplicate. +if [ -L /usr/local/bin/FlashForgeUI ]; then + rm -f /usr/local/bin/FlashForgeUI || true +fi exit 0 - \ No newline at end of file diff --git a/assets/linux/afterRemove.sh b/assets/linux/afterRemove.sh index 2f628d5..2b4662e 100644 --- a/assets/linux/afterRemove.sh +++ b/assets/linux/afterRemove.sh @@ -1,22 +1,31 @@ #!/bin/bash -# Post-removal script for FlashForgeUI -# This script runs after the package is removed +# Post-removal script for FlashForgeUI (deb / rpm). +# +# As with afterInstall.sh, supplying this file REPLACES electron-builder's after-remove template +# rather than extending it - so the upstream body is reproduced here verbatim, with the +# FlashForgeUI-specific legacy cleanup appended. Diff against +# app-builder-lib/templates/linux/after-remove.tpl when bumping electron-builder. -# Remove desktop entries (both old and new) -if [ -f /usr/share/applications/flashforge-ui-ts.desktop ]; then - rm -f /usr/share/applications/flashforge-ui-ts.desktop || true -fi -if [ -f /usr/share/applications/FlashForgeUI.desktop ]; then - rm -f /usr/share/applications/FlashForgeUI.desktop || true +# Delete the link to the binary +if type update-alternatives >/dev/null 2>&1; then + update-alternatives --remove 'FlashForgeUI' '/usr/bin/FlashForgeUI' +else + rm -f '/usr/bin/FlashForgeUI' fi -# Update desktop database -if command -v update-desktop-database >/dev/null 2>&1; then - update-desktop-database /usr/share/applications || true +APPARMOR_PROFILE_DEST='/etc/apparmor.d/FlashForgeUI' + +# Remove apparmor profile. +if [ -f "$APPARMOR_PROFILE_DEST" ]; then + rm -f "$APPARMOR_PROFILE_DEST" fi -# Remove symlinks from /usr/local/bin (both old and new) +# --- FlashForgeUI-specific: clean up artifacts of the pre-rename flashforge-ui-ts packages --- + +if [ -f /usr/share/applications/flashforge-ui-ts.desktop ]; then + rm -f /usr/share/applications/flashforge-ui-ts.desktop || true +fi if [ -L /usr/local/bin/flashforge-ui-ts ]; then rm -f /usr/local/bin/flashforge-ui-ts || true fi @@ -24,11 +33,8 @@ if [ -L /usr/local/bin/FlashForgeUI ]; then rm -f /usr/local/bin/FlashForgeUI || true fi -# Remove any leftover configuration files (optional) -# Note: We typically don't remove user data/config files in afterRemove -# but you can uncomment the lines below if needed -# rm -rf /home/*/.config/FlashForgeUI || true -# rm -rf /root/.config/FlashForgeUI || true +if command -v update-desktop-database >/dev/null 2>&1; then + update-desktop-database /usr/share/applications || true +fi exit 0 - \ No newline at end of file diff --git a/assets/linux/apparmor-profile b/assets/linux/apparmor-profile new file mode 100644 index 0000000..19e7b57 --- /dev/null +++ b/assets/linux/apparmor-profile @@ -0,0 +1,31 @@ +abi , +include + +# AppArmor profile for FlashForgeUI (deb / rpm installs). +# +# Ubuntu 23.10+ ships kernel.apparmor_restrict_unprivileged_userns=1, which forbids unprivileged +# processes from creating user namespaces. Chromium needs them for its namespace sandbox, so +# without a profile granting `userns` the app aborts during startup and never draws a window. +# See https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2046844. +# +# flags=(unconfined) means this profile does not actually confine the application - it exists +# solely to carry the `userns` grant, which is the pattern the AppArmor maintainers recommend for +# application packages. +# +# The attachment uses brace expansion to cover both entry points, because the Linux build wraps +# the Electron binary in a small launcher script (see scripts/linux/after-pack.cjs): +# /opt/FlashForgeUI/FlashForgeUI - the launcher script +# /opt/FlashForgeUI/FlashForgeUI.bin - the real Electron binary the launcher execs +# Covering the .bin path is the part that matters: that is the process which actually creates the +# user namespace, and it must match a profile granting `userns` regardless of how the interpreted +# launcher script resolves its own attachment. +# +# This file overrides app-builder-lib/templates/linux/apparmor-profile.tpl, whose attachment only +# covers the unwrapped binary path. + +profile "FlashForgeUI" "/opt/FlashForgeUI/FlashForgeUI{,.bin}" flags=(unconfined) { + userns, + + # Site-specific additions and overrides. See local/README for details. + include if exists +} diff --git a/docs/README.md b/docs/README.md index 00b363e..4012ce7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -34,7 +34,19 @@ For MacOS, the command structure starts with open "/Applications/FlashForgeUI.app/Contents/MacOS/FlashForgeUI" ``` -For Linux, (coming soon...) +For Linux, the command depends on which package you installed. + +Installed from the `.deb` or `.rpm` — the installer puts `FlashForgeUI` on your `PATH`: +```bash +FlashForgeUI --headless +``` + +Running the AppImage — call it by path (make it executable once with `chmod +x` if you have not already): +```bash +./FlashForgeUI-*.AppImage --headless +``` + +Both accept the same flags as the Windows examples below. ## Starting Headless Mode @@ -190,3 +202,67 @@ When using `--all-saved-printers` or specifying multiple printers with `--printe - The file has been sliced with OrcaSlicer and lacks the correct (and correct ordering of) metadata. FlashForge printers only "broadcast" this information to the API for files sliced by Orca-FlashForge. Both slicers include the information, but in different formats, and FlashForge printers only look for/accept the format from Orca-FlashForge. - Please download and set up [this](https://github.com/GhostTypes/orca2flashforge) post-process script - If you already have a script for MD5 generation, remove it and add `-m` to the end of this. It will generate both the MD5 hash and the corrected metadata. + +## Linux Notes + +### Start with system / Start minimized + +"Start with system" writes a standard freedesktop autostart entry to `~/.config/autostart/flashforgeui.desktop` (or `$XDG_CONFIG_HOME/autostart/` if you set that variable). Every major desktop environment honors it - GNOME, KDE, XFCE, Cinnamon, MATE - so it works the same on any distro. Turning the setting off deletes the file. + +"Start minimized" only applies to sessions the system auto-launched; launching FlashForgeUI yourself always shows the window. + +Be aware that some environments ignore requests from an application to minimize itself. Wayland in particular has no "minimized" window state, so on a Wayland session the window may simply open normally instead of minimizing. Use the tray icon to get back to the window whenever it is out of sight. On GNOME, tray icons require the AppIndicator extension - without it the icon will not appear, though relaunching FlashForgeUI always brings the existing window to the front. + +### Headless start with system + +The "Start with system" setting is part of the desktop app and does not apply to headless mode. To start headless FlashForgeUI at login, create a systemd user service at `~/.config/systemd/user/flashforgeui.service`: + +```ini +[Unit] +Description=FlashForgeUI (headless) +After=network-online.target + +[Service] +Type=simple +ExecStart=/opt/FlashForgeUI/FlashForgeUI --headless +Restart=on-failure + +[Install] +WantedBy=default.target +``` + +Adjust `ExecStart` to match your install (for an AppImage, use the full path to the `.AppImage` file). Then enable it: + +```bash +systemctl --user daemon-reload +systemctl --user enable --now flashforgeui +loginctl enable-linger "$USER" # start without an active login session +``` + +### The AppImage runs without Chromium's sandbox on Ubuntu + +Ubuntu 23.10 and newer ship `kernel.apparmor_restrict_unprivileged_userns=1`, which stops unprivileged programs from creating user namespaces. Chromium - which Electron is built on - needs either those namespaces or a root-owned `chrome-sandbox` helper to sandbox itself. An AppImage runs from a temporary user-owned mount, so the helper can never be root-owned, and the namespace route is now blocked. With neither available, Chromium refuses to start and the app appears to do nothing when launched. + +FlashForgeUI detects this at launch and starts with `--no-sandbox` so the app remains usable. This happens **only** when running the AppImage on a system where namespaces are blocked; the `.deb` and `.rpm` packages always run fully sandboxed. + +**If you want the AppImage sandboxed as well**, you can install an AppArmor profile yourself. This is optional and unsupported - it depends on where you keep the AppImage and is not something the app can do for you, since granting the permission requires root. Create `/etc/apparmor.d/flashforgeui` with the path to your AppImage: + +``` +abi , +include + +profile flashforgeui /home/YOUR_USER/Applications/FlashForgeUI.AppImage flags=(unconfined) { + userns, + include if exists +} +``` + +Then load it: + +```bash +sudo apparmor_parser -r /etc/apparmor.d/flashforgeui +``` + +The profile is tied to that exact path, so moving or renaming the AppImage means updating it. Installing the **`.deb` (or `.rpm`) instead** avoids all of this - those packages install their own AppArmor profile automatically during installation and need no manual steps. On Ubuntu 24.04+ the `.deb` is the recommended download. + +Background: [electron#41066](https://github.com/electron/electron/issues/41066) and [Ubuntu bug #2046844](https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2046844). diff --git a/electron-builder-config.cjs b/electron-builder-config.cjs index 30ee555..d71b268 100644 --- a/electron-builder-config.cjs +++ b/electron-builder-config.cjs @@ -41,6 +41,11 @@ module.exports = { executableName: 'FlashForgeUI', copyright: `Copyright © ${new Date().getFullYear()} GhostTypes`, + // Linux-only: wraps the packed binary in a launcher that falls back to --no-sandbox when an + // AppImage has no usable Chromium sandbox (Ubuntu 23.10+ AppArmor userns restriction). No-op on + // Windows/macOS. See the hook's header for the full rationale. + afterPack: 'scripts/linux/after-pack.cjs', + // Shared configurations directories: { output: 'dist', @@ -241,14 +246,20 @@ module.exports = { }, // DEB configuration + // NOTE: supplying afterInstall/afterRemove REPLACES electron-builder's own templates rather than + // extending them, so those scripts must reproduce the upstream body (AppArmor profile install, + // chrome-sandbox permissions, update-alternatives). appArmorProfile likewise overrides the + // generated profile so its attachment can cover the wrapped binary. See the file headers. deb: { afterInstall: 'assets/linux/afterInstall.sh', afterRemove: 'assets/linux/afterRemove.sh', + appArmorProfile: 'assets/linux/apparmor-profile', }, // RPM configuration rpm: { afterInstall: 'assets/linux/afterInstall.sh', afterRemove: 'assets/linux/afterRemove.sh', + appArmorProfile: 'assets/linux/apparmor-profile', }, }; diff --git a/scripts/linux/after-pack.cjs b/scripts/linux/after-pack.cjs new file mode 100644 index 0000000..2605836 --- /dev/null +++ b/scripts/linux/after-pack.cjs @@ -0,0 +1,115 @@ +/** + * @fileoverview electron-builder afterPack hook that wraps the packaged Linux binary in a launcher + * script which enables Chromium's `--no-sandbox` fallback only when the AppImage runtime has no + * usable sandbox. + * + * Why this exists: + * - An AppImage runs from an ephemeral, user-owned FUSE mount, so `chrome-sandbox` can never carry + * the root-owned setuid bit Chromium's SUID sandbox requires. AppImages have always relied on + * the alternative namespace sandbox instead. + * - Ubuntu 23.10+ sets `kernel.apparmor_restrict_unprivileged_userns=1`, which blocks unprivileged + * user namespaces for binaries without an AppArmor profile granting `userns`. An AppImage has no + * install step, so it cannot install such a profile (that would require root). + * - With neither sandbox available Chromium aborts during startup - before `app.whenReady()` - so + * this cannot be detected or reported from inside the application. It has to happen in a shell + * wrapper that runs before the binary. See https://github.com/electron/electron/issues/41066. + * + * electron-builder does put `--no-sandbox` in the AppImage's generated `.desktop` entry, but that + * only applies to desktop-integrated launches; double-clicking the `.AppImage` invokes `AppRun` + * directly with no arguments and gets nothing. The launcher closes that gap. + * + * Deliberately narrow: the launcher degrades ONLY when running from an AppImage (`$APPIMAGE` set) + * AND user namespaces are actually unavailable. The same packed output is reused for the .deb and + * .rpm targets, and there the launcher is a pass-through - those packages install an AppArmor + * profile in their postinst and keep the sandbox fully enabled. + * + * Key exports: + * - module.exports: the afterPack hook, wired up via `afterPack` in electron-builder-config.cjs + * + * @module scripts/linux/after-pack + */ + +const fs = require('node:fs'); +const path = require('node:path'); + +/** Must match `executableName` in electron-builder-config.cjs. */ +const EXECUTABLE_NAME = 'FlashForgeUI'; + +/** + * Name the real Electron binary is moved aside to. The AppArmor profile in + * assets/linux/apparmor-profile attaches to both this and the launcher; keep them in sync. + */ +const REAL_BINARY_NAME = `${EXECUTABLE_NAME}.bin`; + +/** + * Marker comment used to recognize a launcher this hook already wrote, so repeated packs (or a + * rebuild over a dirty output directory) do not wrap the wrapper. + */ +const LAUNCHER_MARKER = '# FlashForgeUI sandbox-aware launcher'; + +const LAUNCHER_SCRIPT = `#!/bin/bash +${LAUNCHER_MARKER} +# +# Generated by scripts/linux/after-pack.cjs - do not edit inside the packaged app. +# +# Chooses between a sandboxed and an unsandboxed launch. See the hook for the full rationale; +# in short, an AppImage on Ubuntu 23.10+ has neither the SUID sandbox (impossible from a FUSE +# mount) nor the namespace sandbox (blocked by AppArmor), and Chromium aborts before the app can +# report anything. Falling back to --no-sandbox there is the difference between the app starting +# and the user seeing nothing happen at all. +set -u + +HERE="$(dirname "$(readlink -f "\${0}")")" +BIN="\$HERE/${REAL_BINARY_NAME}" + +# Only AppImage launches are eligible for the fallback. Under .deb/.rpm the postinst installs an +# AppArmor profile granting userns and sets up chrome-sandbox, so the sandbox must stay enabled. +if [ -n "\${APPIMAGE:-}" ]; then + # 'unshare --user true' is the same probe electron-builder's postinst uses. If unshare itself is + # unavailable we cannot test, so we assume namespaces work and keep the sandbox on rather than + # silently weakening it. + if command -v unshare >/dev/null 2>&1; then + if ! { [ -L /proc/self/ns/user ] && unshare --user true; } >/dev/null 2>&1; then + exec "\$BIN" --no-sandbox "\$@" + fi + fi +fi + +exec "\$BIN" "\$@" +`; + +/** + * Wrap the packed Linux executable. No-ops on non-Linux packs and on output directories that have + * already been wrapped. + * + * @param {{ electronPlatformName: string, appOutDir: string }} context - electron-builder afterPack context. + * @returns {Promise} + */ +module.exports = async function afterPack(context) { + if (context.electronPlatformName !== 'linux') { + return; + } + + const launcherPath = path.join(context.appOutDir, EXECUTABLE_NAME); + const realBinaryPath = path.join(context.appOutDir, REAL_BINARY_NAME); + + if (fs.existsSync(realBinaryPath)) { + console.log(`[after-pack] Launcher already present in ${context.appOutDir} - skipping.`); + return; + } + + if (!fs.existsSync(launcherPath)) { + throw new Error( + `[after-pack] Expected packed executable at ${launcherPath} but it does not exist. ` + + `Has executableName changed in electron-builder-config.cjs?` + ); + } + + fs.renameSync(launcherPath, realBinaryPath); + fs.writeFileSync(launcherPath, LAUNCHER_SCRIPT, { encoding: 'utf8', mode: 0o755 }); + // writeFileSync only applies `mode` when it creates the file; chmod unconditionally so a + // pre-existing file (or a restrictive umask) cannot leave the launcher non-executable. + fs.chmodSync(launcherPath, 0o755); + + console.log(`[after-pack] Wrapped ${EXECUTABLE_NAME} with the sandbox-aware launcher.`); +}; diff --git a/src/main/index.ts b/src/main/index.ts index ab3c4f1..86eeb1a 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -67,6 +67,7 @@ import { getHeadlessManager } from './managers/HeadlessManager.js'; import { getLoadingManager } from './managers/LoadingManager.js'; import { getAutoUpdateService } from './services/AutoUpdateService.js'; import { getAutoLaunchService } from './services/AutoLaunchService.js'; +import { getTrayService } from './services/TrayService.js'; import { initializeSpoolmanIntegrationService, getSpoolmanIntegrationService, @@ -376,9 +377,13 @@ const createMainWindow = async (): Promise => { const roundedUI = config.RoundedUI; const useRoundedUI = roundedUI && isRoundedUISupported(); - // Resolve the hidden-start (minimized) state for this launch. StartMinimized applies to - // every launch; wasLaunchedHidden() covers OS auto-launched sessions via the --hidden arg. - const startHidden = config.StartMinimized || autoLaunchService.wasLaunchedHidden(); + // Resolve the hidden-start (minimized) state for this launch. StartMinimized is a MODIFIER on + // StartAtBoot, not an independent preference: it reaches this process as the `--hidden` launch + // argument that AutoLaunchService writes into the OS login item (Windows/macOS) or the + // freedesktop autostart entry (Linux). Reading config.StartMinimized directly here would also + // hide manually launched sessions, which reads as "the app does not start" - especially on + // Linux, where a hidden window may never surface in the taskbar at all. + const startHidden = autoLaunchService.wasLaunchedHidden(); console.log( `[Window] Hidden-start decision: startHidden=${startHidden} (StartMinimized=${config.StartMinimized})` ); @@ -399,7 +404,10 @@ const createMainWindow = async (): Promise => { }, frame: false, // Always frameless for custom titlebar transparent: useRoundedUI, // Only transparent when rounded UI is enabled - show: !startHidden, // Hide immediately when starting hidden/minimized + // Hidden starts create the window unmapped so it never flashes on screen. Linux is the + // exception: an unmapped window cannot be minimized (see the hidden-start block below), so + // it is created shown and minimized once its contents are ready. + show: !startHidden || process.platform === 'linux', }); // Hide traffic light buttons on macOS @@ -410,11 +418,26 @@ const createMainWindow = async (): Promise => { // Ensure background throttling is disabled for WebContents mainWindow.webContents.setBackgroundThrottling(false); - // Apply taskbar minimize for hidden starts on Windows/Linux without flashing the window. - // On macOS, the window was created with show:false and stays hidden until surfaced. - if (startHidden && (process.platform === 'win32' || process.platform === 'linux')) { - mainWindow.minimize(); - console.log('[Window] Main window started minimized to taskbar'); + // Apply taskbar minimize for hidden starts. Platform behavior differs: + // - Windows: minimize() on the not-yet-shown window creates the taskbar button directly, so the + // window never flashes on screen. + // - Linux: minimize() cannot act on a window that was never mapped (see electron#45815 for the + // same defect via maximize()), so the window is created shown and minimized on ready-to-show. + // Some environments ignore programmatic minimize entirely - notably Wayland, where "minimized" + // is not a supported window state - and there the window simply stays open. That is a + // window-manager limitation, not something the app can work around; the tray icon is the + // reliable way back to the window in that case. + // - macOS: the window was created with show:false and stays hidden until the dock surfaces it. + if (startHidden) { + if (process.platform === 'win32') { + mainWindow.minimize(); + console.log('[Window] Main window started minimized to taskbar'); + } else if (process.platform === 'linux') { + mainWindow.once('ready-to-show', () => { + mainWindow.minimize(); + console.log('[Window] Main window minimized after ready-to-show (Linux hidden start)'); + }); + } } // Load the app using environment-aware path resolution @@ -976,6 +999,10 @@ const initializeApp = async (): Promise => { await createMainWindow(); console.log('Main window created with all handlers ready'); + // Create the tray icon once a window exists for it to surface. This is the reliable way back to + // the app after a hidden start, since not every desktop environment honors minimize-to-taskbar. + getTrayService().initialize(); + // Initialize Spoolman integration service (after window creation to avoid timing issues) const spoolmanService = initializeSpoolmanIntegrationService( getConfigManager(), @@ -1408,6 +1435,9 @@ app.on('window-all-closed', () => { // Cleanup when app is quitting app.on('before-quit', async () => { try { + // Remove the tray icon first so it does not linger in the status area during teardown + getTrayService().destroy(); + // Stop power save blocker if (powerSaveBlockerId !== null) { powerSaveBlocker.stop(powerSaveBlockerId); diff --git a/src/main/services/AutoLaunchService.ts b/src/main/services/AutoLaunchService.ts index fe147f3..f550fc6 100644 --- a/src/main/services/AutoLaunchService.ts +++ b/src/main/services/AutoLaunchService.ts @@ -23,7 +23,10 @@ * real, fixed `.AppImage` location in `process.env.APPIMAGE`; that is what we write. For non-AppImage * packaging (.deb/.rpm) there is no FUSE mount and `process.execPath` already IS the stable installed * binary path (e.g. `/opt/FlashForgeUI/flashforgeui`), and no APPIMAGE var is set — so falling back to - * `process.execPath` there is correct. In short: prefer APPIMAGE when set, else process.execPath. + * `process.execPath` there is correct. In short: prefer APPIMAGE when set, else process.execPath - + * minus the `.bin` suffix the packaged Linux launcher wrapper introduces (see resolveLinuxExecPath). + * - The entry also carries TryExec (so a moved or uninstalled binary makes the entry a silent no-op + * rather than a failing launch) and Icon (so KDE's Autostart panel renders the row properly). * - Disabling start-at-boot removes the `.desktop` file. * * Key exports: @@ -38,7 +41,7 @@ * @module services/AutoLaunchService */ -import { mkdirSync, rmSync, writeFileSync } from 'node:fs'; +import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'; import { homedir } from 'node:os'; import { posix as pathPosix } from 'node:path'; @@ -61,6 +64,12 @@ const HIDDEN_LAUNCH_ARG = '--hidden'; */ const LINUX_AUTOSTART_FILENAME = 'flashforgeui.desktop'; +/** + * Suffix the Linux build gives the real Electron binary when it is moved aside for the + * sandbox-aware launcher script (see `scripts/linux/after-pack.cjs`). Kept in sync with that hook. + */ +const WRAPPED_BINARY_SUFFIX = '.bin'; + /** * Quote a single argument for a Desktop Entry `Exec=` line per the freedesktop Desktop Entry * Specification: the argument is wrapped in double quotes and the reserved characters `"`, backtick, @@ -68,7 +77,11 @@ const LINUX_AUTOSTART_FILENAME = 'flashforgeui.desktop'; * and other reserved characters (parentheses, `&`, `;`, etc.) that can appear in install paths. */ const quoteDesktopExecArg = (value: string): string => { - const escaped = value.replace(/(["`$\\])/g, '\\$1'); + // Literal percent signs are field codes to the Exec parser and must be doubled. This is applied + // before quoting because `%` is not one of the backslash-escaped characters - `%%` is its own + // escape mechanism, independent of the surrounding double quotes. + const percentEscaped = value.replace(/%/g, '%%'); + const escaped = percentEscaped.replace(/(["`$\\])/g, '\\$1'); return `"${escaped}"`; }; @@ -103,10 +116,12 @@ class AutoLaunchService { * Read current StartAtBoot / StartMinimized preferences, apply the OS login item, and * subscribe to per-key config changes so live toggles stay in sync. * - * ConfigManager loads asynchronously, so getConfig() may initially return defaults. The - * per-key `config:` events also fire during load (for values that differ from defaults), - * which re-applies the correct registration once the saved values are available. This mirrors - * AutoUpdateService's initialize() behavior. + * ConfigManager loads asynchronously, so getConfig() returns defaults until the load settles. + * Applying those defaults eagerly is not harmless on Linux: StartAtBoot defaults to false, and + * a false value DELETES the autostart entry - so a user with start-at-boot enabled would have + * their `.desktop` file removed and then rewritten moments later when the load completes. The + * initial apply is therefore deferred until the config is loaded; the per-key listeners are + * registered immediately either way so live toggles are never missed. */ public initialize(): void { if (this.initialized) { @@ -114,8 +129,15 @@ class AutoLaunchService { } this.initialized = true; - const config = this.configManager.getConfig(); - this.applyLoginItemSettings(config.StartAtBoot, config.StartMinimized); + if (this.configManager.isConfigLoaded()) { + const config = this.configManager.getConfig(); + this.applyLoginItemSettings(config.StartAtBoot, config.StartMinimized); + } else { + this.configManager.once('config-loaded', () => { + const loadedConfig = this.configManager.getConfig(); + this.applyLoginItemSettings(loadedConfig.StartAtBoot, loadedConfig.StartMinimized); + }); + } this.configManager.on('config:StartAtBoot', (startAtBoot: boolean) => { const currentConfig = this.configManager.getConfig(); @@ -194,10 +216,26 @@ class AutoLaunchService { * `.desktop` entry referencing it would be dead after the first reboot. APPIMAGE holds the * stable path to the actual `.AppImage` file. Non-AppImage packaging (.deb/.rpm, or a plain * unpacked run) has no APPIMAGE env var and falls back to `process.execPath`. + * + * One wrinkle on .deb/.rpm: the Linux build wraps the Electron binary in a launcher script + * (`scripts/linux/after-pack.cjs`) and moves the real binary aside to `.bin`, so + * `process.execPath` points at the `.bin`. Autostart should invoke the launcher - the supported + * entry point - so a trailing `.bin` is dropped when the sibling launcher actually exists. */ private resolveLinuxExecPath(): string { const appImagePath = process.env.APPIMAGE?.trim(); - return appImagePath && appImagePath.length > 0 ? appImagePath : process.execPath; + if (appImagePath && appImagePath.length > 0) { + return appImagePath; + } + + const execPath = process.execPath; + if (execPath.endsWith(WRAPPED_BINARY_SUFFIX)) { + const launcherPath = execPath.slice(0, -WRAPPED_BINARY_SUFFIX.length); + if (existsSync(launcherPath)) { + return launcherPath; + } + } + return execPath; } /** @@ -236,6 +274,14 @@ class AutoLaunchService { `Name=${app.getName()}`, 'Comment=Automatically start FlashForgeUI at login', `Exec=${execLine}`, + // TryExec makes a stale entry fail silently instead of loudly: if the binary has been moved, + // renamed or uninstalled, the autostart spec requires the entry to be skipped rather than + // executed. Unlike Exec this is a plain path, not a quoted/escaped command line. + `TryExec=${execPath}`, + // Icon is optional for autostart itself, but KDE's Autostart control panel and several + // session managers list the entry with its icon; without it the row renders blank. The name + // matches the icon the .deb/.rpm install into hicolor. + `Icon=${app.getName()}`, 'Terminal=false', 'X-GNOME-Autostart-enabled=true', '', diff --git a/src/main/services/TrayService.ts b/src/main/services/TrayService.ts new file mode 100644 index 0000000..f3bf695 --- /dev/null +++ b/src/main/services/TrayService.ts @@ -0,0 +1,162 @@ +/** + * @fileoverview System tray service providing a persistent, always-reachable entry point to the + * main window. + * + * Added alongside the start-at-boot / start-minimized work for issue #75. A hidden start is only + * safe if there is a guaranteed way back to the window, and minimizing to the taskbar is not that + * guarantee on every platform: Electron does not support "minimized" as a window state on Wayland, + * and several Linux desktop environments ignore programmatic minimize entirely, so a window asked + * to minimize may end up with no visible taskbar presence at all. The tray icon is the reliable + * fallback - it is present regardless of window state and independent of the window manager's + * minimize behavior. + * + * Behavior: + * - Left-click (and double-click, which Windows reports separately) surfaces the main window + * - Context menu offers Show and Quit + * - Desktop mode only; headless runs never create a tray + * + * Note that tray support itself is not universal on Linux: GNOME has no built-in StatusNotifierItem + * host and needs an extension (e.g. AppIndicator) for the icon to appear. Tray creation failing is + * therefore treated as non-fatal and logged rather than thrown - the app remains fully usable, and + * relaunching still surfaces the window through the single-instance handler. + * + * Key exports: + * - TrayService class: singleton managing the tray lifecycle + * - getTrayService(): singleton accessor + * + * @module services/TrayService + */ + +import path from 'node:path'; + +import { app, Menu, nativeImage, Tray } from 'electron'; +import log from 'electron-log'; + +import { getWindowManager } from '../windows/WindowManager.js'; + +/** + * Tray icon edge length in pixels. Linux and macOS status areas expect a small image and will not + * downscale a full-size application icon gracefully; Windows tolerates either but looks best with + * a scaled image too. + */ +const TRAY_ICON_SIZE = 22; + +/** + * System tray orchestration service. + */ +class TrayService { + private static instance: TrayService | null = null; + + private tray: Tray | null = null; + + private constructor() { + // Singleton - use getTrayService() + } + + /** + * Get singleton instance. + */ + public static getInstance(): TrayService { + if (!TrayService.instance) { + TrayService.instance = new TrayService(); + } + return TrayService.instance; + } + + /** + * Create the tray icon and wire its menu. Safe to call repeatedly; subsequent calls are ignored + * while a tray already exists. + */ + public initialize(): void { + if (this.tray) { + return; + } + + try { + const icon = this.buildTrayIcon(); + if (icon.isEmpty()) { + log.warn('[Tray] Tray icon image could not be loaded - skipping tray creation.'); + return; + } + + this.tray = new Tray(icon); + this.tray.setToolTip(app.getName()); + this.tray.setContextMenu( + Menu.buildFromTemplate([ + { + label: `Show ${app.getName()}`, + click: (): void => this.surfaceMainWindow(), + }, + { type: 'separator' }, + { + label: 'Quit', + click: (): void => app.quit(), + }, + ]) + ); + + // Windows reports single and double clicks as distinct events; both should surface the app. + this.tray.on('click', () => this.surfaceMainWindow()); + this.tray.on('double-click', () => this.surfaceMainWindow()); + + log.info('[Tray] System tray icon created.'); + } catch (error: unknown) { + // Tray support is optional (notably absent on stock GNOME). Never let it break startup. + log.error(`[Tray] Failed to create system tray icon: ${String(error)}`); + this.tray = null; + } + } + + /** + * Restore, show and focus the main window. Mirrors the single-instance handler so both recovery + * paths behave identically. + */ + public surfaceMainWindow(): void { + const mainWindow = getWindowManager().getMainWindow(); + if (!mainWindow) { + log.warn('[Tray] Show requested but no main window exists.'); + return; + } + + if (mainWindow.isMinimized()) { + mainWindow.restore(); + } + mainWindow.show(); + mainWindow.focus(); + } + + /** + * Destroy the tray icon. Called during shutdown so the icon does not linger in the status area. + */ + public destroy(): void { + if (!this.tray) { + return; + } + + this.tray.destroy(); + this.tray = null; + log.info('[Tray] System tray icon destroyed.'); + } + + /** + * Load and scale the tray image. + * + * Uses the same `src/icons` location as NotificationService so both surfaces stay consistent. + * PNG is used on every platform: it scales predictably, and Windows accepts it for tray icons. + */ + private buildTrayIcon(): Electron.NativeImage { + const iconPath = path.join(app.getAppPath(), 'src', 'icons', 'icon.png'); + const image = nativeImage.createFromPath(iconPath); + if (image.isEmpty()) { + return image; + } + return image.resize({ width: TRAY_ICON_SIZE, height: TRAY_ICON_SIZE }); + } +} + +/** + * Singleton accessor. + */ +export const getTrayService = (): TrayService => TrayService.getInstance(); + +export { TrayService }; diff --git a/src/main/services/__tests__/AutoLaunchService.test.ts b/src/main/services/__tests__/AutoLaunchService.test.ts index e726a7a..f1726bc 100644 --- a/src/main/services/__tests__/AutoLaunchService.test.ts +++ b/src/main/services/__tests__/AutoLaunchService.test.ts @@ -4,8 +4,10 @@ * Validates OS login-item registration for the "Start with system" / "Start minimized" * preferences (issue #75): correct app.setLoginItemSettings arguments on toggle, openAsHidden * only applying on darwin, the Linux freedesktop `.desktop` autostart path (write/remove, - * APPIMAGE vs execPath, XDG_CONFIG_HOME, --hidden), wasLaunchedHidden() detection across - * platforms, and that unpackaged (development) builds skip OS registration while honoring toggles. + * APPIMAGE vs execPath vs the wrapped `.bin` launcher, XDG_CONFIG_HOME, --hidden, TryExec/Icon, + * `%%` escaping), deferral of the initial apply until the config has loaded, wasLaunchedHidden() + * detection across platforms, and that unpackaged (development) builds skip OS registration while + * honoring toggles. * * @module services/__tests__/AutoLaunchService.test */ @@ -21,11 +23,13 @@ jest.mock('electron', () => ({ app: mockApp, })); -// Filesystem mock for the Linux autostart path (node:fs). +// Filesystem mock for the Linux autostart path (node:fs). existsSync backs the launcher-vs-.bin +// resolution and defaults to false so tests opt in explicitly. const mockFs = { mkdirSync: jest.fn(), writeFileSync: jest.fn(), rmSync: jest.fn(), + existsSync: jest.fn(() => false), }; jest.mock('node:fs', () => mockFs); @@ -38,7 +42,9 @@ jest.mock('node:os', () => ({ // Mutable ConfigManager mock used by the service constructor + listeners. const mockConfigManager = { getConfig: jest.fn(() => ({ StartAtBoot: false, StartMinimized: false })), + isConfigLoaded: jest.fn(() => true), on: jest.fn(), + once: jest.fn(), emit: jest.fn(), }; @@ -72,7 +78,9 @@ describe('AutoLaunchService', () => { // Restore default mock return values. mockConfigManager.getConfig.mockReturnValue({ StartAtBoot: false, StartMinimized: false }); + mockConfigManager.isConfigLoaded.mockReturnValue(true); mockEnvironmentService.isPackaged.mockReturnValue(true); + mockFs.existsSync.mockReturnValue(false); mockApp.getLoginItemSettings.mockReturnValue({ launchItems: [] }); Object.defineProperty(process, 'argv', { value: ['electron'], configurable: true }); @@ -349,6 +357,84 @@ describe('AutoLaunchService', () => { expect(mockFs.writeFileSync).not.toHaveBeenCalled(); }); + it('writes TryExec and Icon so stale entries are skipped and KDE renders the row', () => { + process.env.APPIMAGE = '/home/testuser/Apps/FlashForgeUI.AppImage'; + mockConfigManager.getConfig.mockReturnValue({ StartAtBoot: true, StartMinimized: false }); + + service.initialize(); + + const [, contents] = mockFs.writeFileSync.mock.calls[0] as [string, string]; + // TryExec is a plain path, not a quoted Exec-style command line. + expect(contents).toContain('TryExec=/home/testuser/Apps/FlashForgeUI.AppImage'); + expect(contents).toContain('Icon=FlashForgeUI'); + }); + + it('escapes literal percent signs in the Exec path as %%', () => { + // A literal % is a field code to the Exec parser, so it must be doubled. + process.env.APPIMAGE = '/home/testuser/100% Apps/FlashForgeUI.AppImage'; + mockConfigManager.getConfig.mockReturnValue({ StartAtBoot: true, StartMinimized: false }); + + service.initialize(); + + const [, contents] = mockFs.writeFileSync.mock.calls[0] as [string, string]; + expect(contents).toContain('Exec="/home/testuser/100%% Apps/FlashForgeUI.AppImage"'); + }); + + it('targets the launcher script rather than the wrapped .bin binary on deb/rpm', () => { + // The Linux build moves the real Electron binary to .bin behind a launcher script; + // autostart should invoke the launcher, which is the supported entry point. + Object.defineProperty(process, 'execPath', { + value: '/opt/FlashForgeUI/FlashForgeUI.bin', + configurable: true, + }); + mockFs.existsSync.mockImplementation((p: unknown) => p === '/opt/FlashForgeUI/FlashForgeUI'); + mockConfigManager.getConfig.mockReturnValue({ StartAtBoot: true, StartMinimized: false }); + + service.initialize(); + + const [, contents] = mockFs.writeFileSync.mock.calls[0] as [string, string]; + expect(contents).toContain('Exec="/opt/FlashForgeUI/FlashForgeUI"'); + expect(contents).toContain('TryExec=/opt/FlashForgeUI/FlashForgeUI'); + }); + + it('keeps the .bin path when no sibling launcher exists', () => { + Object.defineProperty(process, 'execPath', { + value: '/opt/FlashForgeUI/FlashForgeUI.bin', + configurable: true, + }); + mockFs.existsSync.mockReturnValue(false); + mockConfigManager.getConfig.mockReturnValue({ StartAtBoot: true, StartMinimized: false }); + + service.initialize(); + + const [, contents] = mockFs.writeFileSync.mock.calls[0] as [string, string]; + expect(contents).toContain('Exec="/opt/FlashForgeUI/FlashForgeUI.bin"'); + }); + + it('defers the initial apply until the config is loaded', () => { + // Applying default StartAtBoot=false eagerly would delete a valid autostart entry before + // the saved config arrives. + mockConfigManager.isConfigLoaded.mockReturnValue(false); + mockConfigManager.getConfig.mockReturnValue({ StartAtBoot: false, StartMinimized: false }); + process.env.APPIMAGE = '/home/testuser/Apps/FlashForgeUI.AppImage'; + + service.initialize(); + + expect(mockFs.rmSync).not.toHaveBeenCalled(); + expect(mockFs.writeFileSync).not.toHaveBeenCalled(); + + // Once the load settles, the saved values are applied. + const configLoadedCall = mockConfigManager.once.mock.calls.find( + ([event]) => event === 'config-loaded' + ); + expect(configLoadedCall).toBeDefined(); + mockConfigManager.getConfig.mockReturnValue({ StartAtBoot: true, StartMinimized: true }); + (configLoadedCall as unknown as [string, () => void])[1](); + + const [, contents] = mockFs.writeFileSync.mock.calls[0] as [string, string]; + expect(contents).toContain('Exec="/home/testuser/Apps/FlashForgeUI.AppImage" --hidden'); + }); + it('skips filesystem writes in development (unpackaged) mode', () => { mockEnvironmentService.isPackaged.mockReturnValue(false); mockConfigManager.getConfig.mockReturnValue({ StartAtBoot: true, StartMinimized: false }); From 4459714c5178e44a04efaa98d82cfed49e1f5569 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Thu, 23 Jul 2026 20:03:22 -0400 Subject: [PATCH 40/93] docs: surface the deb/rpm AppArmor behavior for end users (#75) --- docs/README.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 4012ce7..b76bed9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -239,7 +239,21 @@ systemctl --user enable --now flashforgeui loginctl enable-linger "$USER" # start without an active login session ``` -### The AppImage runs without Chromium's sandbox on Ubuntu +### Chromium's sandbox on Ubuntu 24.04+ (AppArmor) + +**If you installed the `.deb` or `.rpm`, there is nothing to do here** — read this only if the app fails to start. + +Those packages install an AppArmor profile to `/etc/apparmor.d/FlashForgeUI` during installation and load it automatically, so FlashForgeUI runs fully sandboxed with no manual steps. To confirm it is active: + +```bash +aa-status | grep FlashForgeUI +``` + +Installation deliberately skips the profile on older AppArmor versions that cannot parse it (Ubuntu 22.04 and earlier). That is expected and harmless — those releases do not restrict user namespaces in the first place, so the sandbox works without a profile. You will see a "Skipping the installation of the AppArmor profile" line during install. + +If FlashForgeUI does not start after a `.deb`/`.rpm` install on Ubuntu 24.04+, check whether that profile exists and reload it with `sudo apparmor_parser -r /etc/apparmor.d/FlashForgeUI`. Running the app from a terminal will show the underlying Chromium sandbox error. + +#### Why the AppImage is different Ubuntu 23.10 and newer ship `kernel.apparmor_restrict_unprivileged_userns=1`, which stops unprivileged programs from creating user namespaces. Chromium - which Electron is built on - needs either those namespaces or a root-owned `chrome-sandbox` helper to sandbox itself. An AppImage runs from a temporary user-owned mount, so the helper can never be root-owned, and the namespace route is now blocked. With neither available, Chromium refuses to start and the app appears to do nothing when launched. @@ -263,6 +277,6 @@ Then load it: sudo apparmor_parser -r /etc/apparmor.d/flashforgeui ``` -The profile is tied to that exact path, so moving or renaming the AppImage means updating it. Installing the **`.deb` (or `.rpm`) instead** avoids all of this - those packages install their own AppArmor profile automatically during installation and need no manual steps. On Ubuntu 24.04+ the `.deb` is the recommended download. +The profile is tied to that exact path, so moving or renaming the AppImage means updating it. Installing the **`.deb` (or `.rpm`) instead** avoids all of this, which is why those are the recommended downloads on Ubuntu 24.04+. Background: [electron#41066](https://github.com/electron/electron/issues/41066) and [Ubuntu bug #2046844](https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2046844). From 07c2b14850f2272bbec16f5b9f6e2853692422e5 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Thu, 23 Jul 2026 21:35:32 -0400 Subject: [PATCH 41/93] Detect modern printers from the discovery product ID and add a manual connect form --- CHANGELOG.md | 5 + CLAUDE.md | 6 +- docs/README.md | 57 +++- src/main/ipc/DialogHandlers.ts | 31 +- src/main/managers/ConnectionFlowManager.ts | 160 +++++++--- .../ConnectionEstablishmentService.ts | 17 +- src/main/utils/HeadlessArguments.ts | 43 ++- src/main/windows/WindowFactory.ts | 3 +- .../windows/factories/DialogWindowFactory.ts | 86 ++++++ src/main/windows/shared/WindowTypes.ts | 13 + .../manual-connect-dialog-preload.ts | 74 +++++ .../manual-connect-dialog-renderer.ts | 280 ++++++++++++++++++ .../manual-connect-dialog.css | 167 +++++++++++ .../manual-connect-dialog.html | 72 +++++ src/shared/types/global.d.ts | 2 + src/shared/types/manual-connect.ts | 57 ++++ 16 files changed, 995 insertions(+), 78 deletions(-) create mode 100644 src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog-preload.ts create mode 100644 src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog-renderer.ts create mode 100644 src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog.css create mode 100644 src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog.html create mode 100644 src/shared/types/manual-connect.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 62d5d43..30806f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Connecting to Printers +- Modern printers are now identified from the USB product ID in their discovery broadcast instead of an unauthenticated TCP probe. The probe was previously skipped only for the HTTP-only Creator 5 series; it is now skipped for every modern model (5M, 5M Pro, AD5X, Creator 5, Creator 5 Pro), removing a redundant round trip from every modern connect. The broadcast already carries the serial and name, and the capability flags come from the library after `initialize()`, so the probe had nothing left to contribute. Printers with no product ID — genuine legacy printers, and manual connects that chose "Legacy Printer" — are still probed as before. +- New **manual connect form**, replacing the single "Enter IP" prompt. Because a named model is no longer probed, the form collects the details the broadcast would have supplied: IP address, printer type, serial number, and check code. Legacy remains IP-only. The check code entered here is used directly, so you are no longer prompted for it a second time. +- Headless `--printers` now accepts `creator-5` / `creator-5-pro` type tokens and an optional fourth `SERIAL` field (`IP:TYPE[:CHECKCODE[:SERIAL]]`). The Creator tokens mark HTTP-only printers so the flow skips the TCP probe they cannot answer, and a serial is required for them since it cannot be recovered by probing. Documented in the user guide with examples. + ### File Manager - New SFTP-based file manager (topbar shortcut) for the Adventurer 5M / 5M Pro / AD5X. Browse, multi-select delete, and rename gcode/3MF files on internal storage and USB, with thumbnails resolved through the local cache, printer-side cache PNGs, and ranged-read `.3mf` extraction (no full-file download). USB presence is probed via `/proc/mounts`. diff --git a/CLAUDE.md b/CLAUDE.md index 57270b0..a11eb8f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -144,9 +144,11 @@ For detailed architectural information, see the comprehensive reference document - `src/main/printer-backends/MaterialStationBackend.ts` - shared abstract base for the 4-slot material-station printers; AD5X and Creator 5 both extend it - `src/main/printer-backends/ad5x/*` - material station transforms/types/utils -### Model Detection (TCP-First Bootstrap, PID-Aware) +### Model Detection (Discovery-PID-First, TCP Fallback) -- **Bootstrap order matters.** The HTTP `/detail` endpoint requires authentication (`serialNumber` + `checkCode`), so during the very first connection — before the user has supplied a check code — we cannot read the firmware-set `pid` from `/detail`. `ConnectionEstablishmentService.ts` therefore opens an unauthenticated TCP `M115` first via `tcpClient.getPrinterInfo()` and uses the resulting `TypeName` (firmware-controlled, e.g. `"FlashForge Adventurer 5M Pro"`) for backend selection in `PrinterUtils.ts` (`detectPrinterModelType` / `detectPrinterFamily`). This is correct and intentional — `TypeName` is firmware-set and not the same as the user-mutable `Name` from `/detail`. +- **Modern printers are typed from the discovery broadcast, not a TCP probe.** The UDP discovery response (276-byte modern packet) carries the USB product ID at `0x88`, the serial number at `0x92` and the name at `0x00`. `ConnectionEstablishmentService.createTemporaryConnection()` short-circuits on any product ID in `NEW_API_PRODUCT_IDS` (35 = 5M, 36 = 5M Pro, 38 = AD5X, 40 = Creator 5, 41 = Creator 5 Pro) and synthesizes the type info from that packet — **no TCP probe runs for any modern model**. This is safe because `establishDualAPIConnection` consumes none of the probe's output, capability flags come from `FiveMClient.initialize()` post-init, and reachability is covered by `initialize()` hitting authenticated `/detail`. (Verified against real hardware: a 5M Pro and an AD5X both return their serial at `0x92` and a correct PID at `0x88`.) +- **The TCP probe remains the fallback for anything with no product ID.** Genuine legacy printers, and manual/headless connects that named no model, still open an unauthenticated TCP `M115` via `tcpClient.getPrinterInfo()`; the resulting `TypeName` (firmware-controlled, e.g. `"FlashForge Adventurer 5M Pro"`) drives backend selection in `PrinterUtils.ts` (`detectPrinterModelType` / `detectPrinterFamily`). `TypeName` is firmware-set and not the same as the user-mutable `Name` from `/detail`. +- **Manual connects supply what the broadcast would have.** Because a named model skips the probe, the manual connect dialog (`src/renderer/src/ui/manual-connect-dialog/`, shown from the connect-choice "Enter IP" branch) collects IP + printer type + serial + check code, and `ConnectionFlowManager.connectDirectlyToIP()` maps the selected type to a product ID hint. Selecting `Legacy Printer` sends no product ID and is probed as before; `connectDirectlyToIP` still accepts a bare IP string for that path. - **Once paired, trust the library.** After the check code is provided and `FiveMClient.initialize()` succeeds, `client.isPro` / `client.isAD5X` / `info.Pid` (from `@ghosttypes/ff-api>=1.3.1`) are derived from the firmware `pid` (35 = 5M, 36 = 5M Pro, 38 = AD5X). All later capability gating should read those flags, not re-substring-match `info.Name` — that field is user-mutable via the LCD or cloud and re-deriving capabilities from it re-introduces the bug fixed in `ff-5mp-hass#13`. - **Don't mutate `client.isAD5X` after the fact.** If the upstream library disagrees with what you expected, fix the library or the backend selection upstream — don't patch the flag locally. - **HTTP-only models (Creator 5 / Creator 5 Pro) bypass TCP.** These printers expose no legacy TCP server on port 8899. `ConnectionEstablishmentService.ts` checks `isHttpOnlyModel()` and connects them over HTTP directly — even if a stale `forceLegacyMode` flag is saved, the bad flag is healed on the next successful HTTP connect. Backend routing for these uses the authoritative USB product ID carried through discovery, not the post-auth `/detail` endpoint. diff --git a/docs/README.md b/docs/README.md index b76bed9..fbede55 100644 --- a/docs/README.md +++ b/docs/README.md @@ -84,9 +84,14 @@ FlashForgeUI.exe --enable-logging --headless --all-saved-printers **`--printers=`** - Connects to specific printer(s) by IP address and type -- Format: `--printers="::,::,..."` -- Type: `new` (5M family) or `legacy` (older models) -- Checkcode: Required for `new` type printers (8-digit code) +- Format: `--printers=":[:[:]],..."` +- Type: `new` (5M family), `legacy` (older models), or `creator-5` / `creator-5-pro` +- Checkcode: Required for all modern types (8-digit code) +- Serial: **Required for `creator-5` / `creator-5-pro`**, optional otherwise + +The Creator 5 series is HTTP-only — it runs no legacy TCP server — so those printers +need the dedicated type token (the generic `new` token triggers a TCP probe they +cannot answer) and their serial number, which cannot be recovered by probing. Single printer example: ```bash @@ -98,6 +103,11 @@ Multiple printers example: FlashForgeUI.exe --enable-logging --headless --printers="192.168.1.100:new:12345678,192.168.1.101:legacy" ``` +Creator 5 Pro example (serial required): +```bash +FlashForgeUI.exe --enable-logging --headless --printers="192.168.1.184:creator-5-pro:12345678:SNCRE51234567" +``` + ### WebUI Server Configuration **`--webui-port=`** @@ -241,25 +251,48 @@ loginctl enable-linger "$USER" # start without an active login session ### Chromium's sandbox on Ubuntu 24.04+ (AppArmor) -**If you installed the `.deb` or `.rpm`, there is nothing to do here** — read this only if the app fails to start. +Ubuntu 23.10 and newer ship `kernel.apparmor_restrict_unprivileged_userns=1`, which stops unprivileged programs from creating user namespaces. Chromium — which Electron is built on — needs either those namespaces or a root-owned `chrome-sandbox` helper in order to sandbox itself. Granting a program permission to use namespaces again requires an AppArmor profile, and installing one requires root. + +**Whether you have to do anything depends on which package you installed.** Jump to the half that applies to you: + +| You installed | Do you need to set anything up? | +| --- | --- | +| `.deb` or `.rpm` | **No.** The profile is installed for you. | +| `.AppImage` | **Only if you want the sandbox on.** It runs unsandboxed otherwise. | + +#### Installed from the `.deb` or `.rpm` — nothing to set up + +The package installs an AppArmor profile to `/etc/apparmor.d/FlashForgeUI` during installation and loads it, because the installer runs as root and can do what an application cannot do for itself. FlashForgeUI then runs fully sandboxed. There are no manual steps. -Those packages install an AppArmor profile to `/etc/apparmor.d/FlashForgeUI` during installation and load it automatically, so FlashForgeUI runs fully sandboxed with no manual steps. To confirm it is active: +To confirm the profile is active: ```bash aa-status | grep FlashForgeUI ``` -Installation deliberately skips the profile on older AppArmor versions that cannot parse it (Ubuntu 22.04 and earlier). That is expected and harmless — those releases do not restrict user namespaces in the first place, so the sandbox works without a profile. You will see a "Skipping the installation of the AppArmor profile" line during install. +On Ubuntu 22.04 and earlier the installer deliberately skips the profile and prints "Skipping the installation of the AppArmor profile". This is expected, not a failure — those releases do not restrict user namespaces, so the sandbox already works without one. + +If FlashForgeUI does not start at all after installing on Ubuntu 24.04+, check that the profile exists and reload it: + +```bash +sudo apparmor_parser -r /etc/apparmor.d/FlashForgeUI +``` + +Launching the app from a terminal will show the underlying Chromium sandbox error if something else is wrong. + +#### Running the `.AppImage` — works out of the box, sandbox off + +An AppImage has no installation step and never runs as root, so it cannot install an AppArmor profile for itself — that is exactly what Ubuntu's restriction is designed to prevent. It also runs from a temporary user-owned mount, so the `chrome-sandbox` helper can never be root-owned either. With neither sandbox available, Chromium would normally refuse to start, and the app would appear to do nothing when launched. -If FlashForgeUI does not start after a `.deb`/`.rpm` install on Ubuntu 24.04+, check whether that profile exists and reload it with `sudo apparmor_parser -r /etc/apparmor.d/FlashForgeUI`. Running the app from a terminal will show the underlying Chromium sandbox error. +FlashForgeUI detects this at launch and starts with `--no-sandbox` so it remains usable. This happens **only** on systems where namespaces are blocked; everywhere else the AppImage runs sandboxed as normal. -#### Why the AppImage is different +If you are happy running the AppImage unsandboxed, you are done — there is nothing to configure. -Ubuntu 23.10 and newer ship `kernel.apparmor_restrict_unprivileged_userns=1`, which stops unprivileged programs from creating user namespaces. Chromium - which Electron is built on - needs either those namespaces or a root-owned `chrome-sandbox` helper to sandbox itself. An AppImage runs from a temporary user-owned mount, so the helper can never be root-owned, and the namespace route is now blocked. With neither available, Chromium refuses to start and the app appears to do nothing when launched. +##### Optional: sandboxing the AppImage yourself -FlashForgeUI detects this at launch and starts with `--no-sandbox` so the app remains usable. This happens **only** when running the AppImage on a system where namespaces are blocked; the `.deb` and `.rpm` packages always run fully sandboxed. +If you would rather keep the sandbox on, you can install a profile by hand. This is optional and unsupported: it is tied to where you keep the AppImage, and it needs root, which is why the app cannot do it for you. -**If you want the AppImage sandboxed as well**, you can install an AppArmor profile yourself. This is optional and unsupported - it depends on where you keep the AppImage and is not something the app can do for you, since granting the permission requires root. Create `/etc/apparmor.d/flashforgeui` with the path to your AppImage: +Create `/etc/apparmor.d/flashforgeui`, replacing the path with the actual location of your AppImage: ``` abi , @@ -277,6 +310,6 @@ Then load it: sudo apparmor_parser -r /etc/apparmor.d/flashforgeui ``` -The profile is tied to that exact path, so moving or renaming the AppImage means updating it. Installing the **`.deb` (or `.rpm`) instead** avoids all of this, which is why those are the recommended downloads on Ubuntu 24.04+. +The profile is tied to that exact path, so moving or renaming the AppImage means updating it and reloading. If that upkeep sounds annoying, installing the `.deb` or `.rpm` avoids the whole problem — which is why those are the recommended downloads on Ubuntu 24.04+. Background: [electron#41066](https://github.com/electron/electron/issues/41066) and [Ubuntu bug #2046844](https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2046844). diff --git a/src/main/ipc/DialogHandlers.ts b/src/main/ipc/DialogHandlers.ts index 08235f1..b8c2f68 100644 --- a/src/main/ipc/DialogHandlers.ts +++ b/src/main/ipc/DialogHandlers.ts @@ -22,7 +22,11 @@ import { ipcMain } from 'electron'; import { getPrinterConnectionManager } from '../managers/ConnectionFlowManager.js'; import { getLoadingManager } from '../managers/LoadingManager.js'; import { createPrinterConnectedWarningDialog } from '../windows/factories/DialogWindowFactory.js'; -import { createConnectChoiceDialog, createInputDialog } from '../windows/WindowFactory.js'; +import { + createConnectChoiceDialog, + createInputDialog, + createManualConnectDialog, +} from '../windows/WindowFactory.js'; import { getWindowManager } from '../windows/WindowManager.js'; /** @@ -37,6 +41,11 @@ export const setupDialogHandlers = (): void => { return createInputDialog(options); }); + // Manual connects collect IP + type + serial + check code in one form + connectionManager.setManualConnectDialogHandler(async (options) => { + return createManualConnectDialog(options); + }); + // Enhanced connect choice dialog initialization const setupConnectChoiceEnhancement = (): void => { // Override the 'open-printer-selection' handler with connect choice dialog @@ -68,19 +77,17 @@ export const setupDialogHandlers = (): void => { const userChoice = await createConnectChoiceDialog({}); if (userChoice === 'enter-ip') { - console.log('User chose to enter IP manually'); - // Show input dialog for IP entry - const ipAddress = await createInputDialog({ - title: 'Enter Printer IP', - message: 'Enter the IP address of your FlashForge printer:', - placeholder: '192.168.1.100', - inputType: 'text', + console.log('User chose to enter printer details manually'); + // Modern printers are typed from their product ID and never TCP-probed, + // so the form also collects the model, serial number and check code. + const details = await createManualConnectDialog({ + title: 'Manual Printer Connection', + message: "Enter your FlashForge printer's details:", }); - if (ipAddress) { - // Connect directly to the provided IP - console.log(`Connecting directly to IP: ${ipAddress}`); - const result = await connectionManager.connectDirectlyToIP(ipAddress); + if (details) { + console.log(`Connecting directly to ${details.ipAddress} (${details.printerType})`); + const result = await connectionManager.connectDirectlyToIP(details); if (result.success) { console.log('Manual IP connection completed successfully'); } else { diff --git a/src/main/managers/ConnectionFlowManager.ts b/src/main/managers/ConnectionFlowManager.ts index a8dea4a..0cef5bb 100644 --- a/src/main/managers/ConnectionFlowManager.ts +++ b/src/main/managers/ConnectionFlowManager.ts @@ -36,6 +36,11 @@ import { SavedPrinterMatch, StoredPrinterDetails, } from '@shared/types/printer.js'; +import { + isModernManualConnectType, + type ManualConnectPrinterType, + type ManualConnectResult, +} from '@shared/types/manual-connect.js'; import { applyPerPrinterDefaults, hasMissingDefaults } from '@shared/utils/printerSettingsDefaults.js'; import { EventEmitter } from 'events'; import { getAutoConnectService } from '../services/AutoConnectService.js'; @@ -56,6 +61,7 @@ import { getConnectionErrorMessage, getDefaultCheckCode, isHttpOnlyModel, + NEW_API_PRODUCT_IDS, shouldPromptForCheckCode, } from '../utils/PrinterUtils.js'; import { getLoadingManager } from './LoadingManager.js'; @@ -71,6 +77,27 @@ interface InputDialogOptions { placeholder?: string; } +// Manual connect dialog options (matching WindowTypes.ManualConnectDialogOptions) +interface ManualConnectDialogOptions { + title?: string; + message?: string; + defaultIpAddress?: string; +} + +/** + * Reverse lookup of {@link NEW_API_PRODUCT_IDS}: the USB product ID for a manually + * selected printer type. Returns undefined for `legacy` (and anything unrecognized), + * which leaves the connection to be typed by the TCP probe as before. + */ +const getManualConnectProductId = (type: ManualConnectPrinterType): number | undefined => { + if (!isModernManualConnectType(type)) { + return undefined; + } + + const entry = Object.entries(NEW_API_PRODUCT_IDS).find(([, modelType]) => modelType === type); + return entry ? Number(entry[0]) : undefined; +}; + /** * Main connection flow orchestrator * Coordinates all services to handle the complete printer connection workflow @@ -97,6 +124,10 @@ export class ConnectionFlowManager extends EventEmitter { private inputDialogHandler: ((options: InputDialogOptions) => Promise) | null = null; + private manualConnectDialogHandler: + | ((options: ManualConnectDialogOptions) => Promise) + | null = null; + /** Map of active connection flows for tracking concurrent connections */ private readonly activeFlows = new Map(); @@ -157,6 +188,13 @@ export class ConnectionFlowManager extends EventEmitter { this.inputDialogHandler = handler; } + /** Set the handler that shows the multi-field manual connect form */ + public setManualConnectDialogHandler( + handler: (options: ManualConnectDialogOptions) => Promise + ): void { + this.manualConnectDialogHandler = handler; + } + /** Generate unique flow ID */ private generateFlowId(): string { this.flowIdCounter++; @@ -525,8 +563,17 @@ export class ConnectionFlowManager extends EventEmitter { } } - /** Connect to a selected printer with proper type detection and pairing */ - private async connectToPrinter(discoveredPrinter: DiscoveredPrinter): Promise { + /** + * Connect to a selected printer with proper type detection and pairing. + * + * @param discoveredPrinter The printer to connect to + * @param options.checkCodeOverride Check code supplied up front (manual connects + * collect it in the connect form, so the user must not be prompted again) + */ + private async connectToPrinter( + discoveredPrinter: DiscoveredPrinter, + options: { checkCodeOverride?: string } = {} + ): Promise { // Start tracking this connection flow const flowId = this.startFlow(); @@ -604,7 +651,10 @@ export class ConnectionFlowManager extends EventEmitter { let checkCode = getDefaultCheckCode(); const savedCheckCode = existingPrinter?.CheckCode ?? this.savedPrinterService.getSavedCheckCode(serialNumber); - if (savedCheckCode) { + if (options.checkCodeOverride) { + console.log('Using check code supplied with the connection request'); + checkCode = options.checkCodeOverride; + } else if (savedCheckCode) { console.log('Using saved check code for known printer:', realPrinterName); checkCode = savedCheckCode; } else if (shouldPromptForCheckCode(familyInfo.is5MFamily, undefined, forceLegacyMode)) { @@ -799,34 +849,26 @@ export class ConnectionFlowManager extends EventEmitter { } } - /** Offer manual IP entry to user */ + /** Offer manual printer entry to the user */ private async offerManualIPEntry(): Promise { - if (!this.inputDialogHandler) { - return { success: false, error: 'Manual IP entry not available - input dialog handler not set' }; + if (!this.manualConnectDialogHandler) { + return { + success: false, + error: 'Manual connection not available - manual connect dialog handler not set', + }; } try { - const ipAddress = await this.inputDialogHandler({ + const details = await this.manualConnectDialogHandler({ title: 'Manual Printer Connection', - message: 'No printers found on network. Enter printer IP address manually:', - defaultValue: '', - inputType: 'text', - placeholder: 'e.g., 192.168.1.100', + message: "No printers found on network. Enter your printer's details manually:", }); - if (!ipAddress) { - return { success: false, error: 'No IP address provided' }; + if (!details) { + return { success: false, error: 'Manual connection cancelled' }; } - // Validate IP address format - const { IPAddressSchema } = await import('../utils/validation.utils.js'); - const validation = IPAddressSchema.safeParse(ipAddress.trim()); - if (!validation.success) { - this.loadingManager.showError('Invalid IP address format', 3000); - return { success: false, error: 'Invalid IP address format' }; - } - - return await this.connectDirectlyToIP(validation.data); + return await this.connectDirectlyToIP(details); } catch (error) { const errorMessage = getConnectionErrorMessage(error); this.loadingManager.showError(`Manual connection failed: ${errorMessage}`, 4000); @@ -834,27 +876,48 @@ export class ConnectionFlowManager extends EventEmitter { } } - /** Connect directly to an IP address */ - public async connectDirectlyToIP(ipAddress: string): Promise { + /** + * Connect directly to a manually entered printer. + * + * Accepts either a bare IP string (legacy callers — the printer is TCP-probed as + * before) or the full details collected by the manual connect dialog. When a + * modern printer type is named, its product ID is passed through so the flow + * types the printer from that ID and skips the legacy TCP probe entirely — which + * is also why the serial number has to come from the user in that case. + */ + public async connectDirectlyToIP( + target: string | ManualConnectResult + ): Promise { + const details: ManualConnectResult = + typeof target === 'string' ? { ipAddress: target, printerType: 'legacy' } : target; + const { ipAddress, printerType, serialNumber, checkCode } = details; + try { this.loadingManager.show({ message: `Connecting to printer at ${ipAddress}...`, canCancel: false }); - // Create a mock discovered printer for the connection process - // The actual name and serial will be determined during temporary connection + // A named modern model resolves to a product ID, which makes the connection + // flow type the printer from that ID instead of probing it over TCP. Legacy + // (and bare-IP) connections carry no product ID and are still probed. + const productId = getManualConnectProductId(printerType); + const mockDiscoveredPrinter: DiscoveredPrinter = { - name: `Printer at ${ipAddress}`, // Temporary name, will be updated - ipAddress: ipAddress, - serialNumber: '', // Will be determined during connection - model: undefined, // Will be determined during connection + name: `Printer at ${ipAddress}`, // Temporary name, replaced once identified + ipAddress, + // Modern printers skip the probe, so the serial cannot be recovered + // automatically — it comes from the connect form. Legacy connects leave it + // blank and take it from the probe. + serialNumber: serialNumber ?? '', + model: undefined, + productId, }; - console.log('Starting direct IP connection to:', ipAddress); + console.log('Starting direct connection to:', { ipAddress, printerType, productId }); // Use the standard connection flow which will: - // 1. Create temporary connection to get printer info - // 2. Extract proper name and serial number - // 3. Establish final connection with correct details - return await this.connectToPrinter(mockDiscoveredPrinter); + // 1. Type the printer (from the product ID, or the TCP probe when absent) + // 2. Resolve the final name and serial number + // 3. Establish the final connection with the correct details + return await this.connectToPrinter(mockDiscoveredPrinter, { checkCodeOverride: checkCode }); } catch (error) { const errorMessage = getConnectionErrorMessage(error); console.error('Direct IP connection failed:', error); @@ -1159,7 +1222,13 @@ export class ConnectionFlowManager extends EventEmitter { * @returns Array of successfully connected contexts with their IDs */ public async connectHeadlessDirect( - printerSpecs: Array<{ ip: string; type: PrinterClientType; checkCode?: string }> + printerSpecs: Array<{ + ip: string; + type: PrinterClientType; + checkCode?: string; + productId?: number; + serialNumber?: string; + }> ): Promise<{ contextId: string; ip: string }[]> { const connectedContexts: { contextId: string; ip: string }[] = []; @@ -1167,14 +1236,19 @@ export class ConnectionFlowManager extends EventEmitter { try { console.log(`[Headless] Connecting directly to ${spec.ip} (${spec.type})`); + // Create mock discovered printer. A product ID (from a creator-5 / + // creator-5-pro TYPE token) makes the temporary connection type the printer + // from that ID and skip the legacy TCP probe — required for the HTTP-only + // Creator 5 series, which cannot answer it. const flowId = this.startFlow(); - // Create mock discovered printer const mockDiscoveredPrinter: DiscoveredPrinter = { name: `Printer at ${spec.ip}`, ipAddress: spec.ip, - serialNumber: '', // Will be determined during connection + // Supplied for models that skip the probe; otherwise resolved by it + serialNumber: spec.serialNumber ?? '', model: undefined, + productId: spec.productId, }; // Determine if this is a 5M family printer @@ -1199,7 +1273,8 @@ export class ConnectionFlowManager extends EventEmitter { ? tempResult.printerInfo.SerialNumber : `Unknown-${Date.now()}`; - const modelType = detectPrinterModelType(tempResult.typeName); + // Prefer the authoritative product ID when the TYPE token supplied one + const modelType = detectPrinterModelTypeFromId(spec.productId, tempResult.typeName); // Preserve existing saved printer settings if available const existingPrinter = this.savedPrinterService.getSavedPrinter(serialNumber); @@ -1214,15 +1289,18 @@ export class ConnectionFlowManager extends EventEmitter { ipAddress: spec.ip, serialNumber: serialNumber, model: tempResult.typeName, + productId: spec.productId, }; - // Establish final connection + // Establish final connection. Passing the resolved model type is what routes + // the HTTP-only Creator 5 series away from the dead legacy TCP path. const connectionResult = await this.connectionService.establishFinalConnection( updatedDiscoveredPrinter, tempResult.typeName, is5MFamily, checkCode, - forceLegacyMode + forceLegacyMode, + modelType ); if (!connectionResult) { diff --git a/src/main/services/ConnectionEstablishmentService.ts b/src/main/services/ConnectionEstablishmentService.ts index a22c8df..fa1b9d5 100644 --- a/src/main/services/ConnectionEstablishmentService.ts +++ b/src/main/services/ConnectionEstablishmentService.ts @@ -29,6 +29,7 @@ import { getConnectionErrorMessage, getModelDisplayName, isHttpOnlyModel, + NEW_API_PRODUCT_IDS, } from '../utils/PrinterUtils.js'; // Connection clients interface for dual API support @@ -91,14 +92,18 @@ export class ConnectionEstablishmentService extends EventEmitter { public async createTemporaryConnection(printer: DiscoveredPrinter): Promise { this.emit('temporary-connection-started', printer); - // HTTP-only models (Creator 5 / 5 Pro) run no legacy TCP server, so the usual - // ~M601/~M115 probe can't work. When discovery's USB product ID identifies such - // a model, synthesize the type info (model name + the serial/name from the - // discovery packet) and skip the TCP probe entirely. + // Any printer whose discovery USB product ID is a known new-API model is typed + // from that ID alone. The same broadcast also carries the serial (0x92) and name + // (0x00), and FiveMClient.initialize() later supplies the authoritative capability + // flags plus reachability — so the legacy ~M601/~M115 probe contributes nothing + // here and is skipped for ALL modern printers (5M / 5M Pro / AD5X / Creator 5 / + // 5 Pro). It is also impossible for the HTTP-only Creator 5 series, which runs no + // TCP server. Printers with no product ID (genuine legacy, or manual/headless + // connects that supplied no model hint) fall through to the TCP probe below. const idModelType = detectPrinterModelTypeFromId(printer.productId, ''); - if (isHttpOnlyModel(idModelType)) { + if (printer.productId !== undefined && printer.productId in NEW_API_PRODUCT_IDS) { const typeName = getModelDisplayName(idModelType); - console.log(`Temporary connection - HTTP-only model detected via product ID: ${typeName}`); + console.log(`Temporary connection - modern model detected via product ID: ${typeName}`); this.emit('printer-type-detected', { typeName, familyInfo: detectPrinterFamily(typeName) }); return { success: true, diff --git a/src/main/utils/HeadlessArguments.ts b/src/main/utils/HeadlessArguments.ts index b80b5a8..5c46b33 100644 --- a/src/main/utils/HeadlessArguments.ts +++ b/src/main/utils/HeadlessArguments.ts @@ -7,7 +7,8 @@ * Examples: * --headless --last-used * --headless --all-saved-printers - * --headless --printers="192.168.1.100:new:12345678,192.168.1.101:legacy" + * --headless --printers="192.168.1.100:new:12345678:SNMOMC1234567,192.168.1.101:legacy" + * --headless --printers="192.168.1.184:creator-5-pro:12345678:SNCRE51234567" * --headless --webui-port=3001 --webui-password=mypassword * --headless --debug --debug-network */ @@ -46,6 +47,19 @@ export interface PrinterSpec { ip: string; type: PrinterClientType; checkCode?: string; + /** + * USB product ID hint for HTTP-only models (Creator 5 series). Set when the + * TYPE token is `creator-5` / `creator-5-pro` so the connection flow types the + * printer from the ID and skips the legacy TCP probe these printers cannot + * answer. + */ + productId?: number; + /** + * Printer serial number. Modern printers authenticate with serial + check code. + * Dual-API models can fall back to the serial reported by the TCP probe; + * HTTP-only models cannot, so it is required for the Creator 5 series. + */ + serialNumber?: string; } /** @@ -126,7 +140,11 @@ export function parseHeadlessArguments(): HeadlessConfig | null { /** * Parse --printers argument into array of PrinterSpec * - * Format: --printers="192.168.1.100:new:12345678,192.168.1.101:legacy" + * Format: --printers="IP:TYPE[:CHECKCODE[:SERIAL]],..." + * e.g. --printers="192.168.1.100:new:12345678:SNMOMC1234567,192.168.1.101:legacy" + * + * TYPE is `new`, `legacy`, `creator-5`, or `creator-5-pro`. The Creator tokens + * mark HTTP-only printers so the connection flow skips the legacy TCP probe. * * @param arg The --printers= argument string * @returns Array of PrinterSpec objects @@ -151,13 +169,21 @@ function parsePrintersArgument(arg: string): PrinterSpec[] { continue; } - const [ip, typeStr, checkCode] = parts; - const type: PrinterClientType = typeStr === 'new' ? 'new' : 'legacy'; + const [ip, typeStr, checkCode, serialNumber] = parts; + // The Creator 5 series is HTTP-only (no legacy TCP server), so the type token + // also carries the model for those printers. All other non-"new" tokens fall + // back to legacy, matching historical behavior. + const normalizedType = typeStr.trim().toLowerCase(); + const isCreator = normalizedType === 'creator-5' || normalizedType === 'creator-5-pro'; + const type: PrinterClientType = normalizedType === 'new' || isCreator ? 'new' : 'legacy'; + const productId = isCreator ? (normalizedType === 'creator-5' ? 40 : 41) : undefined; specs.push({ ip: ip.trim(), type, checkCode: checkCode?.trim(), + productId, + serialNumber: serialNumber?.trim() || undefined, }); } @@ -231,6 +257,15 @@ export function validateHeadlessConfig(config: HeadlessConfig): ValidationResult if (printer.type === 'new' && !printer.checkCode) { errors.push(`Printer ${index + 1}: New printer type requires check code`); } + // HTTP-only models (Creator 5 series) can't be probed over TCP for their + // serial, so it must be supplied. Dual-API models fall back to the probe's + // serial, so it stays optional there for compatibility. + if (printer.productId !== undefined && !printer.serialNumber) { + errors.push( + `Printer ${index + 1}: Creator 5 series requires a serial number ` + + `(format IP:TYPE:CHECKCODE:SERIAL)` + ); + } }); } } diff --git a/src/main/windows/WindowFactory.ts b/src/main/windows/WindowFactory.ts index 2965f2a..952d7cc 100644 --- a/src/main/windows/WindowFactory.ts +++ b/src/main/windows/WindowFactory.ts @@ -71,7 +71,7 @@ */ // Re-export shared types for backward compatibility -export type { InputDialogOptions } from './shared/WindowTypes.js'; +export type { InputDialogOptions, ManualConnectDialogOptions } from './shared/WindowTypes.js'; // Re-export all functions from specialized factory modules to maintain API compatibility @@ -88,6 +88,7 @@ export { export { createConnectChoiceDialog, createInputDialog, + createManualConnectDialog, createMaterialInfoDialog, createMaterialMatchingDialog, createPrinterConnectedWarningDialog, diff --git a/src/main/windows/factories/DialogWindowFactory.ts b/src/main/windows/factories/DialogWindowFactory.ts index 7e2a74c..8c157ae 100644 --- a/src/main/windows/factories/DialogWindowFactory.ts +++ b/src/main/windows/factories/DialogWindowFactory.ts @@ -59,6 +59,7 @@ * - Printer Connected Warning: 450x380 (min 400x350), non-resizable, frameless, transparent * * @exports createInputDialog - Create input dialog for user text input + * @exports createManualConnectDialog - Create the multi-field manual connect form * @exports createMaterialMatchingDialog - Create material matching dialog for printer configuration * @exports createSingleColorConfirmationDialog - Create single color confirmation for print validation * @exports createMaterialInfoDialog - Create material info dialog for slot information @@ -78,10 +79,12 @@ import { setupWindowLifecycle, validateParentWindow, } from '../shared/WindowConfig.js'; +import type { ManualConnectResult } from '@shared/types/manual-connect.js'; import { AutoConnectChoiceDialogData, ConnectChoiceDialogData, InputDialogOptions, + ManualConnectDialogOptions, MaterialMatchingDialogData, PrinterConnectedWarningData, SingleColorConfirmationDialogData, @@ -177,6 +180,89 @@ export const createInputDialog = (options: InputDialogOptions): Promise => { + return new Promise((resolve) => { + const windowManager = getWindowManager(); + const mainWindow = windowManager.getMainWindow(); + + if (!validateParentWindow(mainWindow, 'manual connect dialog')) { + resolve(null); + return; + } + + const dialogId = generateDialogId(); + const responseChannel = createResponseChannelName(dialogId); + let handlerActive = true; + + const manualConnectWindow = createModalWindow( + mainWindow, + WINDOW_SIZES.MANUAL_CONNECT_DIALOG, + createUIPreloadPath('manual-connect-dialog'), + { resizable: true, frame: false } + ); + + const handleResponse = async ( + _event: unknown, + result: ManualConnectResult | null + ): Promise => { + if (!handlerActive) return; + + handlerActive = false; + ipcMain.removeHandler(responseChannel); + + // Shares the input-dialog slot: both are the single modal entry prompt and + // can never be open at the same time. + windowManager.setInputDialogWindow(null); + + // Close immediately to prevent race conditions + if (manualConnectWindow && !manualConnectWindow.isDestroyed()) { + manualConnectWindow.destroy(); + } + + resolve(result); + }; + + ipcMain.handle(responseChannel, handleResponse); + + void loadWindowHTML(manualConnectWindow, 'manual-connect-dialog'); + + manualConnectWindow.webContents.on('did-finish-load', () => { + if (manualConnectWindow && !manualConnectWindow.isDestroyed()) { + manualConnectWindow.webContents.send('manual-connect:init', { + ...options, + responseChannel, + }); + } + }); + + setupWindowLifecycle(manualConnectWindow, () => { + windowManager.setInputDialogWindow(null); + // Window closed without a response - treat as cancelled + if (handlerActive) { + handlerActive = false; + ipcMain.removeHandler(responseChannel); + resolve(null); + } + }); + + setupDevTools(manualConnectWindow); + windowManager.setInputDialogWindow(manualConnectWindow); + }); +}; + /** * Create the material matching dialog window * @param data - Dialog initialization data diff --git a/src/main/windows/shared/WindowTypes.ts b/src/main/windows/shared/WindowTypes.ts index 4e689ce..c67277f 100644 --- a/src/main/windows/shared/WindowTypes.ts +++ b/src/main/windows/shared/WindowTypes.ts @@ -96,6 +96,13 @@ export interface InputDialogOptions { readonly placeholder?: string; } +// Options for the multi-field manual printer-connection dialog +export interface ManualConnectDialogOptions { + readonly title?: string; + readonly message?: string; + readonly defaultIpAddress?: string; +} + // Common window dimension configuration export interface WindowDimensions { readonly width: WindowWidth; @@ -212,6 +219,12 @@ export const WINDOW_SIZES = { minWidth: createWindowMinWidth(380), minHeight: createWindowMinHeight(280), }, + MANUAL_CONNECT_DIALOG: { + width: createWindowWidth(480), + height: createWindowHeight(480), + minWidth: createWindowMinWidth(420), + minHeight: createWindowMinHeight(420), + }, JOB_UPLOADER: { width: createWindowWidth(950), height: createWindowHeight(720), diff --git a/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog-preload.ts b/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog-preload.ts new file mode 100644 index 0000000..5216a60 --- /dev/null +++ b/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog-preload.ts @@ -0,0 +1,74 @@ +/** + * @fileoverview Preload script for the manual printer-connection dialog. + * + * Provides the secure bridge for the multi-field manual connect form (IP address, + * printer type, serial number, check code). Mirrors the input-dialog preload's + * unique-response-channel pattern so several dialogs can be open without their + * results crossing over. + * + * Key exports: + * - ManualConnectDialogAPI: secure API for dialog init and result submission + * - ManualConnectDialogInitOptions: configuration received from the main process + */ + +import { contextBridge, ipcRenderer } from 'electron'; +import type { ManualConnectResult } from '@shared/types/manual-connect.js'; + +// Response channel for this dialog instance, supplied by the main process on init +let responseChannel: string | null = null; + +// Valid channels for security +const validReceiveChannels = ['manual-connect:init', 'theme-changed']; + +/** Initialization payload sent by the main process. */ +export interface ManualConnectDialogInitOptions { + title?: string; + message?: string; + defaultIpAddress?: string; + responseChannel: string; +} + +/** IPC surface exposed to the dialog renderer. */ +export interface ManualConnectDialogAPI { + receive: (channel: string, func: (options: unknown) => void) => void; + submit: (result: ManualConnectResult) => Promise; + cancel: () => Promise; +} + +const invokeResponse = async (payload: ManualConnectResult | null): Promise => { + if (!responseChannel) { + const error = new Error('Manual connect dialog response channel not set!'); + console.error(error.message); + throw error; + } + + try { + await ipcRenderer.invoke(responseChannel, payload); + } catch (error) { + console.error('Failed to send manual connect dialog result:', error); + throw error; + } +}; + +const manualConnectDialogAPI: ManualConnectDialogAPI = { + receive: (channel: string, func: (options: unknown) => void): void => { + if (validReceiveChannels.includes(channel)) { + ipcRenderer.on(channel, (_event, options: ManualConnectDialogInitOptions) => { + if (options?.responseChannel) { + responseChannel = options.responseChannel; + } + func(options); + }); + } + }, + + submit: (result: ManualConnectResult): Promise => invokeResponse(result), + + cancel: (): Promise => invokeResponse(null), +}; + +contextBridge.exposeInMainWorld('api', { + dialog: { + manualConnect: manualConnectDialogAPI, + }, +}); diff --git a/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog-renderer.ts b/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog-renderer.ts new file mode 100644 index 0000000..6404064 --- /dev/null +++ b/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog-renderer.ts @@ -0,0 +1,280 @@ +/** + * @fileoverview Renderer process for the manual printer-connection dialog. + * + * Collects everything a manual connect needs now that modern printers are typed + * from their USB product ID instead of being TCP-probed: IP address, printer type, + * and — for modern models — the serial number and check code the discovery + * broadcast would otherwise have supplied. Legacy selections hide the serial and + * check-code fields since those printers are still probed over TCP. + * + * Key features: + * - Printer-type dropdown driven by the shared MANUAL_CONNECT_PRINTER_TYPES list + * - Per-type field visibility and validation (serial + check code for modern) + * - Inline validation errors, Enter to submit, Escape to cancel + */ + +export {}; + +import type { ThemeColors } from '@shared/types/config.js'; +import { + isModernManualConnectType, + MANUAL_CONNECT_PRINTER_TYPES, + type ManualConnectPrinterType, + type ManualConnectResult, +} from '@shared/types/manual-connect.js'; +import { initializeLucideIconsFromGlobal } from '../shared/lucide.js'; +import { applyDialogTheme } from '../shared/theme-utils.js'; +import type { + ManualConnectDialogAPI, + ManualConnectDialogInitOptions, +} from './manual-connect-dialog-preload.cts'; + +const IPV4_PATTERN = + /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + +interface DialogElements { + readonly title: HTMLElement | null; + readonly message: HTMLElement | null; + readonly ipInput: HTMLInputElement; + readonly typeSelect: HTMLSelectElement; + readonly serialField: HTMLElement; + readonly serialInput: HTMLInputElement; + readonly checkCodeField: HTMLElement; + readonly checkCodeInput: HTMLInputElement; + readonly hint: HTMLElement; + readonly error: HTMLElement; + readonly connectButton: HTMLButtonElement; + readonly cancelButton: HTMLButtonElement; + readonly closeButton: HTMLButtonElement; +} + +const getManualConnectAPI = (): ManualConnectDialogAPI => { + const api = window.api?.dialog?.manualConnect as ManualConnectDialogAPI | undefined; + if (!api) { + throw new Error('[ManualConnectDialog] dialog API bridge is not available'); + } + return api; +}; + +document.addEventListener('DOMContentLoaded', (): void => { + initializeLucideIconsFromGlobal(['x']); + + const elements = resolveElements(); + if (!elements) { + console.error('Manual connect dialog: required DOM elements not found'); + return; + } + + populatePrinterTypes(elements.typeSelect); + applyTypeVisibility(elements); + + const api = getManualConnectAPI(); + + api.receive('manual-connect:init', (data: unknown): void => { + initializeDialog(elements, data as ManualConnectDialogInitOptions); + }); + + api.receive('theme-changed', (data: unknown): void => { + applyDialogTheme(data as ThemeColors); + }); + + setupEventHandlers(elements, api); +}); + +function resolveElements(): DialogElements | null { + const ipInput = document.getElementById('input-ip') as HTMLInputElement | null; + const typeSelect = document.getElementById('input-type') as HTMLSelectElement | null; + const serialField = document.getElementById('field-serial'); + const serialInput = document.getElementById('input-serial') as HTMLInputElement | null; + const checkCodeField = document.getElementById('field-check-code'); + const checkCodeInput = document.getElementById('input-check-code') as HTMLInputElement | null; + const hint = document.getElementById('field-hint'); + const error = document.getElementById('dialog-error'); + const connectButton = document.getElementById('dialog-connect') as HTMLButtonElement | null; + const cancelButton = document.getElementById('dialog-cancel') as HTMLButtonElement | null; + const closeButton = document.getElementById('dialog-close') as HTMLButtonElement | null; + + if ( + !ipInput || + !typeSelect || + !serialField || + !serialInput || + !checkCodeField || + !checkCodeInput || + !hint || + !error || + !connectButton || + !cancelButton || + !closeButton + ) { + return null; + } + + return { + title: document.getElementById('dialog-title'), + message: document.getElementById('dialog-message'), + ipInput, + typeSelect, + serialField, + serialInput, + checkCodeField, + checkCodeInput, + hint, + error, + connectButton, + cancelButton, + closeButton, + }; +} + +function populatePrinterTypes(select: HTMLSelectElement): void { + for (const { value, label } of MANUAL_CONNECT_PRINTER_TYPES) { + const option = document.createElement('option'); + option.value = value; + option.textContent = label; + select.appendChild(option); + } +} + +function initializeDialog(elements: DialogElements, options: ManualConnectDialogInitOptions): void { + if (elements.title && options.title) { + elements.title.textContent = options.title; + } + if (elements.message && options.message) { + elements.message.textContent = options.message; + } + if (options.defaultIpAddress) { + elements.ipInput.value = options.defaultIpAddress; + } + + elements.ipInput.focus(); + if (elements.ipInput.value) { + elements.ipInput.select(); + } +} + +/** Show serial + check code only for modern models; legacy printers are still probed. */ +function applyTypeVisibility(elements: DialogElements): void { + const isModern = isModernManualConnectType(selectedType(elements)); + + elements.serialField.classList.toggle('hidden', !isModern); + elements.checkCodeField.classList.toggle('hidden', !isModern); + elements.hint.classList.toggle('hidden', !isModern); +} + +function selectedType(elements: DialogElements): ManualConnectPrinterType { + return elements.typeSelect.value as ManualConnectPrinterType; +} + +function setupEventHandlers(elements: DialogElements, api: ManualConnectDialogAPI): void { + elements.typeSelect.addEventListener('change', (): void => { + applyTypeVisibility(elements); + clearError(elements); + }); + + elements.connectButton.addEventListener('click', (): void => { + submitDialog(elements, api); + }); + + for (const button of [elements.cancelButton, elements.closeButton]) { + button.addEventListener('click', (): void => { + cancelDialog(api); + }); + } + + // Enter submits from any text field + for (const input of [elements.ipInput, elements.serialInput, elements.checkCodeInput]) { + input.addEventListener('keydown', (event: KeyboardEvent): void => { + if (event.key === 'Enter') { + event.preventDefault(); + submitDialog(elements, api); + } + }); + input.addEventListener('input', (): void => { + input.classList.remove('invalid'); + clearError(elements); + }); + } + + document.addEventListener('keydown', (event: KeyboardEvent): void => { + if (event.key === 'Escape') { + event.preventDefault(); + cancelDialog(api); + } + }); +} + +function submitDialog(elements: DialogElements, api: ManualConnectDialogAPI): void { + const result = validate(elements); + if (!result) { + return; + } + + api.submit(result).catch((error: unknown) => { + console.error('Error submitting manual connect dialog:', error); + }); +} + +/** + * Validate the form, highlighting the first offending field. Returns null when + * the form is not yet submittable. + */ +function validate(elements: DialogElements): ManualConnectResult | null { + clearError(elements); + + const ipAddress = elements.ipInput.value.trim(); + if (!IPV4_PATTERN.test(ipAddress)) { + return failValidation(elements, elements.ipInput, 'Enter a valid IPv4 address.'); + } + + const printerType = selectedType(elements); + + if (!isModernManualConnectType(printerType)) { + return { ipAddress, printerType }; + } + + // Modern printers are typed from their product ID and never TCP-probed, so the + // serial can no longer be recovered automatically — it has to be supplied here. + const serialNumber = elements.serialInput.value.trim(); + if (!serialNumber) { + return failValidation( + elements, + elements.serialInput, + 'Serial number is required for modern printers.' + ); + } + + const checkCode = elements.checkCodeInput.value.trim(); + if (!checkCode) { + return failValidation( + elements, + elements.checkCodeInput, + 'Check code is required for modern printers.' + ); + } + + return { ipAddress, printerType, serialNumber, checkCode }; +} + +function failValidation( + elements: DialogElements, + field: HTMLInputElement, + message: string +): null { + elements.error.textContent = message; + elements.error.hidden = false; + field.classList.add('invalid'); + field.focus(); + return null; +} + +function clearError(elements: DialogElements): void { + elements.error.hidden = true; + elements.error.textContent = ''; +} + +function cancelDialog(api: ManualConnectDialogAPI): void { + api.cancel().catch((error: unknown) => { + console.error('Error cancelling manual connect dialog:', error); + }); +} diff --git a/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog.css b/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog.css new file mode 100644 index 0000000..ad57459 --- /dev/null +++ b/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog.css @@ -0,0 +1,167 @@ +/* Manual Connect Dialog CSS - Rounded Styling Pattern */ +/* Import shared template for consistent styling */ +@import url("../shared/rounded-dialog-template.css"); + +/* Content scrolls if the window is short - the form is taller than a plain input dialog */ +.dialog-content { + overflow-y: auto; +} + +/* Intro message */ +.dialog-message { + font-size: 13px; + line-height: 1.4; + color: var(--theme-text); + margin-bottom: 16px; + text-align: center; + opacity: 0.85; +} + +/* Labelled form rows */ +.field { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 12px; +} + +.field.hidden { + display: none; +} + +.field-label { + flex: 0 0 104px; + font-size: 13px; + color: var(--theme-text); + text-align: right; +} + +.field-input { + flex: 1 1 auto; + min-width: 0; + background-color: var(--surface-elevated); + border: 1px solid var(--border-color); + padding: 8px 10px; + color: var(--theme-text); + font-size: 13px; + font-family: inherit; + border-radius: 6px; + outline: none; + transition: all 0.2s ease; +} + +.field-input:focus { + border-color: var(--theme-primary); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--theme-primary) 30%, transparent); +} + +.field-input::placeholder { + color: color-mix(in srgb, var(--theme-text) 45%, transparent); +} + +/* Invalid field highlight */ +.field-input.invalid { + border-color: var(--theme-error, #e05252); +} + +select.field-input { + cursor: pointer; + appearance: none; + background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), + linear-gradient(135deg, currentColor 50%, transparent 50%); + background-position: calc(100% - 16px) calc(50% + 1px), calc(100% - 11px) calc(50% + 1px); + background-size: 5px 5px, 5px 5px; + background-repeat: no-repeat; + padding-right: 30px; +} + +/* Contextual hint under the form */ +.field-hint { + font-size: 11px; + line-height: 1.4; + color: color-mix(in srgb, var(--theme-text) 65%, transparent); + margin: 4px 0 12px 116px; +} + +.field-hint.hidden { + display: none; +} + +/* Validation error banner */ +.dialog-error { + font-size: 12px; + line-height: 1.4; + color: var(--theme-error, #e05252); + background-color: color-mix(in srgb, var(--theme-error, #e05252) 12%, transparent); + border: 1px solid color-mix(in srgb, var(--theme-error, #e05252) 40%, transparent); + border-radius: 6px; + padding: 8px 10px; + margin-bottom: 12px; + text-align: center; +} + +.dialog-error[hidden] { + display: none; +} + +/* Button container styling */ +.dialog-buttons { + display: flex; + justify-content: center; + gap: 10px; + padding-top: 4px; +} + +/* Button styling - inherit most styles from template */ +.dialog-button { + background-color: var(--theme-primary); + border-color: var(--theme-primary); +} + +.dialog-button:hover { + background-color: var(--theme-primary-hover); + border-color: var(--theme-primary-hover); +} + +/* Cancel button variant */ +.dialog-button.cancel { + background-color: var(--surface-elevated); + border-color: var(--border-color); +} + +.dialog-button.cancel:hover { + background-color: var(--surface-muted); + border-color: var(--border-color-light); +} + +/* Responsive adjustments */ +@media (max-width: 420px) { + .dialog-content { + padding: 20px; + } + + .field { + flex-direction: column; + align-items: stretch; + gap: 4px; + } + + .field-label { + flex: none; + text-align: left; + } + + .field-hint { + margin-left: 0; + } + + .dialog-buttons { + flex-direction: column-reverse; + align-items: center; + gap: 8px; + } + + .dialog-button { + width: 140px; + } +} diff --git a/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog.html b/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog.html new file mode 100644 index 0000000..fc96cc3 --- /dev/null +++ b/src/renderer/src/ui/manual-connect-dialog/manual-connect-dialog.html @@ -0,0 +1,72 @@ + + + + + + + Manual Printer Connection + + + +
+
+
Manual Printer Connection
+ +
+
+
+ Enter your printer's details to connect directly. +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ Modern printers need the serial number and check code shown on the printer's + network/status screen. +
+ + + +
+ + +
+
+
+ + + + diff --git a/src/shared/types/global.d.ts b/src/shared/types/global.d.ts index 9bff95e..e14911f 100644 --- a/src/shared/types/global.d.ts +++ b/src/shared/types/global.d.ts @@ -29,6 +29,7 @@ import type { CameraProxyStatus } from './camera/camera.types.js'; import type { ISettingsAPI, IPrinterSettingsAPI, IAutoUpdateAPI } from '../ui/settings/types/external.js'; import type { PrinterSelectionAPI as PrinterSelectionDialogAPI } from '../ui/printer-selection/printer-selection-preload.js'; import type { DialogAPI as InputDialogAPI } from '../ui/input-dialog/input-dialog-preload.js'; +import type { ManualConnectDialogAPI } from '../ui/manual-connect-dialog/manual-connect-dialog-preload.js'; import type { JobUploaderAPI } from '../ui/job-uploader/job-uploader-preload.js'; import type { AppConfig, ThemeColors } from './config.js'; import type { @@ -223,6 +224,7 @@ interface DialogNamespace { sendCommands?: SendCommandsDialogAPI; status?: StatusDialogAPI; input?: InputDialogAPI; + manualConnect?: ManualConnectDialogAPI; materialInfo?: MaterialInfoDialogAPI; materialMatching?: MaterialMatchingDialogAPI; singleColor?: SingleColorConfirmDialogAPI; diff --git a/src/shared/types/manual-connect.ts b/src/shared/types/manual-connect.ts new file mode 100644 index 0000000..dfffd16 --- /dev/null +++ b/src/shared/types/manual-connect.ts @@ -0,0 +1,57 @@ +/** + * @fileoverview Shared contract for the manual printer-connection dialog. + * + * Manual connects can no longer rely on the legacy TCP probe to discover a modern + * printer's identity: any printer whose model is known up front is typed from its + * USB product ID and never probed. That means the user must supply the details the + * broadcast would otherwise have carried — the model, the serial number and the + * check code — which is what this dialog collects. + * + * Key exports: + * - MANUAL_CONNECT_PRINTER_TYPES: the selectable printer types (dropdown source) + * - ManualConnectPrinterType: union of the selectable type tokens + * - ManualConnectResult: the payload the dialog resolves with + * - isModernManualConnectType(): whether a selection requires serial + check code + * + * Consumed by the dialog renderer (option list + validation) and by the main + * process (`ConnectionFlowManager.connectDirectlyToIP`), which maps the selected + * type to a product ID hint so the connection flow skips the probe. + */ + +/** + * Selectable printer types, in dropdown order. `legacy` is the catch-all for + * older TCP-only printers, which carry no product ID and are still TCP-probed. + * + * The `value` tokens mirror the standalone WebUI's printer-type dropdown so both + * front-ends speak the same vocabulary. + */ +export const MANUAL_CONNECT_PRINTER_TYPES = [ + { value: 'adventurer-5m', label: 'Adventurer 5M' }, + { value: 'adventurer-5m-pro', label: 'Adventurer 5M Pro' }, + { value: 'ad5x', label: 'AD5X' }, + { value: 'creator-5', label: 'Creator 5' }, + { value: 'creator-5-pro', label: 'Creator 5 Pro' }, + { value: 'legacy', label: 'Legacy Printer (Old API)' }, +] as const; + +export type ManualConnectPrinterType = (typeof MANUAL_CONNECT_PRINTER_TYPES)[number]['value']; + +/** + * Result returned by the manual-connect dialog. `null` (rather than this object) + * signals that the user cancelled. + */ +export interface ManualConnectResult { + readonly ipAddress: string; + readonly printerType: ManualConnectPrinterType; + /** Required for modern models; omitted for legacy. */ + readonly serialNumber?: string; + /** Required for modern models; omitted for legacy. */ + readonly checkCode?: string; +} + +/** + * Modern (new-API) selections authenticate with serial + check code and are typed + * from their product ID. Only `legacy` falls back to the TCP probe. + */ +export const isModernManualConnectType = (type: ManualConnectPrinterType): boolean => + type !== 'legacy'; From 79b7b6dc63ce7d2f21c83205aadaa886db81e84e Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Fri, 24 Jul 2026 12:53:25 -0400 Subject: [PATCH 42/93] feat(webui): gate G-code on HTTP-only printers, tighten material-station slot-config --- CHANGELOG.md | 3 + src/main/index.ts | 3 + src/main/webui/schemas/web-api.schemas.ts | 67 +++++++++++++++++++ .../__tests__/printer-status-routes.test.ts | 52 ++++++++++++++ .../server/routes/printer-status-routes.ts | 20 ++---- src/main/webui/static/app.ts | 6 ++ src/main/webui/static/ui/panels.ts | 36 +++++----- src/renderer/src/renderer.ts | 6 ++ .../components/controls-grid/controls-grid.ts | 9 +++ 9 files changed, 173 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30806f9..81e823f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed the calibration dialog being too narrow and its export button rendering comically large. - Fixed see-through popup backgrounds caused by a broken style definition. - Updated the slicer file reader to its latest version. +- The **Home Axes** button is now disabled on HTTP-only printers (Creator 5 / Creator 5 Pro). Raw G-code passthrough — including the `~G28` homing command — runs over the legacy TCP channel those printers don't expose, so it could never have worked on them. G-code availability is now reported to clients via `features.gcodeCommands`, and the same gating covers the desktop controls grid, not just the browser UI. +- Aligned the WebUI request-validation schemas with the standalone project: added `GCodeCommandRequestSchema`, `ModelPreviewRequestSchema`, `CommandDataValidators`, `StandardAPIResponseSchema`, and `SlotConfigRequestSchema`. +- The material-station slot-config endpoint now validates through the shared `SlotConfigRequestSchema` (replacing hand-rolled checks). The schema was tightened to the correct rules — a required material name and a strict 6-digit hex color — matching the AD5X / Creator 5 fixed material and color palettes; the previously permissive 3/6/8-digit hex and nullable material are no longer accepted. ### Diagnostics & Updates - Debug mode now captures all main-process console output (plus renderer log-panel messages) to a new `console-.log`, alongside the targeted `debug-*.log` instrumentation channel. Console logs are also exposed through the WebUI debug routes (list / download / latest). diff --git a/src/main/index.ts b/src/main/index.ts index 86eeb1a..def3fd7 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -799,6 +799,9 @@ const setupConnectionEventForwarding = (): void => { success: true, printerName: eventData.printerDetails?.Name || 'Unknown', modelType: eventData.modelType || 'unknown', + gcodeAvailable: eventData.contextId + ? backendManager.getBackendStatus(eventData.contextId)?.features?.gcodeCommands.available ?? true + : true, contextId: eventData.contextId, serialNumber: eventData.printerDetails?.SerialNumber, timestamp: new Date().toISOString(), diff --git a/src/main/webui/schemas/web-api.schemas.ts b/src/main/webui/schemas/web-api.schemas.ts index 62d5b21..ff0a527 100644 --- a/src/main/webui/schemas/web-api.schemas.ts +++ b/src/main/webui/schemas/web-api.schemas.ts @@ -73,6 +73,14 @@ export const JobStartDataSchema = z.object({ startNow: z.boolean().optional().default(true), }); +/** + * Model preview request data + */ +export const ModelPreviewRequestSchema = z.object({ + filename: z.string().min(1), + requestId: z.string().optional(), +}); + // ============================================================================ // API REQUEST SCHEMAS // ============================================================================ @@ -108,6 +116,16 @@ export const JobStartRequestSchema = z.object({ .optional(), }); +/** + * G-code command request validation + */ +export const GCodeCommandRequestSchema = z.object({ + command: z + .string() + .min(1, 'Command is required') + .regex(/^[A-Z]/, 'G-code commands must start with a letter'), +}); + // ============================================================================ // COMMAND VALIDATION // ============================================================================ @@ -148,10 +166,29 @@ export const PrinterCommandSchema = z.enum([ 'request-model-preview', ]); +/** + * Command-specific data validation + */ +export const CommandDataValidators = { + 'set-bed-temp': TemperatureDataSchema, + 'set-extruder-temp': TemperatureDataSchema, + 'print-file': JobStartDataSchema, + 'request-model-preview': ModelPreviewRequestSchema, +} as const; + // ============================================================================ // RESPONSE VALIDATION // ============================================================================ +/** + * Standard API response validation (for internal use) + */ +export const StandardAPIResponseSchema = z.object({ + success: z.boolean(), + message: z.string().optional(), + error: z.string().optional(), +}); + /** * Printer features validation */ @@ -163,6 +200,13 @@ export const PrinterFeaturesSchema = z.object({ canPause: z.boolean(), canResume: z.boolean(), canCancel: z.boolean(), + gcodeCommands: z + .object({ + available: z.boolean(), + usesLegacyAPI: z.boolean(), + supportedCommands: z.array(z.string()), + }) + .optional(), }); // ============================================================================ @@ -211,6 +255,29 @@ export const SpoolClearRequestSchema = z.object({ contextId: z.string().optional(), }); +/** + * Material station slot configuration request validation. + * + * The client snaps a Spoolman spool's material/color to the printer's fixed + * palette (AD5X vs Creator 5) and sends the already-snapped values here. Slot is + * 1-based (1-4); `materialName` is required (the slot editor always resolves a + * material from the model's fixed palette), and `colorHex` must be a 6-digit hex + * with an optional leading '#'. Both string fields are trimmed before validation. + */ +export const SlotConfigRequestSchema = z.object({ + contextId: z.string().optional(), + slot: z + .number() + .int('slot must be an integer') + .min(1, 'slot must be at least 1') + .max(4, 'slot must be at most 4'), + materialName: z.string().trim().min(1, 'Material name is required'), + colorHex: z + .string() + .trim() + .regex(/^#?[0-9a-fA-F]{6}$/, 'A valid 6-digit hex color is required'), +}); + // ============================================================================ // THEME PROFILE SCHEMAS // ============================================================================ diff --git a/src/main/webui/server/routes/__tests__/printer-status-routes.test.ts b/src/main/webui/server/routes/__tests__/printer-status-routes.test.ts index 045a0fd..15715dd 100644 --- a/src/main/webui/server/routes/__tests__/printer-status-routes.test.ts +++ b/src/main/webui/server/routes/__tests__/printer-status-routes.test.ts @@ -263,4 +263,56 @@ describe('printer-status-routes', () => { expect(response.status).toBe(400); expect(deps.backendManager.configureMaterialSlot).not.toHaveBeenCalled(); }); + + it('rejects a material-station slot write with a non-6-digit hex color', async () => { + const deps = createDependencies({ + backendManager: { + ...createDependencies().backendManager, + isFeatureAvailable: jest + .fn() + .mockImplementation((_contextId: string, feature: string) => feature === 'material-station'), + }, + }); + const server = await startTestServer((app) => { + const router = express.Router(); + registerPrinterStatusRoutes(router, deps); + app.use('/api', router); + }); + + const response = await fetch(`${server.baseUrl}/api/printer/material-station/slot?contextId=context-1`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ slot: 2, materialName: 'PLA', colorHex: '#FFF' }), + }); + await server.close(); + + expect(response.status).toBe(400); + expect(deps.backendManager.configureMaterialSlot).not.toHaveBeenCalled(); + }); + + it('rejects a material-station slot write with a missing material name', async () => { + const deps = createDependencies({ + backendManager: { + ...createDependencies().backendManager, + isFeatureAvailable: jest + .fn() + .mockImplementation((_contextId: string, feature: string) => feature === 'material-station'), + }, + }); + const server = await startTestServer((app) => { + const router = express.Router(); + registerPrinterStatusRoutes(router, deps); + app.use('/api', router); + }); + + const response = await fetch(`${server.baseUrl}/api/printer/material-station/slot?contextId=context-1`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ slot: 2, materialName: null, colorHex: '#F72224' }), + }); + await server.close(); + + expect(response.status).toBe(400); + expect(deps.backendManager.configureMaterialSlot).not.toHaveBeenCalled(); + }); }); diff --git a/src/main/webui/server/routes/printer-status-routes.ts b/src/main/webui/server/routes/printer-status-routes.ts index 3072dbc..ba54988 100644 --- a/src/main/webui/server/routes/printer-status-routes.ts +++ b/src/main/webui/server/routes/printer-status-routes.ts @@ -12,6 +12,7 @@ import { StandardAPIResponse, } from '@shared/types/web-api.types.js'; import type { Response, Router } from 'express'; +import { createValidationError, SlotConfigRequestSchema } from '../../schemas/web-api.schemas.js'; import { toAppError } from '../../../utils/error.utils.js'; import type { AuthenticatedRequest } from '../auth-middleware.js'; import { type RouteDependencies, resolveContext, sendErrorResponse } from './route-helpers.js'; @@ -195,6 +196,7 @@ export function registerPrinterStatusRoutes(router: Router, deps: RouteDependenc ledUsesLegacyAPI: features.ledControl.customControlEnabled || features.ledControl.usesLegacyAPI, hasMultiTool, isCreator5Pro, + gcodeCommands: features.gcodeCommands, }; return res.json({ @@ -245,20 +247,12 @@ export function registerPrinterStatusRoutes(router: Router, deps: RouteDependenc return sendErrorResponse(res, contextResult.statusCode, contextResult.error); } - const body = (req.body ?? {}) as { slot?: unknown; materialName?: unknown; colorHex?: unknown }; - const slot = typeof body.slot === 'number' ? body.slot : Number.parseInt(String(body.slot), 10); - const materialName = typeof body.materialName === 'string' ? body.materialName.trim() : ''; - const colorHex = typeof body.colorHex === 'string' ? body.colorHex.trim() : ''; - - if (!Number.isInteger(slot) || slot < 1 || slot > 4) { - return sendErrorResponse(res, 400, 'Invalid slot number (expected 1-4)'); - } - if (materialName === '') { - return sendErrorResponse(res, 400, 'Material name is required'); - } - if (!/^#?[0-9a-fA-F]{6}$/.test(colorHex)) { - return sendErrorResponse(res, 400, 'A valid 6-digit hex color is required'); + const validation = SlotConfigRequestSchema.safeParse(req.body); + if (!validation.success) { + const validationError = createValidationError(validation.error); + return sendErrorResponse(res, 400, validationError.error); } + const { slot, materialName, colorHex } = validation.data; if (!deps.backendManager.isFeatureAvailable(contextResult.contextId, 'material-station')) { return sendErrorResponse(res, 400, 'Material station not available on this printer'); diff --git a/src/main/webui/static/app.ts b/src/main/webui/static/app.ts index 4eb0f65..7ac571e 100644 --- a/src/main/webui/static/app.ts +++ b/src/main/webui/static/app.ts @@ -161,6 +161,12 @@ export interface PrinterFeatures { ledUsesLegacyAPI?: boolean; // Whether custom LED control is enabled hasMultiTool?: boolean; // Creator 5 series — gates the per-tool temperature card isCreator5Pro?: boolean; // Creator 5 Pro — gates the read-only TVOC display + /** Raw G-code passthrough availability; gates the Home Axes (~G28) button. */ + gcodeCommands?: { + available: boolean; + usesLegacyAPI: boolean; + supportedCommands: readonly string[]; + }; } export interface AD5XToolData { diff --git a/src/main/webui/static/ui/panels.ts b/src/main/webui/static/ui/panels.ts index dcfe9a4..30b7cdd 100644 --- a/src/main/webui/static/ui/panels.ts +++ b/src/main/webui/static/ui/panels.ts @@ -53,10 +53,10 @@ export function updatePrinterStatus(status: PrinterStatus | null): void { state.printerStatus = status; updatePrinterStateCard(status); - const bedTemp = isNaN(status.bedTemperature) ? 0 : Math.round(status.bedTemperature); - const bedTarget = isNaN(status.bedTargetTemperature) ? 0 : Math.round(status.bedTargetTemperature); - const extruderTemp = isNaN(status.nozzleTemperature) ? 0 : Math.round(status.nozzleTemperature); - const extruderTarget = isNaN(status.nozzleTargetTemperature) ? 0 : Math.round(status.nozzleTargetTemperature); + const bedTemp = Number.isNaN(status.bedTemperature) ? 0 : Math.round(status.bedTemperature); + const bedTarget = Number.isNaN(status.bedTargetTemperature) ? 0 : Math.round(status.bedTargetTemperature); + const extruderTemp = Number.isNaN(status.nozzleTemperature) ? 0 : Math.round(status.nozzleTemperature); + const extruderTarget = Number.isNaN(status.nozzleTargetTemperature) ? 0 : Math.round(status.nozzleTargetTemperature); setTextContent('bed-temp', `${bedTemp}°C / ${bedTarget}°C`); setTextContent('extruder-temp', `${extruderTemp}°C / ${extruderTarget}°C`); @@ -64,7 +64,7 @@ export function updatePrinterStatus(status: PrinterStatus | null): void { if (status.jobName) { setTextContent('current-job', status.jobName); - const progress = isNaN(status.progress) ? 0 : status.progress; + const progress = Number.isNaN(status.progress) ? 0 : status.progress; const progressPercent = progress <= 1 ? Math.round(progress * 100) : Math.round(progress); setTextContent('progress-percentage', `${progressPercent}%`); @@ -76,8 +76,8 @@ export function updatePrinterStatus(status: PrinterStatus | null): void { if ( status.currentLayer !== undefined && status.totalLayers !== undefined && - !isNaN(status.currentLayer) && - !isNaN(status.totalLayers) + !Number.isNaN(status.currentLayer) && + !Number.isNaN(status.totalLayers) ) { setTextContent('layer-info', `${status.currentLayer} / ${status.totalLayers}`); } else { @@ -85,9 +85,9 @@ export function updatePrinterStatus(status: PrinterStatus | null): void { } // Elapsed — prefer seconds precision - if (status.elapsedTimeSeconds !== undefined && !isNaN(status.elapsedTimeSeconds)) { + if (status.elapsedTimeSeconds !== undefined && !Number.isNaN(status.elapsedTimeSeconds)) { setTextContent('elapsed-time', formatElapsedSeconds(status.elapsedTimeSeconds)); - } else if (status.timeElapsed !== undefined && !isNaN(status.timeElapsed)) { + } else if (status.timeElapsed !== undefined && !Number.isNaN(status.timeElapsed)) { setTextContent('elapsed-time', formatTime(status.timeElapsed)); } else { setTextContent('elapsed-time', '--:--'); @@ -96,19 +96,19 @@ export function updatePrinterStatus(status: PrinterStatus | null): void { // ETA — prefer firmware string if (status.formattedEta && status.formattedEta !== '--:--') { setTextContent('time-remaining', formatETAFromString(status.formattedEta)); - } else if (status.timeRemaining !== undefined && !isNaN(status.timeRemaining)) { + } else if (status.timeRemaining !== undefined && !Number.isNaN(status.timeRemaining)) { setTextContent('time-remaining', formatETA(status.timeRemaining)); } else { setTextContent('time-remaining', '--:--'); } // Weight and length as separate fields - if (status.estimatedWeight !== undefined && !isNaN(status.estimatedWeight)) { + if (status.estimatedWeight !== undefined && !Number.isNaN(status.estimatedWeight)) { setTextContent('job-weight', `${Math.round(status.estimatedWeight)}g`); } else { setTextContent('job-weight', '--'); } - if (status.estimatedLength !== undefined && !isNaN(status.estimatedLength)) { + if (status.estimatedLength !== undefined && !Number.isNaN(status.estimatedLength)) { setTextContent('job-length', `${status.estimatedLength.toFixed(1)}m`); } else { setTextContent('job-length', '--'); @@ -137,8 +137,8 @@ export function updatePrinterStatus(status: PrinterStatus | null): void { /** `°C / °C`, guarding against NaN readings. */ function formatTempPair(current: number, target: number): string { - const c = isNaN(current) ? 0 : Math.round(current); - const t = isNaN(target) ? 0 : Math.round(target); + const c = Number.isNaN(current) ? 0 : Math.round(current); + const t = Number.isNaN(target) ? 0 : Math.round(target); return `${c}°C / ${t}°C`; } @@ -243,7 +243,7 @@ export function updateTvocDisplay(status: PrinterStatus | null): void { tvocInfo?.classList.remove('hidden'); const tvoc = status?.tvocLevel; - setTextContent('tvoc-status', tvoc !== undefined && !isNaN(tvoc) ? `${Math.round(tvoc)}` : '--'); + setTextContent('tvoc-status', tvoc !== undefined && !Number.isNaN(tvoc) ? `${Math.round(tvoc)}` : '--'); // The Creator 5 Pro exposes a TVOC sensor but no filtration-mode control. const isCreator5Pro = Boolean(state.printerFeatures?.isCreator5Pro); @@ -423,7 +423,11 @@ function updateButtonStates(printerState: string): void { if (recentBtn) recentBtn.disabled = !isReadyForNewJob; if (localBtn) localBtn.disabled = !isReadyForNewJob; - if (homeAxesBtn) homeAxesBtn.disabled = isPrintingActive; + // Home Axes (~G28) is a raw G-code command. HTTP-only printers (Creator 5 + // series) expose no TCP/G-code passthrough, so disable the button while printing + // OR when the active printer explicitly reports G-code commands unavailable. + const gcodeUnavailable = state.printerFeatures?.gcodeCommands?.available === false; + if (homeAxesBtn) homeAxesBtn.disabled = isPrintingActive || gcodeUnavailable; const clearStatusBtn = $('btn-clear-status') as HTMLButtonElement | null; if (clearStatusBtn) clearStatusBtn.disabled = isPrintingActive; diff --git a/src/renderer/src/renderer.ts b/src/renderer/src/renderer.ts index 7137eae..9ae5974 100644 --- a/src/renderer/src/renderer.ts +++ b/src/renderer/src/renderer.ts @@ -149,6 +149,8 @@ interface ActiveRebootInfo { } let activeRebootInfo: ActiveRebootInfo = {}; +/** Whether the active printer supports raw G-code passthrough (gates Home Axes). */ +let activeGcodeAvailable = true; /** Whether a model type supports remote reboot (5M / 5M Pro / AD5X only). */ function isRebootSupportedModel(modelType: string | undefined): boolean { @@ -224,6 +226,7 @@ function handleAllContextsRemoved(): void { // No active context: hide the Reboot item. activeRebootInfo = {}; + activeGcodeAvailable = true; updateRebootAvailability(); if (gridController.areComponentsInitialized()) { @@ -457,6 +460,7 @@ function initializePollingListeners(): void { // Add any other update data fields as needed by components printerState: pollingData.printerStatus?.state, connectionState: pollingData.isConnected, + backendCapabilities: { gcodeAvailable: activeGcodeAvailable }, }; // Update all components with centralized manager @@ -511,6 +515,7 @@ function initializeStateAndEventListeners(): void { printerName: string; modelType: string; backendType?: string; + gcodeAvailable?: boolean; contextId?: string; timestamp: string; }; @@ -532,6 +537,7 @@ function initializeStateAndEventListeners(): void { status: 'connected', }; updateRebootAvailability(); + activeGcodeAvailable = data.gcodeAvailable ?? true; } }); diff --git a/src/renderer/src/ui/components/controls-grid/controls-grid.ts b/src/renderer/src/ui/components/controls-grid/controls-grid.ts index f5b4698..6b7d49d 100644 --- a/src/renderer/src/ui/components/controls-grid/controls-grid.ts +++ b/src/renderer/src/ui/components/controls-grid/controls-grid.ts @@ -232,6 +232,7 @@ export class ControlsGridComponent extends BaseComponent { isLegacyPrinter?: boolean; isActiveJob?: boolean; canControlPrint?: boolean; + gcodeAvailable?: boolean; } = {}; /** @@ -301,6 +302,7 @@ export class ControlsGridComponent extends BaseComponent { isLegacyPrinter: (data.backendCapabilities?.isLegacy as boolean) ?? false, isActiveJob: this.determineActiveJobState(data.printerState), canControlPrint: this.determineControlPrintCapability(data.printerState), + gcodeAvailable: (data.backendCapabilities?.gcodeAvailable as boolean) ?? true, }; // Update internal state @@ -458,6 +460,13 @@ export class ControlsGridComponent extends BaseComponent { // Stop only enabled during controllable print states shouldDisable = !canControlPrint; reason = shouldDisable ? 'Cannot control print' : ''; + } else if (mapping.id === 'btn-home-axes') { + // Home Axes (~G28) is raw G-code. HTTP-only printers (Creator 5 series) + // expose no TCP/G-code passthrough, so disable when gcode is unavailable. + if (this.currentState.gcodeAvailable === false) { + shouldDisable = true; + reason = 'G-code unavailable (HTTP-only printer)'; + } } // Apply button state From e5a8db5ee62f409bf0d69349598f9cd188f2c0fa Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Fri, 24 Jul 2026 17:26:16 -0400 Subject: [PATCH 43/93] docs: migrate docs/README.md to GitHub wiki Deprecate docs/README.md and consolidate user-facing docs into the GitHub wiki. - Delete docs/README.md (315 lines) entirely. - README.md: repoint the install-table "Linux Notes" link to the wiki Auto-Start page. - CLAUDE.md: replace 3 docs/README.md references with wiki links (Auto-Start, Headless Mode, general Wiki). - ai_docs/WEBUI_HEADLESS.md: repoint 2 references to the Headless Mode wiki page. - .claude/commands/bump-version.md: drop the docs/README.md update step and remove its mentions from the example-output lines so the version-bump flow no longer touches the removed file. Consolidates documentation into a single source of truth on the wiki instead of maintaining a duplicate in-repo guide. --- .claude/commands/bump-version.md | 10 +- CLAUDE.md | 6 +- README.md | 2 +- ai_docs/WEBUI_HEADLESS.md | 4 +- docs/README.md | 315 ------------------------------- 5 files changed, 9 insertions(+), 328 deletions(-) delete mode 100644 docs/README.md diff --git a/.claude/commands/bump-version.md b/.claude/commands/bump-version.md index ee1c013..95b85d7 100644 --- a/.claude/commands/bump-version.md +++ b/.claude/commands/bump-version.md @@ -56,10 +56,6 @@ Correct flow: - Use the `mcp__time__get_current_time` MCP tool with timezone `America/New_York` to get accurate timestamp - Format: `**Last Updated:** YYYY-MM-DD HH:mm ET (America/New_York)` - d. **docs/README.md**: - - Update any version references in user-facing documentation - - Update download links similar to main README.md - 5. **Summary**: - Show the user which files were updated - Display old version → new version @@ -71,7 +67,7 @@ Correct flow: ``` Current: 1.0.3-alpha.1 New: 1.0.3-alpha.2 -Updated: package.json, README.md (alpha link), CLAUDE.md timestamp, docs/README.md +Updated: package.json, README.md (alpha link), CLAUDE.md timestamp ``` **Stable Release:** @@ -79,14 +75,14 @@ Updated: package.json, README.md (alpha link), CLAUDE.md timestamp, docs/README. Current: 1.0.3-alpha.5 Confirm: Ready to release 1.0.3 stable? [User confirms] New: 1.0.3 -Updated: package.json, README.md (stable link), CLAUDE.md timestamp, docs/README.md +Updated: package.json, README.md (stable link), CLAUDE.md timestamp ``` **After Stable → Next Alpha:** ``` Current: 1.0.3 New: 1.0.4-alpha.1 -Updated: package.json, README.md (alpha link), CLAUDE.md timestamp, docs/README.md +Updated: package.json, README.md (alpha link), CLAUDE.md timestamp ``` ## Validation diff --git a/CLAUDE.md b/CLAUDE.md index a11eb8f..a57ec4b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -108,7 +108,7 @@ For detailed architectural information, see the comprehensive reference document 15. **Release channel is derived from the `package.json` version**: `electron-builder-config.cjs` parses the prerelease suffix - a `-alpha.N` version yields channel `alpha`/`alpha.yml` (prerelease), a bare `X.Y.Z` yields channel `latest`/`latest.yml` (stable). Bumping the version is all that's needed to flip the channel; don't hardcode it. The release workflow (`.github/workflows/release.yml`, `workflow_dispatch`) reads notes from the matching `## [] - ` CHANGELOG section, and `softprops/action-gh-release` keyed on the tag will publish an existing **draft** of that tag *keeping the draft's body* (it does not overwrite with the templated notes) - so don't pre-create a draft if you want the workflow's templated notes. -16. **WebUI camera streams through an authenticated proxy (single-port)**: browsers must NEVER connect directly to go2rtc's unauthenticated API port (1984). `CameraStreamProxy.ts` (`src/main/webui/server/`) tunnels streams through the authenticated WebUI server at `/api/camera/ws?src=&token=` on the WebUI port; the token is validated against `AuthManager`. For remote/WebUI access, forward the single WebUI port only — do not expose 1984. See `docs/README.md` and issue #76. +16. **WebUI camera streams through an authenticated proxy (single-port)**: browsers must NEVER connect directly to go2rtc's unauthenticated API port (1984). `CameraStreamProxy.ts` (`src/main/webui/server/`) tunnels streams through the authenticated WebUI server at `/api/camera/ws?src=&token=` on the WebUI port; the token is validated against `AuthManager`. For remote/WebUI access, forward the single WebUI port only — do not expose 1984. See the [Auto Start](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Auto-Start) wiki page and issue #76. 17. **Single widget-creation path in `gridController.ts`**: do not duplicate grid-widget factories. The reload/context-switch and palette-add paths must route through the shared `createGridWidget()` + `createComponentForGrid()` primitives used by initial load. A divergent factory omits component cases (material-station, tool-temps, creator5-temperature) and produces blank tiles and missing edit-mode delete (X) buttons. The stale duplicate `createComponentInstance()` was removed in the fix for issue #77. @@ -204,7 +204,7 @@ Currently targets AD5X + Adventurer 5M / 5M Pro only (Creator 5 / Creator 5 Pro - `src/main/utils/HeadlessArguments.ts`, `HeadlessDetection.ts`, `HeadlessLogger.ts`, `src/main/managers/HeadlessManager.ts` - `src/main/webui/server/*` (WebUIManager, AuthManager, WebSocketManager, route modules) + `src/main/webui/static/*` (AppState, Transport, features, grid) -- `docs/README.md` - user-facing headless instructions (keep updated) +- **[Headless Mode](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Headless-Mode)** wiki page - user-facing headless instructions (keep updated) ### Testing & Automation @@ -228,7 +228,7 @@ Currently targets AD5X + Adventurer 5M / 5M Pro only (Creator 5 / Creator 5 Pro ### Other Documentation - **`GEMINI.md`, `QWEN.md`**: Sibling agent guides for cross-AI alignment -- **`docs/README.md`**: User-facing setup + headless instructions (update alongside feature changes) +- **[Wiki](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki)**: User-facing setup + headless instructions (update alongside feature changes) - **`ai_specs/*`**: Authoritative specs for in-flight features; always review before touching scoped areas - **`ai_specs/CAMERA_PRIORITY_SPEC.md`**: Camera proxy + RTSP behavior specification - **`ai_specs/webui-push-notifications.md`**: Upcoming WebUI push feature plan diff --git a/README.md b/README.md index 5fb874f..9028162 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ FlashForgeUI connects directly to your FlashForge printer over your local networ | Step | Instructions | | --- | --- | | **1. Download** | Grab the [latest release](https://github.com/Parallel-7/FlashForgeUI-Electron/releases/latest) for your platform | -| **2. Install** | **Windows:** run the `.exe` installer
**macOS:** open the `.dmg` and drag to Applications
**Linux:** install the `.deb` or `.rpm`, or run the `.AppImage` directly — on Ubuntu 24.04+ prefer the `.deb`, see [Linux Notes](docs/README.md#linux-notes) | +| **2. Install** | **Windows:** run the `.exe` installer
**macOS:** open the `.dmg` and drag to Applications
**Linux:** install the `.deb` or `.rpm`, or run the `.AppImage` directly — on Ubuntu 24.04+ prefer the `.deb`, see [Linux Notes](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Auto-Start) | | **3. Connect** | Launch the app, use auto-discovery or enter your printer's IP, and add the [pairing code](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/1.-Pairing-your-printer) if prompted | | **4. Configure** | Optional: set up [remote access](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/WebUI-Setup), [Discord alerts](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Notifications), [Spoolman](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Spoolman-Integration), and [custom cameras](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Custom-Camera-Setup) | diff --git a/ai_docs/WEBUI_HEADLESS.md b/ai_docs/WEBUI_HEADLESS.md index 6a64523..183869e 100644 --- a/ai_docs/WEBUI_HEADLESS.md +++ b/ai_docs/WEBUI_HEADLESS.md @@ -12,7 +12,7 @@ This document covers headless mode operations and the WebUI server architecture. - `HeadlessManager.initialize()` (invoked from `src/index.ts`) forces `WebUIEnabled`, applies overrides, connects printers (respecting discovery + saved printers), starts the WebUI server, launches polling/camera proxies, and sets up graceful shutdown. -- Headless mode is documented for users in `docs/README.md` (update that doc whenever CLI or defaults change). `DEFAULT_CONFIG.WebUIPort` is **3000**; any mention of 3001 is legacy. +- Headless mode is documented for users in the [Headless Mode](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Headless-Mode) wiki page (update it whenever CLI or defaults change). `DEFAULT_CONFIG.WebUIPort` is **3000**; any mention of 3001 is legacy. - The WebUI server (`src/webui/server/WebUIManager.ts`) wires Express, authentication (`AuthManager`), route registration (`server/routes/*.ts` for camera, contexts, jobs, printer control/status, spoolman, temperature, theme, filtration), and `WebSocketManager` for per-context real-time updates. Routes reuse the same services/IPC calls as the desktop UI—avoid duplicating logic. @@ -165,4 +165,4 @@ class AppState { **Headless & WebUI** - `src/main/utils/HeadlessArguments.ts`, `HeadlessDetection.ts`, `HeadlessLogger.ts`, `src/main/managers/HeadlessManager.ts` - `src/main/webui/server/*` (WebUIManager, AuthManager, WebSocketManager, route modules) + `src/main/webui/static/*` (AppState, Transport, features, grid) -- `docs/README.md` – user-facing headless instructions (keep updated) +- [Headless Mode](https://github.com/Parallel-7/FlashForgeUI-Electron/wiki/Headless-Mode) wiki – user-facing headless instructions (keep updated) diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index fbede55..0000000 --- a/docs/README.md +++ /dev/null @@ -1,315 +0,0 @@ -# FlashForgeUI User Guide - -## Initial Setup -Legacy printers are supported out of the box , as they don't use the new HTTP API. - -For new printers (5M series+), you will need to enable LAN-Only mode to connect with FlashForgeUI - -> Enabling LAN-only mode will *prevent* FlashCloud/PolarCloud from working, but provides the benefit of a true direct-connection to the printer. You will notice faster control and a smoother camera stream when comparing to Orca-FlashForge, or any of their cloud services. - -The LAN-only mode setting is located in the same screen as the pairing code, see below - -## 5M & AD5X Pairing Code -The Adventurer 5M, 5M Pro, and AD5X require a pairing code when connecting for the first time. - -You can find the code in this settings menu on the printer (Printer ID = pairing code) -image - -## Camera Setup -For 5M-series printers, OEM cameras are detected automatically whenever the printer reports a `cameraStreamUrl`. You do not need to enable any custom camera setting for an official FlashForge camera. - -If you disable the printer-side camera in firmware, FlashForgeUI will treat the camera as unavailable until it is re-enabled on the printer. - -For a separate custom RTSP or HTTP camera, enable the custom camera option in settings and paste the full camera URL into the camera URL box. You will then be able to view it from the Desktop and WebUI. - -## Custom LED Setup -For users with an Adventurer 5M or AD5X that have installed custom LEDs , you'll need to enable the "Custom LEDs" option in settings. This tells the program that you've installed your own LEDs, and allows you to control them from the Desktop / WebUI - - -## Headless Mode Usage -For Linux and MacOS, replace `FlashForgeUI.exe` with the correct way to start from the CLI, for your OS. The `--enable-logging` flag is only needed for Windows, or if it's not spawning a new CLI window after starting the program. - -For MacOS, the command structure starts with -```bash -open "/Applications/FlashForgeUI.app/Contents/MacOS/FlashForgeUI" -``` - -For Linux, the command depends on which package you installed. - -Installed from the `.deb` or `.rpm` — the installer puts `FlashForgeUI` on your `PATH`: -```bash -FlashForgeUI --headless -``` - -Running the AppImage — call it by path (make it executable once with `chmod +x` if you have not already): -```bash -./FlashForgeUI-*.AppImage --headless -``` - -Both accept the same flags as the Windows examples below. - -## Starting Headless Mode - -Launch FlashForgeUI with the `--headless` flag: - -```bash -FlashForgeUI.exe --enable-logging --headless -``` - -The WebUI will be accessible at `http://localhost:3000` by default. - -## Command-Line Arguments - -### Core Flags - -**`--headless`** -- Runs without the desktop UI -- Starts the WebUI server automatically -- Required for all headless operations - -### Printer Connection Modes - -**`--last-used`** -- Connects to the last printer you used -```bash -FlashForgeUI.exe --enable-logging --headless --last-used -``` - -**`--all-saved-printers`** -- Connects to all saved printers -- Enables multi-printer mode with dropdown selector -```bash -FlashForgeUI.exe --enable-logging --headless --all-saved-printers -``` - -**`--printers=`** -- Connects to specific printer(s) by IP address and type -- Format: `--printers=":[:[:]],..."` -- Type: `new` (5M family), `legacy` (older models), or `creator-5` / `creator-5-pro` -- Checkcode: Required for all modern types (8-digit code) -- Serial: **Required for `creator-5` / `creator-5-pro`**, optional otherwise - -The Creator 5 series is HTTP-only — it runs no legacy TCP server — so those printers -need the dedicated type token (the generic `new` token triggers a TCP probe they -cannot answer) and their serial number, which cannot be recovered by probing. - -Single printer example: -```bash -FlashForgeUI.exe --enable-logging --headless --printers="192.168.1.100:new:12345678" -``` - -Multiple printers example: -```bash -FlashForgeUI.exe --enable-logging --headless --printers="192.168.1.100:new:12345678,192.168.1.101:legacy" -``` - -Creator 5 Pro example (serial required): -```bash -FlashForgeUI.exe --enable-logging --headless --printers="192.168.1.184:creator-5-pro:12345678:SNCRE51234567" -``` - -### WebUI Server Configuration - -**`--webui-port=`** -- Sets the WebUI server port (default: 3000) -```bash -FlashForgeUI.exe --enable-logging --headless --webui-port=8080 -``` - -**`--webui-password=`** -- Overrides the default WebUI password -```bash -FlashForgeUI.exe --enable-logging --headless --webui-password=mypassword -``` - -### Debug Logging - -**`--debug`** -- Enables debug logging to file -- Logs are saved to timestamped files in the app's logs directory -- Includes verbose application logs, status updates, and general debugging info -- Can be combined with `--debug-network` for comprehensive logging -```bash -FlashForgeUI.exe --enable-logging --headless --last-used --debug -``` - -**`--debug-network`** -- Enables network-specific debug logging -- Requires debug mode to be enabled (via `--debug` flag or the DebugMode config setting) -- Logs connection attempts, failures, polling errors, and disconnections -- Useful for diagnosing printer connectivity issues -```bash -FlashForgeUI.exe --enable-logging --headless --last-used --debug --debug-network -``` - -Debug logs can be downloaded from the WebUI at: -- `/api/debug/logs` - List all debug log files -- `/api/debug/latest` - Download most recent debug log -- `/api/debug/network-logs` - List all network debug log files -- `/api/debug/network-latest` - Download most recent network log - -## Common Usage Examples - -### Single Printer (Last Used) -```bash -FlashForgeUI.exe --enable-logging --headless --last-used -``` - -### Multiple Printers (All Saved) -```bash -FlashForgeUI.exe --enable-logging --headless --all-saved-printers -``` - -### Specific Printer by IP (New API) -```bash -FlashForgeUI.exe --enable-logging --headless --printers="192.168.1.146:new:12345678" -``` - -### Specific Printer by IP (Legacy API) -```bash -FlashForgeUI.exe --enable-logging -headless --printers="192.168.1.100:legacy" -``` - -### Multiple Specific Printers -```bash -FlashForgeUI.exe --enable-logging --headless --printers="192.168.1.146:new:12345678,192.168.1.129:new:87654321" -``` - -### Custom Port and Password -```bash -FlashForgeUI.exe --enable-logging --headless --last-used --webui-port=8080 --webui-password=secret -``` - -## Accessing the WebUI - -Once running, access the WebUI from any browser on your network: - -``` -http://:3000 -``` - -Default password is configured in your application settings (or use `--webui-password=` to override). - -### Remote Access / Port Forwarding - -Everything the WebUI needs - including live camera streams - is served over the single WebUI port (default `3000`). If you expose the WebUI outside your LAN, forward **only** that port. Camera video is tunneled through the authenticated WebUI server, so do **not** forward the internal go2rtc streaming port (`1984`); it has no authentication of its own and should never be reachable from outside your machine's network. - -## Multi-Printer Mode - -When using `--all-saved-printers` or specifying multiple printers with `--printers=`, the WebUI provides: - -- **Printer Selector**: Dropdown to switch between printers -- **Per-Printer Camera**: Each printer gets its own camera stream, served through the WebUI port -- **Independent Control**: Each printer maintains its own state and features - -## Troubleshooting - -### My printer is not being discovered automatically -- If your printer is before the 5M series, automatic discovery won't work. Use the direct IP connection option, and it will be saved for future usage. -- If your printer is 5M series+, first make sure LAN-only mode has been properly enabled. After verifying, make sure your PC and printer are on the same network. Occasionally the printer will not respond to the scan, so simply re-scanning can cause your printer to appear. - -### ETA and/or filament usage is not correct/being reported -- The file has been sliced with OrcaSlicer and lacks the correct (and correct ordering of) metadata. FlashForge printers only "broadcast" this information to the API for files sliced by Orca-FlashForge. Both slicers include the information, but in different formats, and FlashForge printers only look for/accept the format from Orca-FlashForge. -- Please download and set up [this](https://github.com/GhostTypes/orca2flashforge) post-process script -- If you already have a script for MD5 generation, remove it and add `-m` to the end of this. It will generate both the MD5 hash and the corrected metadata. - -## Linux Notes - -### Start with system / Start minimized - -"Start with system" writes a standard freedesktop autostart entry to `~/.config/autostart/flashforgeui.desktop` (or `$XDG_CONFIG_HOME/autostart/` if you set that variable). Every major desktop environment honors it - GNOME, KDE, XFCE, Cinnamon, MATE - so it works the same on any distro. Turning the setting off deletes the file. - -"Start minimized" only applies to sessions the system auto-launched; launching FlashForgeUI yourself always shows the window. - -Be aware that some environments ignore requests from an application to minimize itself. Wayland in particular has no "minimized" window state, so on a Wayland session the window may simply open normally instead of minimizing. Use the tray icon to get back to the window whenever it is out of sight. On GNOME, tray icons require the AppIndicator extension - without it the icon will not appear, though relaunching FlashForgeUI always brings the existing window to the front. - -### Headless start with system - -The "Start with system" setting is part of the desktop app and does not apply to headless mode. To start headless FlashForgeUI at login, create a systemd user service at `~/.config/systemd/user/flashforgeui.service`: - -```ini -[Unit] -Description=FlashForgeUI (headless) -After=network-online.target - -[Service] -Type=simple -ExecStart=/opt/FlashForgeUI/FlashForgeUI --headless -Restart=on-failure - -[Install] -WantedBy=default.target -``` - -Adjust `ExecStart` to match your install (for an AppImage, use the full path to the `.AppImage` file). Then enable it: - -```bash -systemctl --user daemon-reload -systemctl --user enable --now flashforgeui -loginctl enable-linger "$USER" # start without an active login session -``` - -### Chromium's sandbox on Ubuntu 24.04+ (AppArmor) - -Ubuntu 23.10 and newer ship `kernel.apparmor_restrict_unprivileged_userns=1`, which stops unprivileged programs from creating user namespaces. Chromium — which Electron is built on — needs either those namespaces or a root-owned `chrome-sandbox` helper in order to sandbox itself. Granting a program permission to use namespaces again requires an AppArmor profile, and installing one requires root. - -**Whether you have to do anything depends on which package you installed.** Jump to the half that applies to you: - -| You installed | Do you need to set anything up? | -| --- | --- | -| `.deb` or `.rpm` | **No.** The profile is installed for you. | -| `.AppImage` | **Only if you want the sandbox on.** It runs unsandboxed otherwise. | - -#### Installed from the `.deb` or `.rpm` — nothing to set up - -The package installs an AppArmor profile to `/etc/apparmor.d/FlashForgeUI` during installation and loads it, because the installer runs as root and can do what an application cannot do for itself. FlashForgeUI then runs fully sandboxed. There are no manual steps. - -To confirm the profile is active: - -```bash -aa-status | grep FlashForgeUI -``` - -On Ubuntu 22.04 and earlier the installer deliberately skips the profile and prints "Skipping the installation of the AppArmor profile". This is expected, not a failure — those releases do not restrict user namespaces, so the sandbox already works without one. - -If FlashForgeUI does not start at all after installing on Ubuntu 24.04+, check that the profile exists and reload it: - -```bash -sudo apparmor_parser -r /etc/apparmor.d/FlashForgeUI -``` - -Launching the app from a terminal will show the underlying Chromium sandbox error if something else is wrong. - -#### Running the `.AppImage` — works out of the box, sandbox off - -An AppImage has no installation step and never runs as root, so it cannot install an AppArmor profile for itself — that is exactly what Ubuntu's restriction is designed to prevent. It also runs from a temporary user-owned mount, so the `chrome-sandbox` helper can never be root-owned either. With neither sandbox available, Chromium would normally refuse to start, and the app would appear to do nothing when launched. - -FlashForgeUI detects this at launch and starts with `--no-sandbox` so it remains usable. This happens **only** on systems where namespaces are blocked; everywhere else the AppImage runs sandboxed as normal. - -If you are happy running the AppImage unsandboxed, you are done — there is nothing to configure. - -##### Optional: sandboxing the AppImage yourself - -If you would rather keep the sandbox on, you can install a profile by hand. This is optional and unsupported: it is tied to where you keep the AppImage, and it needs root, which is why the app cannot do it for you. - -Create `/etc/apparmor.d/flashforgeui`, replacing the path with the actual location of your AppImage: - -``` -abi , -include - -profile flashforgeui /home/YOUR_USER/Applications/FlashForgeUI.AppImage flags=(unconfined) { - userns, - include if exists -} -``` - -Then load it: - -```bash -sudo apparmor_parser -r /etc/apparmor.d/flashforgeui -``` - -The profile is tied to that exact path, so moving or renaming the AppImage means updating it and reloading. If that upkeep sounds annoying, installing the `.deb` or `.rpm` avoids the whole problem — which is why those are the recommended downloads on Ubuntu 24.04+. - -Background: [electron#41066](https://github.com/electron/electron/issues/41066) and [Ubuntu bug #2046844](https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2046844). From 1eb4108b7466f40d8b311aed93fa52acd6f42ddb Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Fri, 24 Jul 2026 18:16:30 -0400 Subject: [PATCH 44/93] chore(deps): bump @ghosttypes/ff-api to ^1.7.0 for loopback discovery --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index e99ffc6..3528bee 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ } }, "dependencies": { - "@ghosttypes/ff-api": "^1.6.1", + "@ghosttypes/ff-api": "^1.7.0", "@parallel-7/slicer-meta": "1.5.0", "electron-log": "^5.4.3", "electron-updater": "^6.8.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 36be5f6..73c0349 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,8 +33,8 @@ importers: .: dependencies: '@ghosttypes/ff-api': - specifier: ^1.6.1 - version: 1.6.1 + specifier: ^1.7.0 + version: 1.7.0 '@parallel-7/slicer-meta': specifier: 1.5.0 version: 1.5.0 @@ -1101,8 +1101,8 @@ packages: cpu: [x64] os: [win32] - '@ghosttypes/ff-api@1.6.1': - resolution: {integrity: sha512-/WopgepJL0hMojkDkIxpUyd2SiPTaXo5wt6aZJFV7BzkXSnMEAqZmHIaI/DumfAfyvXkcQ0o3Q4iRhBKbULGAA==, tarball: https://npm.pkg.github.com/download/@ghosttypes/ff-api/1.6.1/95687f4d27782db0a171c35a569aff8b93d1a916} + '@ghosttypes/ff-api@1.7.0': + resolution: {integrity: sha512-vFpw0Nc/AlfbHi16QV2H/HbjbsC53pnLPEleKbQJCtQCcis9YsXQtAkCtpywW4LKjBEgutEtu0+HYCAEs0Ch2A==, tarball: https://npm.pkg.github.com/download/@ghosttypes/ff-api/1.7.0/1b32fbd158e52255bb16ae7b8d6d78bf48b244d1} '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -5083,7 +5083,7 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@ghosttypes/ff-api@1.6.1': + '@ghosttypes/ff-api@1.7.0': dependencies: axios: 1.16.1 form-data: 4.0.6 From 94718e313fc970911ce02e41e9e1abc0d609b1c3 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Sun, 26 Jul 2026 14:30:13 -0400 Subject: [PATCH 45/93] chore(release): 1.0.5-alpha.9 with ff-api 1.7.1 --- CHANGELOG.md | 6 +++++- package.json | 4 ++-- pnpm-lock.yaml | 10 +++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81e823f..4c0bc98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [1.0.5-alpha.9] - 2026-07-26 ### Connecting to Printers - Modern printers are now identified from the USB product ID in their discovery broadcast instead of an unauthenticated TCP probe. The probe was previously skipped only for the HTTP-only Creator 5 series; it is now skipped for every modern model (5M, 5M Pro, AD5X, Creator 5, Creator 5 Pro), removing a redundant round trip from every modern connect. The broadcast already carries the serial and name, and the capability flags come from the library after `initialize()`, so the probe had nothing left to contribute. Printers with no product ID — genuine legacy printers, and manual connects that chose "Legacy Printer" — are still probed as before. @@ -48,8 +48,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The AppImage now detects when it has no usable sandbox and falls back to `--no-sandbox` so it still launches on Ubuntu 24.04+. The `.deb`/`.rpm` packages are unaffected and remain fully sandboxed; on Ubuntu 24.04+ they are the recommended download. - Documented Linux autostart behavior, the sandbox situation, and headless start-at-boot via a systemd user unit in the user guide. +### Documentation +- Moved the project documentation from `docs/README.md` into the GitHub wiki. The in-repo copy was removed, and the references that pointed at it (the top-level README, the headless-WebUI guide, the version-bump command, and CLAUDE.md) were updated to the wiki. + ### Dependencies - Patched all eight open Dependabot security advisories (#190–#199): bumped `js-yaml` and `tar`, and added overrides for `shell-quote` (critical), `form-data`, and `esbuild`; bumped `vite`, `tsx`, and `@babel/core`. No application source changes. +- Bumped `@ghosttypes/ff-api` to `^1.7.1` for proper loopback-address printer discovery, and for the Material Station capability fix: `FFMachineInfo.HasMatlStation` was a raw copy of an AD5X-only `/detail` field that the Creator 5 series never sends, so it arrived `undefined` on a Creator 5 Pro with four loaded slots. The desktop app gates the material station on `MatlStationInfo` rather than that flag, so nothing here was affected, but 1.7.0 should not ship in a new build. ## [1.0.5-alpha.8] - 2026-07-05 diff --git a/package.json b/package.json index 3528bee..6f2b41d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "FlashForgeUI", "productName": "FlashForgeUI", - "version": "1.0.5-alpha.8", + "version": "1.0.5-alpha.9", "packageManager": "pnpm@10.23.0", "description": "Monitoring and Control software for FlashForge printers", "main": "out/main/index.js", @@ -90,7 +90,7 @@ } }, "dependencies": { - "@ghosttypes/ff-api": "^1.7.0", + "@ghosttypes/ff-api": "^1.7.1", "@parallel-7/slicer-meta": "1.5.0", "electron-log": "^5.4.3", "electron-updater": "^6.8.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 73c0349..2c37f8b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,8 +33,8 @@ importers: .: dependencies: '@ghosttypes/ff-api': - specifier: ^1.7.0 - version: 1.7.0 + specifier: ^1.7.1 + version: 1.7.1 '@parallel-7/slicer-meta': specifier: 1.5.0 version: 1.5.0 @@ -1101,8 +1101,8 @@ packages: cpu: [x64] os: [win32] - '@ghosttypes/ff-api@1.7.0': - resolution: {integrity: sha512-vFpw0Nc/AlfbHi16QV2H/HbjbsC53pnLPEleKbQJCtQCcis9YsXQtAkCtpywW4LKjBEgutEtu0+HYCAEs0Ch2A==, tarball: https://npm.pkg.github.com/download/@ghosttypes/ff-api/1.7.0/1b32fbd158e52255bb16ae7b8d6d78bf48b244d1} + '@ghosttypes/ff-api@1.7.1': + resolution: {integrity: sha512-sU6KRZ1aMlL21r95GAQWyd9JfzSNDbLSzIG2bjAWQnFLM9Fh7T3cgJL3aQo3Qxyj4aZGytx8uSdZBp9izK9ORQ==, tarball: https://npm.pkg.github.com/download/@ghosttypes/ff-api/1.7.1/a5ed0ac5a998c8fe0cfad9fea61233d1eb4e7448} '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -5083,7 +5083,7 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@ghosttypes/ff-api@1.7.0': + '@ghosttypes/ff-api@1.7.1': dependencies: axios: 1.16.1 form-data: 4.0.6 From 507885565c119471acb8a933daf488087ffe0da1 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Fri, 31 Jul 2026 00:20:48 -0400 Subject: [PATCH 46/93] ci: gate releases and main/alpha pushes on type-check, lint, and tests; fix undefined isAD5X in job uploader --- .github/workflows/ci.yml | 57 +++++++++++++++++++ .github/workflows/release.yml | 43 ++++++++++++++ .../ui/job-uploader/job-uploader-renderer.ts | 6 +- 3 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..80873dd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,57 @@ +name: CI + +on: + push: + branches: [main, alpha] + pull_request: + branches: [main, alpha] + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + verify: + name: Type-check, lint, build, test + runs-on: ubuntu-latest + steps: + - name: Checkout FlashForgeUI + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 10.23.0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'pnpm' + + - name: Configure GitHub Packages Authentication + shell: bash + run: | + echo "@ghosttypes:registry=https://npm.pkg.github.com" >> .npmrc + echo "@parallel-7:registry=https://npm.pkg.github.com" >> .npmrc + echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> .npmrc + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies + shell: bash + run: pnpm install --frozen-lockfile + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Type check + run: pnpm type-check + + - name: Lint + run: pnpm lint + + - name: Build (main + renderer + webui) + run: pnpm build + + - name: Unit tests + run: pnpm test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3ff10b4..ba902e9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,50 @@ on: default: false jobs: + verify: + name: Verify (type-check, lint, test) + runs-on: ubuntu-latest + steps: + - name: Checkout FlashForgeUI + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 10.23.0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'pnpm' + + - name: Configure GitHub Packages Authentication + shell: bash + run: | + echo "@ghosttypes:registry=https://npm.pkg.github.com" >> .npmrc + echo "@parallel-7:registry=https://npm.pkg.github.com" >> .npmrc + echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> .npmrc + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies + shell: bash + run: pnpm install --frozen-lockfile + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Type check + run: pnpm type-check + + - name: Lint + run: pnpm lint + + - name: Unit tests + run: pnpm test + build_and_release: + needs: verify runs-on: ${{ matrix.os }} strategy: fail-fast: false diff --git a/src/renderer/src/ui/job-uploader/job-uploader-renderer.ts b/src/renderer/src/ui/job-uploader/job-uploader-renderer.ts index 8874a2b..d66ae7d 100644 --- a/src/renderer/src/ui/job-uploader/job-uploader-renderer.ts +++ b/src/renderer/src/ui/job-uploader/job-uploader-renderer.ts @@ -434,12 +434,12 @@ async function handleUploadJob(elements: DialogElements, api: JobUploaderAPI): P console.error('AD5X upload failed:', error); alert(`Upload failed: ${error instanceof Error ? error.message : String(error)}`); } - } else if (isAD5X && !is3MF) { + } else if (hasMaterialStation && !is3MF) { // This should not happen due to earlier validation, but safety check - alert('AD5X printers only support 3MF files. Please select a valid 3MF file.'); + alert('This printer only supports 3MF files. Please select a valid 3MF file.'); return; } else { - // Use regular upload for non-AD5X printers or non-3MF files + // Use regular upload for printers without a material station const payload: UploadJobPayload = { filePath: currentFilePath, startNow: elements.startNowCheckbox?.checked || false, From 39e09f3ab48e232e3208c9da9dad82453d6d6307 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Fri, 31 Jul 2026 00:42:21 -0400 Subject: [PATCH 47/93] fix(test): close keep-alive sockets in the route test server and run CI on node 22 --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- src/main/webui/server/routes/test-server.ts | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80873dd..6115b68 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 22 cache: 'pnpm' - name: Configure GitHub Packages Authentication diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ba902e9..361066e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,7 +28,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 22 cache: 'pnpm' - name: Configure GitHub Packages Authentication diff --git a/src/main/webui/server/routes/test-server.ts b/src/main/webui/server/routes/test-server.ts index f8073d7..af87ec4 100644 --- a/src/main/webui/server/routes/test-server.ts +++ b/src/main/webui/server/routes/test-server.ts @@ -32,6 +32,10 @@ export async function startTestServer(configureApp: (app: express.Application) = baseUrl: `http://127.0.0.1:${port}`, async close() { await new Promise((resolve, reject) => { + // undici (global fetch) holds its sockets open with keep-alive. Node 19+ + // drops idle connections on close(), but Node 18 waits for the 5s + // keep-alive timeout, which stalls the closing test past Jest's limit. + server.closeAllConnections?.(); server.close((error) => { if (error) { reject(error); From 9d9904803d519a3b0bda9d040467281d97afdf9c Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Fri, 31 Jul 2026 00:42:28 -0400 Subject: [PATCH 48/93] ci: build release artifacts on node 22 to match electron 39 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 361066e..c911c36 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,7 +62,7 @@ jobs: fail-fast: false matrix: os: [windows-latest, macos-latest, ubuntu-latest] - node-version: [18] # LTS version, good for Electron + node-version: [22] # matches the Node runtime Electron 39 bundles steps: - name: Checkout FlashForgeUI From d80e4a110b1b2124e220282d5e58767286990f05 Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Fri, 31 Jul 2026 00:49:14 -0400 Subject: [PATCH 49/93] chore(release): 1.0.5-alpha.10 hotfix for job uploader --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c0bc98..2d9d296 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.5-alpha.10] - 2026-07-31 + +Hotfix for a crash in the job uploader introduced in 1.0.5-alpha.9. + +### Job Uploader +- Fixed pressing **OK** doing nothing on printers without a material station. The AD5X-only file-type check was generalized to cover the Creator 5 series in alpha.9, but one branch still referenced the removed `isAD5X` variable, so confirming any upload threw `ReferenceError: isAD5X is not defined` and the job was never sent. The safety check now uses the material-station result, and its message no longer names the AD5X specifically since the branch also covers the Creator 5 / Creator 5 Pro. + +### Build & CI +- Added a CI workflow that type-checks, lints, builds, and runs the unit tests on every push and pull request to `main` and `alpha`, and gated the release workflow behind the same checks. The alpha.9 crash was a plain type error that `tsc --noEmit` would have caught before packaging. +- CI and release builds now run on Node 22, matching the Node runtime bundled with Electron 39 (previously Node 18, which is end-of-life). +- Fixed the WebUI route tests leaving keep-alive sockets open when closing their fixture servers, which stalled each test for the full keep-alive timeout on Node 18. + ## [1.0.5-alpha.9] - 2026-07-26 ### Connecting to Printers diff --git a/package.json b/package.json index 6f2b41d..53b4d08 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "FlashForgeUI", "productName": "FlashForgeUI", - "version": "1.0.5-alpha.9", + "version": "1.0.5-alpha.10", "packageManager": "pnpm@10.23.0", "description": "Monitoring and Control software for FlashForge printers", "main": "out/main/index.js", From 6220f6d08bed4cfe540693e4991515d3c85e2f8e Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:16:37 -0400 Subject: [PATCH 50/93] test(e2e): rebuild the Electron suite --- .github/workflows/ci.yml | 66 + .gitignore | 1 + package.json | 11 +- pnpm-lock.yaml | 10 +- scripts/run-playwright-electron-discord.cjs | 61 + scripts/run-playwright-electron-emulator.cjs | 25 +- scripts/run-playwright-electron-hardware.cjs | 37 +- scripts/run-playwright-electron-live.cjs | 31 - src/main/printer-backends/AD5XBackend.ts | 7 +- src/main/printer-backends/Creator5Backend.ts | 7 +- .../utils/__tests__/materialColor.test.ts | 92 + src/shared/utils/materialColor.ts | 57 + tests/e2e/electron/desktop-emulator.spec.ts | 1592 -- tests/e2e/electron/desktop-smoke.spec.ts | 63 - tests/e2e/electron/pages/connect-dialogs.ts | 213 + tests/e2e/electron/pages/job-dialogs.ts | 260 + tests/e2e/electron/pages/main-window.ts | 161 + tests/e2e/electron/specs/connect.spec.ts | 129 + tests/e2e/electron/specs/led.spec.ts | 70 + .../e2e/electron/specs/multi-printer.spec.ts | 120 + .../e2e/electron/specs/sftp-roundtrip.spec.ts | 129 + tests/e2e/electron/specs/upload.spec.ts | 155 + tests/e2e/electron/support/electron-app.ts | 272 + tests/e2e/electron/support/fixtures.ts | 73 + tests/e2e/electron/support/hardware-config.ts | 247 + tests/e2e/electron/support/printer-client.ts | 177 + tests/e2e/electron/support/printer-target.ts | 260 + tests/e2e/electron/support/sftp.ts | 114 + tests/e2e/electron/support/ssh2-shim.d.ts | 35 + tests/e2e/electron/support/track.ts | 168 + .../fixtures/print-files/ad5x-multi-tool.3mf | Bin 0 -> 842441 bytes .../fixtures/print-files/ad5x-single-tool.3mf | Bin 0 -> 664764 bytes .../adventurer5m-single-color.gcode | 21227 ++++++++++++++++ tsconfig.e2e.json | 16 + 34 files changed, 24155 insertions(+), 1731 deletions(-) create mode 100644 scripts/run-playwright-electron-discord.cjs delete mode 100644 scripts/run-playwright-electron-live.cjs create mode 100644 src/shared/utils/__tests__/materialColor.test.ts create mode 100644 src/shared/utils/materialColor.ts delete mode 100644 tests/e2e/electron/desktop-emulator.spec.ts delete mode 100644 tests/e2e/electron/desktop-smoke.spec.ts create mode 100644 tests/e2e/electron/pages/connect-dialogs.ts create mode 100644 tests/e2e/electron/pages/job-dialogs.ts create mode 100644 tests/e2e/electron/pages/main-window.ts create mode 100644 tests/e2e/electron/specs/connect.spec.ts create mode 100644 tests/e2e/electron/specs/led.spec.ts create mode 100644 tests/e2e/electron/specs/multi-printer.spec.ts create mode 100644 tests/e2e/electron/specs/sftp-roundtrip.spec.ts create mode 100644 tests/e2e/electron/specs/upload.spec.ts create mode 100644 tests/e2e/electron/support/electron-app.ts create mode 100644 tests/e2e/electron/support/fixtures.ts create mode 100644 tests/e2e/electron/support/hardware-config.ts create mode 100644 tests/e2e/electron/support/printer-client.ts create mode 100644 tests/e2e/electron/support/printer-target.ts create mode 100644 tests/e2e/electron/support/sftp.ts create mode 100644 tests/e2e/electron/support/ssh2-shim.d.ts create mode 100644 tests/e2e/electron/support/track.ts create mode 100644 tests/fixtures/print-files/ad5x-multi-tool.3mf create mode 100644 tests/fixtures/print-files/ad5x-single-tool.3mf create mode 100644 tests/fixtures/print-files/adventurer5m-single-color.gcode create mode 100644 tsconfig.e2e.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6115b68..f56f06f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,3 +55,69 @@ jobs: - name: Unit tests run: pnpm test + + e2e-emulator: + name: E2E (emulator track) + runs-on: ubuntu-latest + needs: verify + steps: + - name: Checkout FlashForgeUI + uses: actions/checkout@v4 + + # The emulator lives in a separate public repo and provides the printers this + # track drives, so no real hardware is needed. + - name: Checkout flashforge-emulator-v2 + uses: actions/checkout@v4 + with: + repository: GhostTypes/flashforge-emulator-v2 + path: emulator + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 10.23.0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'pnpm' + + - name: Configure GitHub Packages Authentication + shell: bash + run: | + echo "@ghosttypes:registry=https://npm.pkg.github.com" >> .npmrc + echo "@parallel-7:registry=https://npm.pkg.github.com" >> .npmrc + echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> .npmrc + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies + shell: bash + run: pnpm install --frozen-lockfile + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install emulator dependencies + working-directory: emulator + run: npm ci + + - name: Install Playwright system dependencies + run: pnpm exec playwright install-deps chromium + + # The suite drives a real Electron window, so CI needs a virtual display. + - name: Run emulator E2E track + run: xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" pnpm test:e2e:electron:emulator + env: + FF_EMULATOR_ROOT: ${{ github.workspace }}/emulator + + - name: Upload Playwright artifacts + if: failure() + uses: actions/upload-artifact@v4 + with: + name: playwright-emulator-artifacts + path: | + test-results/ + playwright-report/ + retention-days: 7 + if-no-files-found: ignore diff --git a/.gitignore b/.gitignore index f493041..49abca3 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,7 @@ temp/ # Playwright test artifacts test-results/ +playwright-report/ # Editor directories and files .vscode/ diff --git a/package.json b/package.json index 53b4d08..629cfaa 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "find:window": "ts-node --esm scripts/find-window-usage.ts", "specs:list": "tsx scripts/list-specs.ts", "clean": "rimraf out dist \"NVIDIA Corporation\"", - "type-check": "pnpm exec tsc --noEmit", + "type-check": "pnpm exec tsc --noEmit && pnpm exec tsc --noEmit -p tsconfig.e2e.json", "test": "jest", "test:all": "npm run test && npm run test:e2e", "test:watch": "jest --watch", @@ -48,12 +48,9 @@ "test:e2e": "npm run build:webui && playwright test", "test:e2e:electron": "npm run build && playwright test -c playwright.electron.config.ts", "test:e2e:electron:emulator": "node scripts/run-playwright-electron-emulator.cjs", - "test:e2e:electron:emulator:legacy": "node scripts/run-playwright-electron-emulator.cjs --grep=Adventurer", - "test:e2e:electron:emulator:legacy-multi": "node scripts/run-playwright-electron-emulator.cjs --grep=A3.*A4.*both", - "test:e2e:electron:emulator:modern-multi": "node scripts/run-playwright-electron-emulator.cjs --grep=separate.*contexts", - "test:e2e:electron:emulator:smoke": "node scripts/run-playwright-electron-emulator.cjs tests/e2e/electron/desktop-smoke.spec.ts", "test:e2e:electron:hardware": "node scripts/run-playwright-electron-hardware.cjs", - "test:e2e:electron:live": "node scripts/run-playwright-electron-live.cjs", + "test:e2e:electron:discord": "node scripts/run-playwright-electron-discord.cjs", + "test:pre-release": "npm run type-check && npm run lint && npm run test && npm run test:e2e:electron:hardware", "full-check": "npm run type-check && npm run lint", "audit:dead-code": "ts-node --esm scripts/audit-dead-code.ts" }, @@ -90,7 +87,7 @@ } }, "dependencies": { - "@ghosttypes/ff-api": "^1.7.1", + "@ghosttypes/ff-api": "^1.8.0", "@parallel-7/slicer-meta": "1.5.0", "electron-log": "^5.4.3", "electron-updater": "^6.8.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2c37f8b..570b918 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,8 +33,8 @@ importers: .: dependencies: '@ghosttypes/ff-api': - specifier: ^1.7.1 - version: 1.7.1 + specifier: ^1.8.0 + version: 1.8.0 '@parallel-7/slicer-meta': specifier: 1.5.0 version: 1.5.0 @@ -1101,8 +1101,8 @@ packages: cpu: [x64] os: [win32] - '@ghosttypes/ff-api@1.7.1': - resolution: {integrity: sha512-sU6KRZ1aMlL21r95GAQWyd9JfzSNDbLSzIG2bjAWQnFLM9Fh7T3cgJL3aQo3Qxyj4aZGytx8uSdZBp9izK9ORQ==, tarball: https://npm.pkg.github.com/download/@ghosttypes/ff-api/1.7.1/a5ed0ac5a998c8fe0cfad9fea61233d1eb4e7448} + '@ghosttypes/ff-api@1.8.0': + resolution: {integrity: sha512-P6EzZxoROOQQ9qQDNPXj+LXK4mJu0WnfTpNXD/qNnZQTSRYD9xlrJhyeL3gzIHYkIC1eSFOj4SryZCuv4/um/w==, tarball: https://npm.pkg.github.com/download/@ghosttypes/ff-api/1.8.0/b3ef55a7e71631aefe03333c9768f27689ac3825} '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -5083,7 +5083,7 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@ghosttypes/ff-api@1.7.1': + '@ghosttypes/ff-api@1.8.0': dependencies: axios: 1.16.1 form-data: 4.0.6 diff --git a/scripts/run-playwright-electron-discord.cjs b/scripts/run-playwright-electron-discord.cjs new file mode 100644 index 0000000..0c4c4f3 --- /dev/null +++ b/scripts/run-playwright-electron-discord.cjs @@ -0,0 +1,61 @@ +#!/usr/bin/env node + +/** + * @fileoverview Wrapper script that builds FlashForgeUI and then runs the guarded + * Electron Discord notification validation against a real printer. + * + * Separate from the main hardware track (run-playwright-electron-hardware.cjs): this + * one drives a single opt-in spec that posts to a live Discord webhook, so it stays + * behind explicit IP/check-code environment variables rather than the shared + * hardware-printers config. + */ + +const { spawnSync } = require('node:child_process'); + +const requiredEnvNames = ['FFUI_E2E_AD5X_IP', 'FFUI_E2E_AD5X_CHECK_CODE']; + +for (const name of requiredEnvNames) { + if (!process.env[name] || process.env[name].trim().length === 0) { + console.error(`[e2e:electron:hardware] Missing required environment variable: ${name}`); + process.exit(1); + } +} + +const env = { + ...process.env, + FFUI_E2E_HARDWARE: '1', +}; + +const passthroughArgs = process.argv.slice(2); + +const buildResult = spawnSync('pnpm', ['run', 'build'], { + stdio: 'inherit', + env, + shell: process.platform === 'win32', + windowsHide: true, +}); + +if (buildResult.status !== 0) { + process.exit(buildResult.status ?? 1); +} + +const testResult = spawnSync( + 'pnpm', + [ + 'exec', + 'playwright', + 'test', + '-c', + 'playwright.electron.config.ts', + 'tests/e2e/electron/discord-hardware.spec.ts', + ...passthroughArgs, + ], + { + stdio: 'inherit', + env, + shell: process.platform === 'win32', + windowsHide: true, + } +); + +process.exit(testResult.status ?? 1); diff --git a/scripts/run-playwright-electron-emulator.cjs b/scripts/run-playwright-electron-emulator.cjs index 0672839..0204181 100644 --- a/scripts/run-playwright-electron-emulator.cjs +++ b/scripts/run-playwright-electron-emulator.cjs @@ -1,8 +1,15 @@ #!/usr/bin/env node /** - * @fileoverview Wrapper script that builds FlashForgeUI and then runs the Electron Playwright - * suite against the external flashforge-emulator-v2 repository. + * @fileoverview Builds FlashForgeUI and runs the Electron E2E suite against the + * emulator track. + * + * The emulator track boots flashforge-emulator-v2 instances, so it needs no printers on + * the network and is the track CI runs. The emulator repo is external; point + * FF_EMULATOR_ROOT at it if it does not sit beside this checkout. + * + * Extra arguments are forwarded to Playwright, e.g. + * pnpm test:e2e:electron:emulator specs/led.spec.ts */ const { existsSync } = require('node:fs'); @@ -13,8 +20,7 @@ const defaultEmulatorRoot = path.resolve(process.cwd(), '..', 'flashforge-emulat const env = { ...process.env, - FFUI_E2E_EMULATOR: '1', - FFUI_E2E_EMULATOR_DISCOVERY: process.env.FFUI_E2E_EMULATOR_DISCOVERY || '1', + FFUI_E2E_TRACK: 'emulator', FF_EMULATOR_ROOT: process.env.FF_EMULATOR_ROOT || defaultEmulatorRoot, }; @@ -24,6 +30,7 @@ if (!existsSync(emulatorPackageJson)) { console.error('[e2e:electron:emulator] Set FF_EMULATOR_ROOT to the flashforge-emulator-v2 repo path.'); process.exit(1); } + const passthroughArgs = process.argv.slice(2); const buildResult = spawnSync('pnpm', ['run', 'build'], { @@ -39,12 +46,12 @@ if (buildResult.status !== 0) { const testResult = spawnSync( 'pnpm', - ['exec', 'playwright', 'test', '-c', 'playwright.electron.config.ts', ...passthroughArgs], + ['exec', 'playwright', 'test', '-c', 'playwright.electron.config.ts', 'tests/e2e/electron/specs', ...passthroughArgs], { - stdio: 'inherit', - env, - shell: process.platform === 'win32', - windowsHide: true, + stdio: 'inherit', + env, + shell: process.platform === 'win32', + windowsHide: true, } ); diff --git a/scripts/run-playwright-electron-hardware.cjs b/scripts/run-playwright-electron-hardware.cjs index 67afb7d..fc6b1f5 100644 --- a/scripts/run-playwright-electron-hardware.cjs +++ b/scripts/run-playwright-electron-hardware.cjs @@ -1,24 +1,27 @@ #!/usr/bin/env node /** - * @fileoverview Wrapper script that builds FlashForgeUI and then runs the guarded - * Electron hardware Playwright Discord validation against a real printer. + * @fileoverview Builds FlashForgeUI and runs the Electron E2E suite against the + * hardware track: the real printers on the developer's bench. + * + * This is the pre-release gate. It drives the actual GUI against actual firmware, so it + * covers what the emulator cannot - real discovery timing, real material-station slot + * contents, and the SFTP file manager (which needs FlashForge-EasySSH provisioning). + * + * Printers are resolved by serial through UDP discovery, so DHCP moving a printer does + * not break the run. Credentials live outside the repo; see support/hardware-config.ts + * for the lookup order. Uploads always run with Start Now unchecked and are followed by + * a safety check that cancels and clears the platform if a print ever starts. + * + * Extra arguments are forwarded to Playwright, e.g. + * pnpm test:e2e:electron:hardware specs/upload.spec.ts */ const { spawnSync } = require('node:child_process'); -const requiredEnvNames = ['FFUI_E2E_AD5X_IP', 'FFUI_E2E_AD5X_CHECK_CODE']; - -for (const name of requiredEnvNames) { - if (!process.env[name] || process.env[name].trim().length === 0) { - console.error(`[e2e:electron:hardware] Missing required environment variable: ${name}`); - process.exit(1); - } -} - const env = { ...process.env, - FFUI_E2E_HARDWARE: '1', + FFUI_E2E_TRACK: 'hardware', }; const passthroughArgs = process.argv.slice(2); @@ -36,15 +39,7 @@ if (buildResult.status !== 0) { const testResult = spawnSync( 'pnpm', - [ - 'exec', - 'playwright', - 'test', - '-c', - 'playwright.electron.config.ts', - 'tests/e2e/electron/discord-hardware.spec.ts', - ...passthroughArgs, - ], + ['exec', 'playwright', 'test', '-c', 'playwright.electron.config.ts', 'tests/e2e/electron/specs', ...passthroughArgs], { stdio: 'inherit', env, diff --git a/scripts/run-playwright-electron-live.cjs b/scripts/run-playwright-electron-live.cjs deleted file mode 100644 index b7515e7..0000000 --- a/scripts/run-playwright-electron-live.cjs +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env node - -/** - * @fileoverview Wrapper script that builds FlashForgeUI and runs the live Electron - * Playwright smoke test against the local desktop environment. - */ - -const { spawnSync } = require('node:child_process'); - -const env = { - ...process.env, - FFUI_E2E_LIVE: '1', -}; - -const buildResult = spawnSync('pnpm', ['run', 'build'], { - stdio: 'inherit', - env, - shell: process.platform === 'win32', -}); - -if (buildResult.status !== 0) { - process.exit(buildResult.status ?? 1); -} - -const testResult = spawnSync('pnpm', ['exec', 'playwright', 'test', '-c', 'playwright.electron.config.ts'], { - stdio: 'inherit', - env, - shell: process.platform === 'win32', -}); - -process.exit(testResult.status ?? 1); diff --git a/src/main/printer-backends/AD5XBackend.ts b/src/main/printer-backends/AD5XBackend.ts index ce6ed18..60035d8 100644 --- a/src/main/printer-backends/AD5XBackend.ts +++ b/src/main/printer-backends/AD5XBackend.ts @@ -21,6 +21,7 @@ import { PrinterFeatureSet, } from '@shared/types/printer-backend/index.js'; import * as path from 'path'; +import { normalizeMaterialMappingColors } from '../../shared/utils/materialColor.js'; import { MaterialStationBackend } from './MaterialStationBackend.js'; /** @@ -100,7 +101,7 @@ export class AD5XBackend extends MaterialStationBackend { const success = await this.fiveMClient.jobControl.startAD5XMultiColorJob({ fileName: params.fileName, levelingBeforePrint: params.leveling, - materialMappings, + materialMappings: normalizeMaterialMappingColors(materialMappings), }); if (!success) { @@ -155,7 +156,9 @@ export class AD5XBackend extends MaterialStationBackend { flowCalibration: false, firstLayerInspection: false, timeLapseVideo: false, - materialMappings: materialMappings || [], + // The AD5X reports slot colours as raw config strings, often without a leading + // '#'. ff-api rejects those before sending, so normalise here. + materialMappings: normalizeMaterialMappingColors(materialMappings ?? []), }; console.log( diff --git a/src/main/printer-backends/Creator5Backend.ts b/src/main/printer-backends/Creator5Backend.ts index fb26e5c..cf586d9 100644 --- a/src/main/printer-backends/Creator5Backend.ts +++ b/src/main/printer-backends/Creator5Backend.ts @@ -33,6 +33,7 @@ import { PrinterFeatureSet, } from '@shared/types/printer-backend/index.js'; import { basename } from 'path'; +import { normalizeMaterialMappingColors } from '../../shared/utils/materialColor.js'; import { MaterialStationBackend } from './MaterialStationBackend.js'; /** @@ -287,8 +288,12 @@ export class Creator5Backend extends MaterialStationBackend { return await this.fiveMClient.jobControl.startCreator5Job({ fileName, levelingBeforePrint, + // ff-api validates mapping colours as '#RRGGBB' and refuses to send otherwise, so + // normalise before handing them over. materialMappings: - materialMappings && materialMappings.length > 0 ? materialMappings : undefined, + materialMappings && materialMappings.length > 0 + ? normalizeMaterialMappingColors(materialMappings) + : undefined, }); } } diff --git a/src/shared/utils/__tests__/materialColor.test.ts b/src/shared/utils/__tests__/materialColor.test.ts new file mode 100644 index 0000000..dfa19f7 --- /dev/null +++ b/src/shared/utils/__tests__/materialColor.test.ts @@ -0,0 +1,92 @@ +/** + * @fileoverview Unit coverage for material colour normalization. + * + * The cases here mirror real values observed on hardware: an AD5X reports slot colours + * as raw config strings ("161616", "7C4B00") while others come back already prefixed + * ("#F98D33"). ff-api rejects anything that is not '#RRGGBB' before sending, so both + * forms have to converge. + */ + +import { + DEFAULT_MATERIAL_COLOR, + normalizeMaterialColor, + normalizeMaterialMappingColors, +} from '../materialColor'; + +describe('normalizeMaterialColor', () => { + it('adds a missing leading hash', () => { + expect(normalizeMaterialColor('161616')).toBe('#161616'); + expect(normalizeMaterialColor('7C4B00')).toBe('#7C4B00'); + }); + + it('leaves an already-prefixed colour intact', () => { + expect(normalizeMaterialColor('#F98D33')).toBe('#F98D33'); + }); + + it('upper-cases so equal colours compare equal regardless of source casing', () => { + expect(normalizeMaterialColor('#f98d33')).toBe('#F98D33'); + expect(normalizeMaterialColor('abcdef')).toBe('#ABCDEF'); + }); + + it('trims surrounding whitespace', () => { + expect(normalizeMaterialColor(' 161616 ')).toBe('#161616'); + }); + + it('keeps only the value before the first semicolon, as the AD5X config encodes it', () => { + expect(normalizeMaterialColor('161616;PLA')).toBe('#161616'); + expect(normalizeMaterialColor('#F98D33;something')).toBe('#F98D33'); + }); + + it('falls back when the colour is missing or unusable', () => { + expect(normalizeMaterialColor(undefined)).toBe(DEFAULT_MATERIAL_COLOR); + expect(normalizeMaterialColor(null)).toBe(DEFAULT_MATERIAL_COLOR); + expect(normalizeMaterialColor('')).toBe(DEFAULT_MATERIAL_COLOR); + expect(normalizeMaterialColor(' ')).toBe(DEFAULT_MATERIAL_COLOR); + expect(normalizeMaterialColor('not-a-colour')).toBe(DEFAULT_MATERIAL_COLOR); + // Three-digit shorthand is not what the printers emit, so it is not accepted. + expect(normalizeMaterialColor('#FFF')).toBe(DEFAULT_MATERIAL_COLOR); + expect(normalizeMaterialColor('#1234567')).toBe(DEFAULT_MATERIAL_COLOR); + }); + + it('honours a caller-supplied fallback', () => { + expect(normalizeMaterialColor('nope', '#000000')).toBe('#000000'); + }); +}); + +describe('normalizeMaterialMappingColors', () => { + it('normalizes both colour fields and preserves everything else', () => { + const mappings = [ + { + toolId: 0, + slotId: 4, + materialName: 'PLA', + toolMaterialColor: '7C4B00', + slotMaterialColor: '161616', + }, + ]; + + expect(normalizeMaterialMappingColors(mappings)).toEqual([ + { + toolId: 0, + slotId: 4, + materialName: 'PLA', + toolMaterialColor: '#7C4B00', + slotMaterialColor: '#161616', + }, + ]); + }); + + it('does not mutate the input', () => { + const mappings = [ + { toolId: 0, slotId: 1, materialName: 'PLA', toolMaterialColor: 'aabbcc', slotMaterialColor: 'ddeeff' }, + ]; + + normalizeMaterialMappingColors(mappings); + + expect(mappings[0].toolMaterialColor).toBe('aabbcc'); + }); + + it('handles an empty array', () => { + expect(normalizeMaterialMappingColors([])).toEqual([]); + }); +}); diff --git a/src/shared/utils/materialColor.ts b/src/shared/utils/materialColor.ts new file mode 100644 index 0000000..9a403ad --- /dev/null +++ b/src/shared/utils/materialColor.ts @@ -0,0 +1,57 @@ +/** + * @fileoverview Normalizes material colors before they are sent to a printer. + * + * The AD5X reports a slot's color as a raw config string - the API docs describe + * `MatlSlotInfo.materialColor` as the "color string before first ';' in config" - so it + * arrives with no format guarantee and frequently without a leading '#'. The Creator 5 + * documents the same field as a proper '#RRGGBB' value. + * + * `@ghosttypes/ff-api` validates every outbound MaterialMapping color against + * /^#[0-9A-Fa-f]{6}$/ and refuses to send the request if any color fails, so forwarding + * a printer-supplied color verbatim can abort an upload before it reaches the network. + * Normalizing here keeps the mapping payload in the documented '#RRGGBB' form for both + * printer families without needing the library to relax its check. + * + * Key exports: + * - normalizeMaterialColor(): one color to '#RRGGBB' + * - normalizeMaterialMappingColors(): a whole mapping array + */ + +/** Used when a color is missing or unparseable, matching the material dialog's default. */ +export const DEFAULT_MATERIAL_COLOR = '#808080'; + +/** + * Coerces a color to '#RRGGBB'. + * + * Accepts values with or without a leading '#', and tolerates the trailing + * config data the AD5X sometimes carries (for example "161616;PLA"). Anything that + * still does not resolve to six hex digits falls back to `fallback` rather than being + * passed through, since an invalid color would fail validation downstream anyway. + */ +export function normalizeMaterialColor(value: string | undefined | null, fallback = DEFAULT_MATERIAL_COLOR): string { + const raw = (value ?? '').trim(); + if (raw.length === 0) { + return fallback; + } + + const hex = raw.split(';')[0].trim().replace(/^#/, ''); + return /^[0-9A-Fa-f]{6}$/.test(hex) ? `#${hex.toUpperCase()}` : fallback; +} + +/** The color fields carried by an AD5X / Creator 5 material mapping. */ +interface MaterialMappingColors { + toolMaterialColor: string; + slotMaterialColor: string; +} + +/** + * Returns a copy of `mappings` with both color fields normalized. + * Non-color fields are preserved untouched. + */ +export function normalizeMaterialMappingColors(mappings: readonly T[]): T[] { + return mappings.map((mapping) => ({ + ...mapping, + toolMaterialColor: normalizeMaterialColor(mapping.toolMaterialColor), + slotMaterialColor: normalizeMaterialColor(mapping.slotMaterialColor), + })); +} diff --git a/tests/e2e/electron/desktop-emulator.spec.ts b/tests/e2e/electron/desktop-emulator.spec.ts deleted file mode 100644 index 35e32fc..0000000 --- a/tests/e2e/electron/desktop-emulator.spec.ts +++ /dev/null @@ -1,1592 +0,0 @@ -/** - * @fileoverview Electron Playwright coverage against the external flashforge-emulator-v2 harness. - * - * Exercises direct and discovery connection flows, single- and multi-printer contexts, modern and - * legacy backends, material matching, LED and filtration controls, and full print lifecycle checks. - */ - -import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'; -import * as net from 'node:net'; -import os from 'node:os'; -import path from 'node:path'; -import { type ElectronApplication, _electron as electron, expect, type Page, test } from '@playwright/test'; -import { - type EmulatorAuthConfig, - type EmulatorMaterialMapping, - type EmulatorModel, - type EmulatorReadyPayload, - fetchEmulatorDetail, - seedEmulatorRecentFile, - startEmulatorInstance, - startEmulatorSupervisor, - waitForEmulatorDetail, -} from './helpers/emulator-harness'; - -const EMULATOR_FLAG = 'FFUI_E2E_EMULATOR'; -const DISCOVERY_FLAG = 'FFUI_E2E_EMULATOR_DISCOVERY'; -const LOCALHOST_IP = '127.0.0.1'; -const DEFAULT_CHECK_CODE = '123'; -const CONNECT_TIMEOUT_MS = 60_000; -const JOB_ACTION_TIMEOUT_MS = 30_000; -const WINDOW_POLL_INTERVAL_MS = 25; -const OPTIONAL_DIALOG_TIMEOUT_MS = 250; -const SEEDED_PRINTER_AUTOCONNECT_TIMEOUT_MS = 4_000; -const CONSOLE_ERROR_ALLOWLIST: readonly RegExp[] = [/Autofill\.enable/i, /Autofill\.setAddresses/i]; - -interface LaunchedElectronApp { - electronApp: ElectronApplication; - mainWindow: Page; - appDataRoot: string; - assertNoUnexpectedRendererErrors: () => void; - disposeRendererErrorGuard: () => void; -} - -interface MaterialSlotAssignment { - toolId: number; - slotId: number; -} - -interface SeedRecentFileOptions { - gcodeContent?: string; - gcodeToolCnt?: number; - useMatlStation?: boolean; - materialMappings?: readonly EmulatorMaterialMapping[]; -} - -interface SeededPrinterDetailsEntry { - Name: string; - IPAddress: string; - SerialNumber: string; - CheckCode: string; - ClientType: 'legacy' | 'new'; - printerModel: string; - customCameraEnabled?: boolean; - customCameraUrl?: string; - customLedsEnabled?: boolean; - forceLegacyMode?: boolean; - webUIEnabled?: boolean; - showCameraFps?: boolean; - commandPort?: number; - httpPort?: number; -} - -const sleep = async (ms: number): Promise => - await new Promise((resolve) => { - setTimeout(resolve, ms); - }); - -const getFreePort = async (): Promise => { - return await new Promise((resolve, reject) => { - const server = net.createServer(); - server.unref(); - server.on('error', reject); - server.listen(0, '127.0.0.1', () => { - const address = server.address(); - if (!address || typeof address === 'string') { - server.close(() => reject(new Error('Failed to acquire a free port'))); - return; - } - - const { port } = address; - server.close((error) => { - if (error) { - reject(error); - } else { - resolve(port); - } - }); - }); - }); -}; - -const getDistinctFreePorts = async (count: number): Promise => { - const ports = new Set(); - while (ports.size < count) { - ports.add(await getFreePort()); - } - - return Array.from(ports.values()); -}; - -const getExpectedUserDataPath = (appDataRoot: string): string => { - return path.join(appDataRoot, 'FlashForgeUI'); -}; - -const seedPrinterDetails = async ( - userDataPath: string, - seededPrinters: readonly SeededPrinterDetailsEntry[] -): Promise => { - if (seededPrinters.length === 0) { - return; - } - - await mkdir(userDataPath, { recursive: true }); - - const printers: Record> = {}; - const nowIso = new Date().toISOString(); - for (const printer of seededPrinters) { - printers[printer.SerialNumber] = { - ...printer, - lastConnected: nowIso, - }; - } - - const payload = { - lastUsedPrinterSerial: seededPrinters[0]?.SerialNumber ?? null, - printers, - }; - - await writeFile(path.join(userDataPath, 'printer_details.json'), `${JSON.stringify(payload, null, 2)}\n`, 'utf-8'); -}; - -const normalizeWhitespace = (value: string | null | undefined): string => { - return (value ?? '').replace(/\s+/g, ' ').trim(); -}; - -const shouldIgnoreConsoleError = (message: string): boolean => { - return CONSOLE_ERROR_ALLOWLIST.some((pattern) => pattern.test(message)); -}; - -const createRendererErrorGuard = ( - electronApp: ElectronApplication -): { - assertNoUnexpectedRendererErrors: () => void; - dispose: () => void; -} => { - const unexpectedErrors: string[] = []; - const seenErrors = new Set(); - const disposers: Array<() => void> = []; - - const pushUnexpectedError = (message: string): void => { - if (seenErrors.has(message)) { - return; - } - seenErrors.add(message); - unexpectedErrors.push(message); - }; - - const pageLabel = (windowPage: Page): string => { - try { - const url = windowPage.url(); - return url && url.length > 0 ? url : 'about:blank'; - } catch { - return 'unknown'; - } - }; - - const attachWindow = (windowPage: Page): void => { - const onPageError = (error: Error): void => { - const url = pageLabel(windowPage); - if (url.startsWith('devtools://')) { - return; - } - - pushUnexpectedError(`[pageerror] ${url}: ${error.message}`); - }; - - const onConsole = (message: { type(): string; text(): string }): void => { - if (message.type() !== 'error') { - return; - } - - const url = pageLabel(windowPage); - if (url.startsWith('devtools://')) { - return; - } - - const text = normalizeWhitespace(message.text()); - if (shouldIgnoreConsoleError(text)) { - return; - } - - pushUnexpectedError(`[console.error] ${url}: ${text}`); - }; - - windowPage.on('pageerror', onPageError); - windowPage.on('console', onConsole); - disposers.push(() => { - windowPage.off('pageerror', onPageError); - windowPage.off('console', onConsole); - }); - }; - - for (const windowPage of electronApp.windows()) { - attachWindow(windowPage); - } - - const onWindowOpened = (windowPage: Page): void => { - attachWindow(windowPage); - }; - electronApp.on('window', onWindowOpened); - disposers.push(() => { - electronApp.off('window', onWindowOpened); - }); - - return { - assertNoUnexpectedRendererErrors: () => { - if (unexpectedErrors.length === 0) { - return; - } - - throw new Error(`Unexpected renderer errors detected:\n${unexpectedErrors.join('\n')}`); - }, - dispose: () => { - for (const disposer of disposers) { - disposer(); - } - }, - }; -}; - -const findWindowWithSelector = async ( - electronApp: ElectronApplication, - selector: string, - timeoutMs = 10_000, - pollIntervalMs = WINDOW_POLL_INTERVAL_MS -): Promise => { - const deadline = Date.now() + timeoutMs; - - while (Date.now() < deadline) { - for (const windowPage of electronApp.windows()) { - try { - if ((await windowPage.locator(selector).count()) > 0) { - return windowPage; - } - } catch { - // Ignore detached/closing windows while polling - } - } - - await sleep(pollIntervalMs); - } - - return null; -}; - -const waitForWindowWithSelector = async ( - electronApp: ElectronApplication, - selector: string, - timeoutMs = 10_000, - pollIntervalMs = WINDOW_POLL_INTERVAL_MS -): Promise => { - const foundWindow = await findWindowWithSelector(electronApp, selector, timeoutMs, pollIntervalMs); - if (foundWindow) { - return foundWindow; - } - - throw new Error(`Timed out waiting for window with selector "${selector}" after ${timeoutMs}ms`); -}; - -const expectWindowWithSelectorToClose = async ( - electronApp: ElectronApplication, - selector: string, - timeoutMs = 10_000 -): Promise => { - await expect - .poll( - async () => { - const found = await findWindowWithSelector(electronApp, selector, 250); - return found ? 1 : 0; - }, - { timeout: timeoutMs } - ) - .toBe(0); -}; - -const hasMainUiMarkers = async (windowPage: Page): Promise => { - try { - if ((await windowPage.locator('#btn-main-menu').count()) > 0) { - return true; - } - - if ((await windowPage.locator('#placeholder-connect-btn').count()) > 0) { - return true; - } - } catch { - return false; - } - - return false; -}; - -const resolveMainWindow = async (electronApp: ElectronApplication, timeoutMs = 20_000): Promise => { - const deadline = Date.now() + timeoutMs; - let lastWindowCount = 0; - - while (Date.now() < deadline) { - const windows = electronApp.windows(); - lastWindowCount = windows.length; - - for (const windowPage of windows) { - if (await hasMainUiMarkers(windowPage)) { - return windowPage; - } - } - - await sleep(WINDOW_POLL_INTERVAL_MS); - } - - throw new Error( - `Unable to locate main application window after ${timeoutMs}ms (observed ${lastWindowCount} window(s))` - ); -}; - -const launchElectronWithIsolatedProfile = async (params?: { - seededPrinters?: readonly SeededPrinterDetailsEntry[]; -}): Promise => { - const appDataRoot = await mkdtemp(path.join(os.tmpdir(), 'ffui-e2e-electron-')); - const userDataPath = getExpectedUserDataPath(appDataRoot); - - if (params?.seededPrinters && params.seededPrinters.length > 0) { - await seedPrinterDetails(userDataPath, params.seededPrinters); - } - - const env = { - ...process.env, - FFUI_USER_DATA_DIR: userDataPath, - }; - - const electronApp = await electron.launch({ - args: ['.'], - cwd: process.cwd(), - timeout: 120_000, - env, - }); - - const rendererErrorGuard = createRendererErrorGuard(electronApp); - const actualUserDataPath = await electronApp.evaluate(async ({ app }) => app.getPath('userData')); - expect(actualUserDataPath.toLowerCase()).toBe(userDataPath.toLowerCase()); - - const mainWindow = await resolveMainWindow(electronApp); - await expect(mainWindow.locator('.title')).toHaveText('FlashForgeUI'); - - return { - electronApp, - mainWindow, - appDataRoot, - assertNoUnexpectedRendererErrors: rendererErrorGuard.assertNoUnexpectedRendererErrors, - disposeRendererErrorGuard: rendererErrorGuard.dispose, - }; -}; - -const closeLaunchedElectronApp = async (launched: LaunchedElectronApp): Promise => { - try { - await launched.electronApp.close(); - } finally { - launched.disposeRendererErrorGuard(); - await rm(launched.appDataRoot, { recursive: true, force: true }); - } -}; - -const openConnectFlow = async (mainWindow: Page): Promise => { - const placeholderConnectButton = mainWindow.locator('#placeholder-connect-btn'); - if (await placeholderConnectButton.isVisible()) { - await placeholderConnectButton.click(); - return; - } - - await expect(mainWindow.locator('#btn-main-menu')).toBeVisible(); - await mainWindow.locator('#btn-main-menu').click(); - const connectMenuItem = mainWindow.locator('#main-menu-dropdown .menu-item[data-action="connect"]'); - await expect(connectMenuItem).toBeVisible(); - await connectMenuItem.click(); -}; - -const maybeHandleConnectedWarningDialog = async ( - electronApp: ElectronApplication, - timeoutMs = OPTIONAL_DIALOG_TIMEOUT_MS -): Promise => { - const warningDialog = await findWindowWithSelector(electronApp, '#dialog-continue', timeoutMs); - if (!warningDialog) { - return; - } - - await warningDialog.locator('#dialog-continue').click(); -}; - -const maybeDismissAutoConnectChoiceDialog = async (params: { - electronApp: ElectronApplication; - timeoutMs?: number; -}): Promise => { - const timeoutMs = params.timeoutMs ?? OPTIONAL_DIALOG_TIMEOUT_MS; - const autoConnectDialog = await findWindowWithSelector(params.electronApp, '#btn-manual-ip', timeoutMs); - if (!autoConnectDialog) { - return false; - } - - const cancelButton = autoConnectDialog.locator('#btn-cancel').first(); - await expect(cancelButton).toBeVisible({ timeout: 5_000 }); - await cancelButton.click(); - return true; -}; - -const maybeSubmitCheckCodeDialog = async (params: { - electronApp: ElectronApplication; - checkCode: string; - timeoutMs?: number; - required?: boolean; -}): Promise => { - const timeoutMs = params.timeoutMs ?? 20_000; - const inputDialog = await findWindowWithSelector(params.electronApp, '#dialog-input', timeoutMs); - if (!inputDialog) { - if (params.required) { - throw new Error(`Expected check code dialog within ${timeoutMs}ms, but it did not appear`); - } - - return false; - } - - await inputDialog.locator('#dialog-input').fill(params.checkCode); - await inputDialog.locator('#dialog-ok').click(); - return true; -}; - -const waitForConnectedUi = async (mainWindow: Page, expectedConnectedTabs: number): Promise => { - await expect - .poll( - async () => { - return await mainWindow.locator('#printer-tabs-container .printer-tab.status-connected').count(); - }, - { timeout: CONNECT_TIMEOUT_MS } - ) - .toBeGreaterThanOrEqual(expectedConnectedTabs); - - await expect(mainWindow.locator('#grid-placeholder')).toBeHidden(); - await expect(mainWindow.locator('.grid-stack')).toBeVisible(); -}; - -const waitForPrinterState = async (mainWindow: Page, expectedState: string): Promise => { - await expect - .poll( - async () => { - const text = await mainWindow.locator('#printer-status-text').first().textContent(); - return normalizeWhitespace(text); - }, - { timeout: JOB_ACTION_TIMEOUT_MS } - ) - .toBe(expectedState); -}; - -const isPageClosedDuringActionError = (error: unknown): boolean => { - return error instanceof Error && /Target page, context or browser has been closed/i.test(error.message); -}; - -const selectPrinterFromDiscoveryDialog = async (params: { - electronApp: ElectronApplication; - rowText: string; -}): Promise => { - const selectionDialog = await waitForWindowWithSelector(params.electronApp, '#printer-table', 35_000); - const matchedRow = selectionDialog - .locator('#printer-table tbody tr[data-printer]', { hasText: params.rowText }) - .first(); - await expect(matchedRow).toBeVisible({ timeout: 20_000 }); - try { - await matchedRow.dblclick(); - } catch (error) { - if (!isPageClosedDuringActionError(error)) { - throw error; - } - } -}; - -const connectThroughDiscoveryDialog = async (params: { - electronApp: ElectronApplication; - mainWindow: Page; - selectionText: string; - checkCode: string; - expectCheckCodePrompt: boolean; -}): Promise => { - await maybeDismissAutoConnectChoiceDialog({ - electronApp: params.electronApp, - timeoutMs: OPTIONAL_DIALOG_TIMEOUT_MS, - }); - await openConnectFlow(params.mainWindow); - await maybeHandleConnectedWarningDialog(params.electronApp); - - const connectChoiceDialog = await waitForWindowWithSelector(params.electronApp, '#btn-scan-network', 15_000); - await connectChoiceDialog.locator('#btn-scan-network').click(); - - await selectPrinterFromDiscoveryDialog({ - electronApp: params.electronApp, - rowText: params.selectionText, - }); - await maybeSubmitCheckCodeDialog({ - electronApp: params.electronApp, - checkCode: params.checkCode, - timeoutMs: params.expectCheckCodePrompt ? 20_000 : OPTIONAL_DIALOG_TIMEOUT_MS, - required: params.expectCheckCodePrompt, - }); - - await expectWindowWithSelectorToClose(params.electronApp, '#btn-scan-network'); -}; - -const connectThroughDirectIpDialog = async (params: { - electronApp: ElectronApplication; - mainWindow: Page; - ipAddress: string; - checkCode: string; - expectCheckCodePrompt: boolean; -}): Promise => { - await maybeDismissAutoConnectChoiceDialog({ - electronApp: params.electronApp, - timeoutMs: OPTIONAL_DIALOG_TIMEOUT_MS, - }); - await openConnectFlow(params.mainWindow); - await maybeHandleConnectedWarningDialog(params.electronApp); - - const connectChoiceDialog = await waitForWindowWithSelector(params.electronApp, '#btn-enter-ip', 15_000); - await connectChoiceDialog.locator('#btn-enter-ip').click(); - - const inputDialog = await waitForWindowWithSelector(params.electronApp, '#dialog-input', 15_000); - await inputDialog.locator('#dialog-input').fill(params.ipAddress); - await inputDialog.locator('#dialog-ok').click(); - - await maybeSubmitCheckCodeDialog({ - electronApp: params.electronApp, - checkCode: params.checkCode, - timeoutMs: params.expectCheckCodePrompt ? 20_000 : OPTIONAL_DIALOG_TIMEOUT_MS, - required: params.expectCheckCodePrompt, - }); - - await expectWindowWithSelectorToClose(params.electronApp, '#btn-enter-ip'); -}; - -const firstConnectedTabName = async (mainWindow: Page): Promise => { - const tabName = await mainWindow.locator('#printer-tabs-container .printer-tab .tab-name').first().textContent(); - return tabName?.trim() ?? ''; -}; - -const setCustomLedsEnabled = async (mainWindow: Page): Promise => { - const updated = await mainWindow.evaluate(async () => { - const bridgedApi = ( - window as unknown as { - api?: { - printerSettings?: { - update: (settings: unknown) => Promise; - get: () => Promise; - }; - }; - } - ).api; - - if (!bridgedApi?.printerSettings) { - return false; - } - - const updateResult = await bridgedApi.printerSettings.update({ customLedsEnabled: true }); - if (!updateResult) { - return false; - } - - const settings = (await bridgedApi.printerSettings.get()) as { customLedsEnabled?: boolean } | null; - return settings?.customLedsEnabled === true; - }); - - expect(updated).toBe(true); -}; - -const completeMaterialMatchingDialog = async (params: { - materialDialog: Page; - assignments?: readonly MaterialSlotAssignment[]; -}): Promise => { - const requirementItems = params.materialDialog.locator('.requirement-item'); - const requirementCount = await requirementItems.count(); - expect(requirementCount).toBeGreaterThan(0); - - const assignments = - params.assignments ?? - Array.from({ length: requirementCount }, (_, index) => ({ - toolId: index, - slotId: index + 1, - })); - - for (const assignment of assignments) { - const requirement = params.materialDialog.locator(`.requirement-item[data-tool-id="${assignment.toolId}"]`).first(); - await expect(requirement).toBeVisible({ timeout: 10_000 }); - await requirement.click(); - - const slot = params.materialDialog - .locator(`.slot-item[data-slot-id="${assignment.slotId}"]:not(.disabled):not(.assigned)`) - .first(); - await expect(slot).toBeVisible({ timeout: 10_000 }); - await slot.click(); - } - - const confirmButton = params.materialDialog.locator('#btn-confirm'); - await expect(confirmButton).toBeEnabled({ timeout: 10_000 }); - await confirmButton.click(); -}; - -const trySelectFileFromPickerWindow = async (params: { - pickerWindow: Page; - preferredFileName: string; - timeoutMs: number; -}): Promise => { - const allFileItems = params.pickerWindow.locator('.file-item[data-filename]'); - - try { - await expect(allFileItems.first()).toBeVisible({ timeout: params.timeoutMs }); - } catch { - return null; - } - - let fileItem = params.pickerWindow.locator(`.file-item[data-filename="${params.preferredFileName}"]`).first(); - if ((await fileItem.count()) === 0) { - fileItem = allFileItems.first(); - } - - await expect(fileItem).toBeVisible({ timeout: 5_000 }); - const selectedFileName = (await fileItem.getAttribute('data-filename')) ?? params.preferredFileName; - await fileItem.click(); - await expect(params.pickerWindow.locator('#btn-select')).toBeEnabled(); - await params.pickerWindow.locator('#btn-select').click(); - return selectedFileName; -}; - -const startRecentJobFromUi = async (params: { - electronApp: ElectronApplication; - mainWindow: Page; - fileName: string; - expectMaterialMatching?: boolean; - materialSlotAssignments?: readonly MaterialSlotAssignment[]; -}): Promise => { - await expect(params.mainWindow.locator('#btn-start-recent')).toBeVisible(); - await expect(params.mainWindow.locator('#btn-start-recent')).toBeEnabled(); - await params.mainWindow.locator('#btn-start-recent').click(); - - let jobPickerWindow = await waitForWindowWithSelector(params.electronApp, '#file-list', 20_000); - let selectedFileName = await trySelectFileFromPickerWindow({ - pickerWindow: jobPickerWindow, - preferredFileName: params.fileName, - timeoutMs: 20_000, - }); - - if (!selectedFileName) { - const cancelButton = jobPickerWindow.locator('#btn-cancel').first(); - if ((await cancelButton.count()) > 0) { - await cancelButton.click().catch(() => { - // Ignore if dialog closes while clicking - }); - } - - await expect(params.mainWindow.locator('#btn-start-local')).toBeVisible(); - await expect(params.mainWindow.locator('#btn-start-local')).toBeEnabled(); - await params.mainWindow.locator('#btn-start-local').click(); - - jobPickerWindow = await waitForWindowWithSelector(params.electronApp, '#file-list', 20_000); - selectedFileName = await trySelectFileFromPickerWindow({ - pickerWindow: jobPickerWindow, - preferredFileName: params.fileName, - timeoutMs: 30_000, - }); - } - - if (!selectedFileName) { - throw new Error('No files available in recent or local picker'); - } - - const materialMatchingDialog = await findWindowWithSelector(params.electronApp, '#print-requirements', 5_000); - if (materialMatchingDialog) { - await completeMaterialMatchingDialog({ - materialDialog: materialMatchingDialog, - assignments: params.materialSlotAssignments, - }); - return selectedFileName; - } - - if (params.expectMaterialMatching) { - throw new Error('Expected material matching dialog, but it did not appear'); - } - - const singleColorDialog = await findWindowWithSelector(params.electronApp, '#btn-start', 5_000); - if (!singleColorDialog) { - return selectedFileName; - } - - await singleColorDialog.locator('#btn-start').click(); - return selectedFileName; -}; - -const verifyLedControls = async (params: { mainWindow: Page; emulatorAuth: EmulatorAuthConfig }): Promise => { - await expect(params.mainWindow.locator('#btn-led-on')).toBeVisible(); - await expect(params.mainWindow.locator('#btn-led-on')).toBeEnabled(); - await params.mainWindow.locator('#btn-led-on').click(); - await waitForEmulatorDetail({ - ...params.emulatorAuth, - description: 'LED toggled on', - predicate: (detail) => detail.lightStatus === 'open', - timeoutMs: JOB_ACTION_TIMEOUT_MS, - }); - - await expect(params.mainWindow.locator('#btn-led-off')).toBeVisible(); - await expect(params.mainWindow.locator('#btn-led-off')).toBeEnabled(); - await params.mainWindow.locator('#btn-led-off').click(); - await waitForEmulatorDetail({ - ...params.emulatorAuth, - description: 'LED toggled off', - predicate: (detail) => detail.lightStatus === 'close', - timeoutMs: JOB_ACTION_TIMEOUT_MS, - }); -}; - -const verifyFiltrationControls = async (params: { - mainWindow: Page; - emulatorAuth: EmulatorAuthConfig; -}): Promise => { - await expect(params.mainWindow.locator('#btn-external-filtration')).toBeVisible(); - await expect(params.mainWindow.locator('#btn-external-filtration')).toBeEnabled(); - await params.mainWindow.locator('#btn-external-filtration').click(); - await expect - .poll( - async () => normalizeWhitespace(await params.mainWindow.locator('#filtration-status-display').textContent()), - { - timeout: JOB_ACTION_TIMEOUT_MS, - } - ) - .toBe('External'); - await waitForEmulatorDetail({ - ...params.emulatorAuth, - description: 'External filtration enabled', - predicate: (detail) => detail.externalFanStatus === 'open' && detail.internalFanStatus === 'close', - timeoutMs: JOB_ACTION_TIMEOUT_MS, - }); - - await expect(params.mainWindow.locator('#btn-internal-filtration')).toBeVisible(); - await expect(params.mainWindow.locator('#btn-internal-filtration')).toBeEnabled(); - await params.mainWindow.locator('#btn-internal-filtration').click(); - await expect - .poll( - async () => normalizeWhitespace(await params.mainWindow.locator('#filtration-status-display').textContent()), - { - timeout: JOB_ACTION_TIMEOUT_MS, - } - ) - .toBe('Internal'); - await waitForEmulatorDetail({ - ...params.emulatorAuth, - description: 'Internal filtration enabled', - predicate: (detail) => detail.externalFanStatus === 'close' && detail.internalFanStatus === 'open', - timeoutMs: JOB_ACTION_TIMEOUT_MS, - }); - - await expect(params.mainWindow.locator('#btn-no-filtration')).toBeVisible(); - await expect(params.mainWindow.locator('#btn-no-filtration')).toBeEnabled(); - await params.mainWindow.locator('#btn-no-filtration').click(); - await expect - .poll( - async () => normalizeWhitespace(await params.mainWindow.locator('#filtration-status-display').textContent()), - { - timeout: JOB_ACTION_TIMEOUT_MS, - } - ) - .toBe('None'); - await waitForEmulatorDetail({ - ...params.emulatorAuth, - description: 'Filtration disabled', - predicate: (detail) => detail.externalFanStatus === 'close' && detail.internalFanStatus === 'close', - timeoutMs: JOB_ACTION_TIMEOUT_MS, - }); -}; - -const runLifecycleControls = async (params: { - electronApp: ElectronApplication; - mainWindow: Page; - fileName: string; - emulatorAuth: EmulatorAuthConfig; - requiresCustomLedSetting: boolean; - supportsLedControls: boolean; - supportsFiltration: boolean; - expectedUiStateAfterCancel: string; - expectedDetailStatusAfterCancel: string; - expectMaterialMatching?: boolean; - materialSlotAssignments?: readonly MaterialSlotAssignment[]; - skipJobLifecycle?: boolean; -}): Promise => { - if (params.requiresCustomLedSetting && params.supportsLedControls) { - await setCustomLedsEnabled(params.mainWindow); - } - - if (params.supportsLedControls) { - await verifyLedControls({ - mainWindow: params.mainWindow, - emulatorAuth: params.emulatorAuth, - }); - } - - if (params.skipJobLifecycle) { - return; - } - - const selectedFileName = await startRecentJobFromUi({ - electronApp: params.electronApp, - mainWindow: params.mainWindow, - fileName: params.fileName, - expectMaterialMatching: params.expectMaterialMatching, - materialSlotAssignments: params.materialSlotAssignments, - }); - - await waitForPrinterState(params.mainWindow, 'Printing'); - await waitForEmulatorDetail({ - ...params.emulatorAuth, - description: 'Print started', - predicate: (detail) => - detail.status === 'printing' && (selectedFileName.length === 0 || detail.printFileName === selectedFileName), - timeoutMs: JOB_ACTION_TIMEOUT_MS, - }); - - await expect(params.mainWindow.locator('#btn-pause')).toBeEnabled({ timeout: JOB_ACTION_TIMEOUT_MS }); - await params.mainWindow.locator('#btn-pause').click(); - await waitForPrinterState(params.mainWindow, 'Paused'); - await waitForEmulatorDetail({ - ...params.emulatorAuth, - description: 'Print paused', - predicate: (detail) => detail.status === 'paused', - timeoutMs: JOB_ACTION_TIMEOUT_MS, - }); - - await expect(params.mainWindow.locator('#btn-resume')).toBeEnabled({ timeout: JOB_ACTION_TIMEOUT_MS }); - await params.mainWindow.locator('#btn-resume').click(); - await waitForPrinterState(params.mainWindow, 'Printing'); - await waitForEmulatorDetail({ - ...params.emulatorAuth, - description: 'Print resumed', - predicate: (detail) => detail.status === 'printing', - timeoutMs: JOB_ACTION_TIMEOUT_MS, - }); - - await expect(params.mainWindow.locator('#btn-stop')).toBeEnabled({ timeout: JOB_ACTION_TIMEOUT_MS }); - await params.mainWindow.locator('#btn-stop').click(); - await waitForPrinterState(params.mainWindow, params.expectedUiStateAfterCancel); - await waitForEmulatorDetail({ - ...params.emulatorAuth, - description: 'Print cancelled', - predicate: (detail) => detail.status === params.expectedDetailStatusAfterCancel, - timeoutMs: JOB_ACTION_TIMEOUT_MS, - }); - - if (params.supportsFiltration) { - await verifyFiltrationControls({ - mainWindow: params.mainWindow, - emulatorAuth: params.emulatorAuth, - }); - } -}; - -const verifyLegacyUnsupportedControls = async (mainWindow: Page): Promise => { - await expect(mainWindow.locator('#btn-upload-job')).toBeVisible(); - await expect(mainWindow.locator('#btn-clear-status')).toBeVisible(); - await expect(mainWindow.locator('#btn-led-on')).toBeVisible(); - await expect(mainWindow.locator('#btn-led-off')).toBeVisible(); - await expect(mainWindow.locator('#btn-start-recent')).toBeEnabled(); - await expect(mainWindow.locator('#btn-start-local')).toBeEnabled(); -}; - -const verifyFiltrationControlsDisabled = async (mainWindow: Page): Promise => { - await expect(mainWindow.locator('#btn-external-filtration')).toBeVisible(); - await expect(mainWindow.locator('#btn-external-filtration')).toBeDisabled(); - await expect(mainWindow.locator('#btn-internal-filtration')).toBeVisible(); - await expect(mainWindow.locator('#btn-internal-filtration')).toBeDisabled(); - await expect(mainWindow.locator('#btn-no-filtration')).toBeVisible(); - await expect(mainWindow.locator('#btn-no-filtration')).toBeDisabled(); -}; - -const verifyForceLegacyModeSetting = async (mainWindow: Page): Promise => { - const forceLegacyMode = await mainWindow.evaluate(async () => { - const bridgedApi = ( - window as unknown as { - api?: { - printerSettings?: { - get: () => Promise; - }; - }; - } - ).api; - - if (!bridgedApi?.printerSettings?.get) { - return null; - } - - const settings = (await bridgedApi.printerSettings.get()) as { forceLegacyMode?: boolean } | null; - return settings?.forceLegacyMode ?? null; - }); - - expect(forceLegacyMode).toBe(true); -}; - -const requireReadyPayload = (payload: EmulatorReadyPayload | null, label: string): EmulatorReadyPayload => { - if (!payload) { - throw new Error(`Missing readiness payload for ${label}`); - } - - return payload; -}; - -type ConnectionMode = 'direct' | 'discovery'; -type DiscoverySelectionStrategy = 'serial' | 'name'; - -interface LifecycleScenario { - label: string; - model: EmulatorModel; - serial: string; - machineName: string; - checkCode: string; - expectsCheckCodePrompt: boolean; - requiresCustomLedSetting: boolean; - supportsLedControls: boolean; - supportsFiltration: boolean; - discoverySelection: DiscoverySelectionStrategy; - verifyLegacyUnsupportedControls: boolean; - expectedUiStateAfterCancel: string; - expectedDetailStatusAfterCancel: string; -} - -const buildTypeNameForScenarioModel = (model: EmulatorModel): string => { - switch (model) { - case 'adventurer-5m': - return 'Adventurer 5M'; - case 'adventurer-5m-pro': - return 'Adventurer 5M Pro'; - case 'adventurer-5x': - return 'AD5X'; - case 'adventurer-3': - return 'Adventurer 3'; - case 'adventurer-4': - return 'Adventurer 4'; - } -}; - -const createForceLegacySeededPrinter = (scenario: LifecycleScenario): SeededPrinterDetailsEntry => { - return { - Name: `${scenario.machineName} Saved`, - IPAddress: LOCALHOST_IP, - SerialNumber: scenario.serial, - CheckCode: scenario.checkCode, - ClientType: 'legacy', - printerModel: buildTypeNameForScenarioModel(scenario.model), - customCameraEnabled: false, - customCameraUrl: '', - customLedsEnabled: false, - forceLegacyMode: true, - webUIEnabled: true, - showCameraFps: false, - }; -}; - -const MODERN_LIFECYCLE_SCENARIOS: readonly LifecycleScenario[] = [ - { - label: '5M Pro', - model: 'adventurer-5m-pro', - serial: 'E2E-SN-5MPRO', - machineName: 'E2E-5MPro', - checkCode: DEFAULT_CHECK_CODE, - expectsCheckCodePrompt: true, - requiresCustomLedSetting: false, - supportsLedControls: true, - supportsFiltration: true, - discoverySelection: 'serial', - verifyLegacyUnsupportedControls: false, - expectedUiStateAfterCancel: 'Cancelled', - expectedDetailStatusAfterCancel: 'cancelled', - }, - { - label: '5M', - model: 'adventurer-5m', - serial: 'E2E-SN-5M', - machineName: 'E2E-5M', - checkCode: DEFAULT_CHECK_CODE, - expectsCheckCodePrompt: true, - requiresCustomLedSetting: true, - supportsLedControls: true, - supportsFiltration: false, - discoverySelection: 'serial', - verifyLegacyUnsupportedControls: false, - expectedUiStateAfterCancel: 'Cancelled', - expectedDetailStatusAfterCancel: 'cancelled', - }, - { - label: 'AD5X', - model: 'adventurer-5x', - serial: 'E2E-SN-AD5X', - machineName: 'E2E-AD5X', - checkCode: DEFAULT_CHECK_CODE, - expectsCheckCodePrompt: true, - requiresCustomLedSetting: true, - supportsLedControls: true, - supportsFiltration: false, - discoverySelection: 'serial', - verifyLegacyUnsupportedControls: false, - expectedUiStateAfterCancel: 'Cancelled', - expectedDetailStatusAfterCancel: 'cancelled', - }, -]; - -const LEGACY_LIFECYCLE_SCENARIOS: readonly LifecycleScenario[] = [ - { - label: 'Adventurer 3', - model: 'adventurer-3', - serial: 'E2E-SN-A3', - machineName: 'E2E-A3', - checkCode: DEFAULT_CHECK_CODE, - expectsCheckCodePrompt: false, - requiresCustomLedSetting: false, - supportsLedControls: false, - supportsFiltration: false, - discoverySelection: 'name', - verifyLegacyUnsupportedControls: true, - expectedUiStateAfterCancel: 'Ready', - expectedDetailStatusAfterCancel: 'cancelled', - }, - { - label: 'Adventurer 4', - model: 'adventurer-4', - serial: 'E2E-SN-A4', - machineName: 'E2E-A4', - checkCode: DEFAULT_CHECK_CODE, - expectsCheckCodePrompt: false, - requiresCustomLedSetting: false, - supportsLedControls: false, - supportsFiltration: false, - discoverySelection: 'name', - verifyLegacyUnsupportedControls: true, - expectedUiStateAfterCancel: 'Ready', - expectedDetailStatusAfterCancel: 'cancelled', - }, -]; - -const ALL_LIFECYCLE_SCENARIOS: readonly LifecycleScenario[] = [ - ...MODERN_LIFECYCLE_SCENARIOS, - ...LEGACY_LIFECYCLE_SCENARIOS, -]; - -const AD5X_SCENARIO = MODERN_LIFECYCLE_SCENARIOS.find((scenario) => scenario.model === 'adventurer-5x'); - -if (!AD5X_SCENARIO) { - throw new Error('Missing AD5X lifecycle scenario'); -} - -const AD5X_MULTI_COLOR_MAPPINGS: readonly EmulatorMaterialMapping[] = [ - { - toolId: 0, - slotId: 1, - materialName: 'PLA', - toolMaterialColor: '#4DA3FF', - slotMaterialColor: '#4DA3FF', - }, - { - toolId: 1, - slotId: 2, - materialName: 'PETG', - toolMaterialColor: '#FF8A3D', - slotMaterialColor: '#FF8A3D', - }, -]; - -const FIVE_M_SCENARIO = MODERN_LIFECYCLE_SCENARIOS.find((scenario) => scenario.model === 'adventurer-5m'); -const FIVE_M_PRO_SCENARIO = MODERN_LIFECYCLE_SCENARIOS.find((scenario) => scenario.model === 'adventurer-5m-pro'); - -if (!FIVE_M_SCENARIO || !FIVE_M_PRO_SCENARIO) { - throw new Error('Missing 5M and/or 5M Pro lifecycle scenario'); -} - -const FORCE_LEGACY_DIRECT_SCENARIOS: readonly LifecycleScenario[] = [ - { - ...FIVE_M_SCENARIO, - label: '5M (forced legacy)', - expectsCheckCodePrompt: false, - requiresCustomLedSetting: true, - supportsLedControls: true, - supportsFiltration: false, - verifyLegacyUnsupportedControls: true, - expectedUiStateAfterCancel: 'Ready', - expectedDetailStatusAfterCancel: 'cancelled', - }, - { - ...FIVE_M_PRO_SCENARIO, - label: '5M Pro (forced legacy)', - expectsCheckCodePrompt: false, - requiresCustomLedSetting: true, - supportsLedControls: true, - supportsFiltration: false, - verifyLegacyUnsupportedControls: true, - expectedUiStateAfterCancel: 'Ready', - expectedDetailStatusAfterCancel: 'cancelled', - }, -]; - -const runSingleModelFlow = async (params: { - scenario: LifecycleScenario; - mode: ConnectionMode; - fileName?: string; - seedFile?: SeedRecentFileOptions; - expectMaterialMatching?: boolean; - materialSlotAssignments?: readonly MaterialSlotAssignment[]; - seededPrinters?: readonly SeededPrinterDetailsEntry[]; - expectForceLegacyModeSetting?: boolean; - expectFiltrationControlsDisabled?: boolean; - skipJobLifecycle?: boolean; -}): Promise => { - const discoveryEnabled = params.mode === 'discovery'; - const tcpPort = params.mode === 'direct' ? 8899 : await getFreePort(); - const httpPort = params.mode === 'direct' ? 8898 : await getFreePort(); - - const emulator = await startEmulatorInstance({ - instance: { - instanceId: `single-${params.scenario.model}-${params.mode}`, - model: params.scenario.model, - serial: params.scenario.serial, - checkCode: params.scenario.checkCode, - machineName: params.scenario.machineName, - tcpPort, - httpPort, - discoveryEnabled, - simulationMode: 'auto', - simulationSpeed: 1, - }, - }); - - const readyPayload = emulator.readyPayloads[0]; - if (!readyPayload) { - await emulator.stop(); - throw new Error(`Missing readiness payload for ${params.scenario.label} (${params.mode})`); - } - - const emulatorAuth: EmulatorAuthConfig = { - httpPort: readyPayload.httpPort, - serial: readyPayload.serial, - checkCode: params.scenario.checkCode, - }; - const fileName = params.fileName ?? `e2e-${params.scenario.machineName.toLowerCase()}-${params.mode}.gcode`; - - await seedEmulatorRecentFile({ - ...emulatorAuth, - fileName, - ...(params.seedFile ?? {}), - }); - - const launched = await launchElectronWithIsolatedProfile({ - seededPrinters: params.seededPrinters, - }); - - try { - const initialAutoConnectDialogTimeoutMs = - params.seededPrinters && params.seededPrinters.length > 0 - ? SEEDED_PRINTER_AUTOCONNECT_TIMEOUT_MS - : OPTIONAL_DIALOG_TIMEOUT_MS; - await maybeDismissAutoConnectChoiceDialog({ - electronApp: launched.electronApp, - timeoutMs: initialAutoConnectDialogTimeoutMs, - }); - - if (params.mode === 'direct') { - await connectThroughDirectIpDialog({ - electronApp: launched.electronApp, - mainWindow: launched.mainWindow, - ipAddress: LOCALHOST_IP, - checkCode: params.scenario.checkCode, - expectCheckCodePrompt: params.scenario.expectsCheckCodePrompt, - }); - } else { - const selectionText = - params.scenario.discoverySelection === 'serial' ? readyPayload.serial : params.scenario.machineName; - await connectThroughDiscoveryDialog({ - electronApp: launched.electronApp, - mainWindow: launched.mainWindow, - selectionText, - checkCode: params.scenario.checkCode, - expectCheckCodePrompt: params.scenario.expectsCheckCodePrompt, - }); - } - - await waitForConnectedUi(launched.mainWindow, 1); - await expect.poll(() => firstConnectedTabName(launched.mainWindow)).not.toBe(''); - await maybeDismissAutoConnectChoiceDialog({ - electronApp: launched.electronApp, - timeoutMs: OPTIONAL_DIALOG_TIMEOUT_MS, - }); - - if (params.expectForceLegacyModeSetting) { - await verifyForceLegacyModeSetting(launched.mainWindow); - } - - if (params.scenario.verifyLegacyUnsupportedControls) { - await verifyLegacyUnsupportedControls(launched.mainWindow); - } - - if (params.expectFiltrationControlsDisabled) { - await verifyFiltrationControlsDisabled(launched.mainWindow); - } - - await runLifecycleControls({ - electronApp: launched.electronApp, - mainWindow: launched.mainWindow, - fileName, - emulatorAuth, - requiresCustomLedSetting: params.scenario.requiresCustomLedSetting, - supportsLedControls: params.scenario.supportsLedControls, - supportsFiltration: params.scenario.supportsFiltration, - expectedUiStateAfterCancel: params.scenario.expectedUiStateAfterCancel, - expectedDetailStatusAfterCancel: params.scenario.expectedDetailStatusAfterCancel, - expectMaterialMatching: params.expectMaterialMatching, - materialSlotAssignments: params.materialSlotAssignments, - skipJobLifecycle: params.skipJobLifecycle, - }); - - if (!params.skipJobLifecycle) { - const finalDetail = await fetchEmulatorDetail(emulatorAuth); - expect(finalDetail.status).toBe('cancelled'); - } - launched.assertNoUnexpectedRendererErrors(); - } finally { - await closeLaunchedElectronApp(launched); - await emulator.stop(); - } -}; - -test.describe('electron emulator e2e', () => { - test.skip(!process.env[EMULATOR_FLAG], `Set ${EMULATOR_FLAG}=1 to run emulator-backed Electron desktop tests`); - test.skip(process.platform !== 'win32', 'This suite currently targets Windows environments'); - - test.describe('direct lifecycle flows', () => { - for (const scenario of ALL_LIFECYCLE_SCENARIOS) { - test(`direct ${scenario.label}: connect + lifecycle + controls`, async () => { - await runSingleModelFlow({ - scenario, - mode: 'direct', - }); - }); - } - - test('direct AD5X: multi-color start + lifecycle + controls', async () => { - await runSingleModelFlow({ - scenario: AD5X_SCENARIO, - mode: 'direct', - fileName: 'e2e-ad5x-direct-multicolor.3mf', - seedFile: { - gcodeToolCnt: AD5X_MULTI_COLOR_MAPPINGS.length, - useMatlStation: true, - materialMappings: AD5X_MULTI_COLOR_MAPPINGS, - }, - expectMaterialMatching: true, - materialSlotAssignments: AD5X_MULTI_COLOR_MAPPINGS.map((mapping) => ({ - toolId: mapping.toolId, - slotId: mapping.slotId, - })), - }); - }); - - for (const scenario of FORCE_LEGACY_DIRECT_SCENARIOS) { - test(`direct ${scenario.label}: connect + lifecycle + controls`, async () => { - await runSingleModelFlow({ - scenario, - mode: 'direct', - seededPrinters: [createForceLegacySeededPrinter(scenario)], - expectForceLegacyModeSetting: true, - expectFiltrationControlsDisabled: scenario.model === 'adventurer-5m-pro', - skipJobLifecycle: scenario.model === 'adventurer-5m-pro', - }); - }); - } - }); - - test.describe('discovery lifecycle flows', () => { - test.skip(!process.env[DISCOVERY_FLAG], `Set ${DISCOVERY_FLAG}=1 to run discovery-based emulator tests`); - - for (const scenario of ALL_LIFECYCLE_SCENARIOS) { - test(`discovery ${scenario.label}: connect + lifecycle + controls`, async () => { - await runSingleModelFlow({ - scenario, - mode: 'discovery', - }); - }); - } - - test('discovery AD5X: multi-color start + lifecycle + controls', async () => { - await runSingleModelFlow({ - scenario: AD5X_SCENARIO, - mode: 'discovery', - fileName: 'e2e-ad5x-discovery-multicolor.3mf', - seedFile: { - gcodeToolCnt: AD5X_MULTI_COLOR_MAPPINGS.length, - useMatlStation: true, - materialMappings: AD5X_MULTI_COLOR_MAPPINGS, - }, - expectMaterialMatching: true, - materialSlotAssignments: AD5X_MULTI_COLOR_MAPPINGS.map((mapping) => ({ - toolId: mapping.toolId, - slotId: mapping.slotId, - })), - }); - }); - }); - - test.describe('multi-printer discovery flow', () => { - test.skip(!process.env[DISCOVERY_FLAG], `Set ${DISCOVERY_FLAG}=1 to run discovery-based emulator tests`); - - let supervisorEmulator: Awaited> | null = null; - let alphaReady: EmulatorReadyPayload | null = null; - let betaReady: EmulatorReadyPayload | null = null; - let gammaReady: EmulatorReadyPayload | null = null; - - test.beforeAll(async () => { - const [alphaTcpPort, alphaHttpPort, betaTcpPort, betaHttpPort, gammaTcpPort, gammaHttpPort] = - await getDistinctFreePorts(6); - - supervisorEmulator = await startEmulatorSupervisor({ - instances: [ - { - instanceId: 'alpha', - model: 'adventurer-5x', - serial: 'E2E-SN-ALPHA', - checkCode: DEFAULT_CHECK_CODE, - machineName: 'E2E-Alpha', - tcpPort: alphaTcpPort, - httpPort: alphaHttpPort, - discoveryEnabled: true, - simulationMode: 'auto', - simulationSpeed: 100, - }, - { - instanceId: 'beta', - model: 'adventurer-5m', - serial: 'E2E-SN-BETA', - checkCode: DEFAULT_CHECK_CODE, - machineName: 'E2E-Beta', - tcpPort: betaTcpPort, - httpPort: betaHttpPort, - discoveryEnabled: true, - simulationMode: 'auto', - simulationSpeed: 100, - }, - { - instanceId: 'gamma', - model: 'adventurer-5m-pro', - serial: 'E2E-SN-GAMMA', - checkCode: DEFAULT_CHECK_CODE, - machineName: 'E2E-Gamma', - tcpPort: gammaTcpPort, - httpPort: gammaHttpPort, - discoveryEnabled: true, - simulationMode: 'auto', - simulationSpeed: 100, - }, - ], - }); - - const alphaPayload = supervisorEmulator.readyPayloads.find((payload) => payload.instanceId === 'alpha'); - const betaPayload = supervisorEmulator.readyPayloads.find((payload) => payload.instanceId === 'beta'); - const gammaPayload = supervisorEmulator.readyPayloads.find((payload) => payload.instanceId === 'gamma'); - if (!alphaPayload || !betaPayload || !gammaPayload) { - throw new Error('Supervisor readiness payloads missing alpha, beta, and/or gamma instance'); - } - - alphaReady = alphaPayload; - betaReady = betaPayload; - gammaReady = gammaPayload; - - for (const ready of [alphaPayload, betaPayload, gammaPayload]) { - await seedEmulatorRecentFile({ - httpPort: ready.httpPort, - serial: ready.serial, - checkCode: DEFAULT_CHECK_CODE, - fileName: `e2e-multi-${ready.instanceId}.gcode`, - }); - } - }); - - test.afterAll(async () => { - if (supervisorEmulator) { - await supervisorEmulator.stop(); - } - }); - - test('shows all discovered printers and connects each as separate contexts', async () => { - const launched = await launchElectronWithIsolatedProfile(); - - try { - await openConnectFlow(launched.mainWindow); - await maybeHandleConnectedWarningDialog(launched.electronApp); - - const connectChoiceDialog = await waitForWindowWithSelector(launched.electronApp, '#btn-scan-network', 15_000); - await connectChoiceDialog.locator('#btn-scan-network').click(); - - const selectionDialog = await waitForWindowWithSelector(launched.electronApp, '#printer-table', 35_000); - await expect( - selectionDialog.locator('#printer-table tbody tr[data-printer]', { - hasText: requireReadyPayload(alphaReady, 'alpha').serial, - }) - ).toBeVisible(); - await expect( - selectionDialog.locator('#printer-table tbody tr[data-printer]', { - hasText: requireReadyPayload(betaReady, 'beta').serial, - }) - ).toBeVisible(); - await expect( - selectionDialog.locator('#printer-table tbody tr[data-printer]', { - hasText: requireReadyPayload(gammaReady, 'gamma').serial, - }) - ).toBeVisible(); - - await selectPrinterFromDiscoveryDialog({ - electronApp: launched.electronApp, - rowText: requireReadyPayload(alphaReady, 'alpha').serial, - }); - await maybeSubmitCheckCodeDialog({ - electronApp: launched.electronApp, - checkCode: DEFAULT_CHECK_CODE, - required: true, - }); - await waitForConnectedUi(launched.mainWindow, 1); - - await connectThroughDiscoveryDialog({ - electronApp: launched.electronApp, - mainWindow: launched.mainWindow, - selectionText: requireReadyPayload(betaReady, 'beta').serial, - checkCode: DEFAULT_CHECK_CODE, - expectCheckCodePrompt: true, - }); - await waitForConnectedUi(launched.mainWindow, 2); - - await connectThroughDiscoveryDialog({ - electronApp: launched.electronApp, - mainWindow: launched.mainWindow, - selectionText: requireReadyPayload(gammaReady, 'gamma').serial, - checkCode: DEFAULT_CHECK_CODE, - expectCheckCodePrompt: true, - }); - await waitForConnectedUi(launched.mainWindow, 3); - - await expect - .poll( - async () => { - return await launched.mainWindow.locator('#printer-tabs-container .printer-tab').count(); - }, - { timeout: CONNECT_TIMEOUT_MS } - ) - .toBeGreaterThanOrEqual(3); - - launched.assertNoUnexpectedRendererErrors(); - } finally { - await closeLaunchedElectronApp(launched); - } - }); - }); - - test.describe('legacy multi-printer discovery flow', () => { - test.skip(!process.env[DISCOVERY_FLAG], `Set ${DISCOVERY_FLAG}=1 to run discovery-based emulator tests`); - - let supervisorEmulator: Awaited> | null = null; - test.beforeAll(async () => { - const [a3TcpPort, a3HttpPort, a4TcpPort, a4HttpPort] = await getDistinctFreePorts(4); - - supervisorEmulator = await startEmulatorSupervisor({ - instances: [ - { - instanceId: 'legacy-a3', - model: 'adventurer-3', - serial: 'E2E-SN-LEGACY-A3', - checkCode: DEFAULT_CHECK_CODE, - machineName: 'E2E Legacy A3', - tcpPort: a3TcpPort, - httpPort: a3HttpPort, - discoveryEnabled: true, - simulationMode: 'auto', - simulationSpeed: 100, - }, - { - instanceId: 'legacy-a4', - model: 'adventurer-4', - serial: 'E2E-SN-LEGACY-A4', - checkCode: DEFAULT_CHECK_CODE, - machineName: 'E2E Legacy A4', - tcpPort: a4TcpPort, - httpPort: a4HttpPort, - discoveryEnabled: true, - simulationMode: 'auto', - simulationSpeed: 100, - }, - ], - }); - - const a3Payload = supervisorEmulator.readyPayloads.find((payload) => payload.instanceId === 'legacy-a3'); - const a4Payload = supervisorEmulator.readyPayloads.find((payload) => payload.instanceId === 'legacy-a4'); - if (!a3Payload || !a4Payload) { - throw new Error('Supervisor readiness payloads missing legacy-a3 and/or legacy-a4 instance'); - } - - for (const ready of [a3Payload, a4Payload]) { - await seedEmulatorRecentFile({ - httpPort: ready.httpPort, - serial: ready.serial, - checkCode: DEFAULT_CHECK_CODE, - fileName: `e2e-legacy-multi-${ready.instanceId}.gcode`, - }); - } - }); - - test.afterAll(async () => { - if (supervisorEmulator) { - await supervisorEmulator.stop(); - } - }); - - test('shows A3 and A4 in discovery and connects both contexts', async () => { - const launched = await launchElectronWithIsolatedProfile(); - - try { - await openConnectFlow(launched.mainWindow); - await maybeHandleConnectedWarningDialog(launched.electronApp); - - const connectChoiceDialog = await waitForWindowWithSelector(launched.electronApp, '#btn-scan-network', 15_000); - await connectChoiceDialog.locator('#btn-scan-network').click(); - - const selectionDialog = await waitForWindowWithSelector(launched.electronApp, '#printer-table', 35_000); - await expect( - selectionDialog.locator('#printer-table tbody tr[data-printer]', { - hasText: 'E2E Legacy A3', - }) - ).toBeVisible(); - await expect( - selectionDialog.locator('#printer-table tbody tr[data-printer]', { - hasText: 'E2E Legacy A4', - }) - ).toBeVisible(); - - await selectPrinterFromDiscoveryDialog({ - electronApp: launched.electronApp, - rowText: 'E2E Legacy A3', - }); - await maybeSubmitCheckCodeDialog({ - electronApp: launched.electronApp, - checkCode: DEFAULT_CHECK_CODE, - timeoutMs: 2_000, - required: false, - }); - await waitForConnectedUi(launched.mainWindow, 1); - await verifyLegacyUnsupportedControls(launched.mainWindow); - - await connectThroughDiscoveryDialog({ - electronApp: launched.electronApp, - mainWindow: launched.mainWindow, - selectionText: 'E2E Legacy A4', - checkCode: DEFAULT_CHECK_CODE, - expectCheckCodePrompt: false, - }); - await waitForConnectedUi(launched.mainWindow, 2); - - await expect - .poll( - async () => { - return await launched.mainWindow.locator('#printer-tabs-container .printer-tab').count(); - }, - { timeout: CONNECT_TIMEOUT_MS } - ) - .toBeGreaterThanOrEqual(2); - - await expect.poll(() => firstConnectedTabName(launched.mainWindow)).not.toBe(''); - launched.assertNoUnexpectedRendererErrors(); - } finally { - await closeLaunchedElectronApp(launched); - } - }); - }); -}); diff --git a/tests/e2e/electron/desktop-smoke.spec.ts b/tests/e2e/electron/desktop-smoke.spec.ts deleted file mode 100644 index 47cb2e6..0000000 --- a/tests/e2e/electron/desktop-smoke.spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @fileoverview Live Electron Playwright smoke test for launching FlashForgeUI against - * the real local environment and verifying connected desktop UI rendering. - */ - -import path from 'node:path'; -import { type ElectronApplication, _electron as electron, expect, type Page, test } from '@playwright/test'; - -const LIVE_FLAG = 'FFUI_E2E_LIVE'; - -async function resolveMainWindow(electronApp: ElectronApplication): Promise { - const firstWindow = await electronApp.firstWindow(); - if ((await firstWindow.locator('#btn-main-menu').count()) > 0) { - return firstWindow; - } - - for (const page of electronApp.windows()) { - if ((await page.locator('#btn-main-menu').count()) > 0) { - return page; - } - } - - throw new Error('Unable to find main application window'); -} - -test.describe('electron desktop smoke', () => { - test.skip( - !process.env[LIVE_FLAG], - `Set ${LIVE_FLAG}=1 to run live Electron desktop smoke tests against your local environment` - ); - - test('launches FFUI, auto-connects, and renders connected UI elements', async () => { - test.skip(process.platform !== 'win32', 'This live smoke test currently targets Windows environments'); - - const electronApp = await electron.launch({ - args: ['.'], - cwd: process.cwd(), - timeout: 120_000, - }); - - try { - const userDataPath = await electronApp.evaluate(async ({ app }) => app.getPath('userData')); - const expectedUserDataPath = process.env.APPDATA ? path.join(process.env.APPDATA, 'FlashForgeUI') : null; - - if (expectedUserDataPath) { - expect(userDataPath.toLowerCase()).toBe(expectedUserDataPath.toLowerCase()); - } - - const mainWindow = await resolveMainWindow(electronApp); - - await expect(mainWindow.locator('.title')).toHaveText('FlashForgeUI'); - await expect(mainWindow.locator('#btn-main-menu')).toBeVisible(); - await expect(mainWindow.locator('#printer-tabs-container .printer-tab.status-connected').first()).toBeVisible({ - timeout: 150_000, - }); - await expect(mainWindow.locator('#printer-tabs-container .printer-tab .tab-name').first()).not.toHaveText(''); - await expect(mainWindow.locator('#grid-placeholder')).toBeHidden(); - await expect(mainWindow.locator('.grid-stack')).toBeVisible(); - } finally { - await electronApp.close(); - } - }); -}); diff --git a/tests/e2e/electron/pages/connect-dialogs.ts b/tests/e2e/electron/pages/connect-dialogs.ts new file mode 100644 index 0000000..ad2ec78 --- /dev/null +++ b/tests/e2e/electron/pages/connect-dialogs.ts @@ -0,0 +1,213 @@ +/** + * @fileoverview Page objects for the printer connection flow dialogs. + * + * Covers the connect-choice dialog, the network scan/discovery table, the + * manual connect form introduced in 1.0.5-alpha.9, and the generic check-code + * input prompt. + * + * The manual connect form is what broke the previous suite: "Enter IP" used to open + * a single-field prompt (#dialog-input / #dialog-ok), and now opens a full form + * (#input-ip / #input-type / #input-serial / #input-check-code / #dialog-connect). + * Because a named printer type skips the TCP probe, the form must supply the serial + * and check code that a discovery broadcast would otherwise have provided. + * + * Key exports: + * - ConnectChoiceDialog: scan-network vs enter-IP branch + * - ManualConnectDialog: the alpha.9 form + * - DiscoveryTable: the scan results list + * - CheckCodePrompt: the generic input dialog + */ + +import { type ElectronApplication, expect, type Page } from '@playwright/test'; +import { findWindowWithSelector, waitForWindowWithSelector } from '../support/electron-app'; + +/** Values accepted by the manual connect type dropdown (see shared/types/manual-connect.ts). */ +export type ManualConnectType = + | 'adventurer-5m' + | 'adventurer-5m-pro' + | 'ad5x' + | 'creator-5' + | 'creator-5-pro' + | 'legacy'; + +export class ConnectChoiceDialog { + constructor(readonly page: Page) {} + + static async waitFor(electronApp: ElectronApplication, timeoutMs = 20_000): Promise { + const page = await waitForWindowWithSelector(electronApp, '#btn-scan-network', timeoutMs); + return new ConnectChoiceDialog(page); + } + + async chooseScanNetwork(): Promise { + await this.page.locator('#btn-scan-network').click(); + } + + async chooseEnterIp(): Promise { + await this.page.locator('#btn-enter-ip').click(); + } +} + +/** + * Shown at startup when the saved profile holds more than one printer. + * + * A single saved printer auto-connects silently; two or more make the app ask which + * one to use, which is why multi-printer runs have to drive this and single-printer + * ones never see it. + */ +export class AutoConnectChoiceDialog { + constructor(readonly page: Page) {} + + static async findOptional( + electronApp: ElectronApplication, + timeoutMs = 10_000 + ): Promise { + const page = await findWindowWithSelector(electronApp, '#btn-connect-last-used', timeoutMs); + return page ? new AutoConnectChoiceDialog(page) : null; + } + + async connectToLastUsed(): Promise { + await this.page.locator('#btn-connect-last-used').click(); + } + + async showAllSavedPrinters(): Promise { + await this.page.locator('#btn-show-saved-printers').click(); + } + + async cancel(): Promise { + await this.page.locator('#btn-cancel').click(); + } +} + +export class ManualConnectDialog { + constructor(readonly page: Page) {} + + static async waitFor(electronApp: ElectronApplication, timeoutMs = 20_000): Promise { + const page = await waitForWindowWithSelector(electronApp, '#input-ip', timeoutMs); + return new ManualConnectDialog(page); + } + + /** + * Fills the form. Serial and check code are only present for modern types - + * selecting "legacy" hides them, since a legacy printer is still TCP-probed. + */ + async fill(params: { + ipAddress: string; + type: ManualConnectType; + serialNumber?: string; + checkCode?: string; + }): Promise { + await this.page.locator('#input-ip').fill(params.ipAddress); + await this.page.locator('#input-type').selectOption(params.type); + + if (params.type !== 'legacy') { + if (!params.serialNumber || !params.checkCode) { + throw new Error(`Manual connect type "${params.type}" requires both a serial number and a check code`); + } + await this.page.locator('#input-serial').fill(params.serialNumber); + await this.page.locator('#input-check-code').fill(params.checkCode); + } + } + + async submit(): Promise { + const connectButton = this.page.locator('#dialog-connect'); + await expect(connectButton).toBeEnabled(); + await connectButton.click(); + } + + async cancel(): Promise { + await this.page.locator('#dialog-cancel').click(); + } + + async getErrorText(): Promise { + return ((await this.page.locator('#dialog-error').textContent()) ?? '').trim(); + } + + /** True when the serial/check-code fields are showing (i.e. a modern type is selected). */ + async requiresCredentials(): Promise { + return await this.page.locator('#field-serial').isVisible(); + } +} + +export class DiscoveryTable { + constructor(readonly page: Page) {} + + static async waitFor(electronApp: ElectronApplication, timeoutMs = 60_000): Promise { + const page = await waitForWindowWithSelector(electronApp, '#printer-table', timeoutMs); + return new DiscoveryTable(page); + } + + /** + * The same #printer-table markup backs both the discovery results and the + * "Select a Saved Printer" dialog, so this resolves either without caring which. + */ + static async findOptional(electronApp: ElectronApplication, timeoutMs = 5_000): Promise { + const page = await findWindowWithSelector(electronApp, '#printer-table', timeoutMs); + return page ? new DiscoveryTable(page) : null; + } + + /** + * Matches on the row's data-printer payload rather than its rendered text. + * + * The serial column is visually truncated ("E2E-SN-5M..."), so text matching is + * fragile the moment a column narrows; the attribute always carries the full value. + */ + row(serialNumber: string) { + return this.page.locator(`#printer-table tbody tr[data-printer*="${serialNumber}"]`).first(); + } + + /** + * Waits for a printer matching `matchText` to appear, then connects to it. + * + * Rows carry their full payload in data-printer, so matching on a serial number + * works and is stable across DHCP changes. + * + * The dblclick closes this window on success, which races the action and surfaces as + * "Target page... has been closed". That specific error means the click landed, so it + * is swallowed here; genuine failures still surface when the caller asserts that a + * printer actually connected. + */ + async connectTo(matchText: string, timeoutMs = 60_000): Promise { + const row = this.row(matchText); + await expect(row).toBeVisible({ timeout: timeoutMs }); + + await row.dblclick().catch((error: unknown) => { + const message = error instanceof Error ? error.message : String(error); + if (!/has been closed/i.test(message)) { + throw error; + } + }); + } + + async getRowCount(): Promise { + return await this.page.locator('#printer-table tbody tr[data-printer]').count(); + } +} + +export class CheckCodePrompt { + constructor(readonly page: Page) {} + + /** + * Returns the prompt only if it appears. A manual connect that already supplied a + * check code should NOT produce a second prompt, so specs use this to assert absence. + */ + static async findOptional(electronApp: ElectronApplication, timeoutMs = 3_000): Promise { + const page = await findWindowWithSelector(electronApp, '#dialog-input', timeoutMs); + return page ? new CheckCodePrompt(page) : null; + } + + async submit(checkCode: string): Promise { + await this.page.locator('#dialog-input').fill(checkCode); + await this.page.locator('#dialog-ok').click(); + } +} + +/** Dismisses the "already connected" warning if the app raises it. */ +export const dismissConnectedWarningIfPresent = async ( + electronApp: ElectronApplication, + timeoutMs = 1_000 +): Promise => { + const warning = await findWindowWithSelector(electronApp, '#dialog-continue', timeoutMs); + if (warning) { + await warning.locator('#dialog-continue').click(); + } +}; diff --git a/tests/e2e/electron/pages/job-dialogs.ts b/tests/e2e/electron/pages/job-dialogs.ts new file mode 100644 index 0000000..1645a09 --- /dev/null +++ b/tests/e2e/electron/pages/job-dialogs.ts @@ -0,0 +1,260 @@ +/** + * @fileoverview Page objects for the job uploader, material matching, and file manager dialogs. + * + * File selection needs special handling: the uploader's Browse button calls + * dialog.showOpenDialog() in the main process, which opens a native OS window that + * Playwright cannot drive. stubFileDialog() replaces that method for the lifetime of + * the app so Browse resolves straight to a fixture path. + * + * Key exports: + * - stubFileDialog(): make native Browse return a chosen path + * - JobUploaderDialog: file selection, Start Now / auto-level checkboxes, confirm + * - MaterialMatchingDialog: the multi-tool mapping dialog (AD5X / Creator 5 only) + * - FileManagerDialog: SFTP browse + delete + */ + +import { type ElectronApplication, expect, type Page } from '@playwright/test'; +import { findWindowWithSelector, waitForWindowWithSelector } from '../support/electron-app'; + +/** + * Forces the main process's native open-file dialog to return `filePath`. + * + * Playwright drives renderer DOM only; a native dialog would block the run forever. + * Patching in the main process is the supported way around that. + */ +export const stubFileDialog = async (electronApp: ElectronApplication, filePath: string): Promise => { + await electronApp.evaluate(async ({ dialog }, chosenPath) => { + // Deliberately overriding the Electron API for the test run. + dialog.showOpenDialog = async () => ({ canceled: false, filePaths: [chosenPath] }); + }, filePath); +}; + +/** Makes the native open-file dialog behave as if the user cancelled. */ +export const stubFileDialogCancelled = async (electronApp: ElectronApplication): Promise => { + await electronApp.evaluate(async ({ dialog }) => { + // Deliberately overriding the Electron API for the test run. + dialog.showOpenDialog = async () => ({ canceled: true, filePaths: [] }); + }); +}; + +export class JobUploaderDialog { + constructor(readonly page: Page) {} + + static async waitFor(electronApp: ElectronApplication, timeoutMs = 20_000): Promise { + const page = await waitForWindowWithSelector(electronApp, '#btn-browse', timeoutMs); + return new JobUploaderDialog(page); + } + + /** Clicks Browse (resolved by the stub) and waits for metadata parsing to finish. */ + async browseForFile(timeoutMs = 60_000): Promise { + await this.page.locator('#btn-browse').click(); + await expect(this.page.locator('#loading-overlay')).toBeHidden({ timeout: timeoutMs }); + } + + async getSelectedFileName(): Promise { + return ((await this.page.locator('#file-path-display').textContent()) ?? '').trim(); + } + + /** + * Guarantees Start Now is unchecked. + * + * This is the safety gate for every upload in the suite: with it unchecked the app + * only transfers the file. Asserting rather than assuming means a changed default + * fails the test instead of quietly heating a real printer. + */ + async ensureStartNowUnchecked(): Promise { + const checkbox = this.page.locator('#cb-start-now'); + if (await checkbox.isChecked()) { + await checkbox.uncheck(); + } + await expect(checkbox).not.toBeChecked(); + } + + async setAutoLevel(enabled: boolean): Promise { + const checkbox = this.page.locator('#cb-auto-level'); + if ((await checkbox.isChecked()) !== enabled) { + await checkbox.setChecked(enabled); + } + } + + async isConfirmEnabled(): Promise { + return await this.page.locator('#btn-ok').isEnabled(); + } + + async confirm(): Promise { + const okButton = this.page.locator('#btn-ok'); + await expect(okButton).toBeEnabled(); + await okButton.click(); + } + + async cancel(): Promise { + await this.page.locator('#btn-cancel').click(); + } + + async getPrinterModelMeta(): Promise { + return ((await this.page.locator('#meta-printer').textContent()) ?? '').trim(); + } + + /** + * Waits for the upload to finish. + * + * Success is signalled by the dialog window closing: the renderer shows + * "Successfully uploaded " in the progress overlay and then self-closes after + * ~2s. The overlay is therefore still visible at the moment of success, so waiting + * for it to hide would hang until the timeout. + * + * Failure keeps the window open and writes the reason into #progress-status, which + * is surfaced here so a failed upload reports why instead of just timing out. + */ + async waitForUploadToComplete(electronApp: ElectronApplication, timeoutMs = 180_000): Promise { + const deadline = Date.now() + timeoutMs; + + while (Date.now() < deadline) { + if (this.page.isClosed()) { + return; + } + + const status = await this.page + .locator('#progress-status') + .textContent() + .catch(() => null); + + if (status && /upload failed/i.test(status)) { + throw new Error(`Upload reported failure: ${status.trim()}`); + } + + await new Promise((resolve) => setTimeout(resolve, 250)); + } + + const lastStatus = await this.page + .locator('#progress-status') + .textContent() + .catch(() => null); + throw new Error( + `Upload did not complete within ${timeoutMs}ms (last status: ${lastStatus?.trim() ?? 'unknown'})` + ); + } +} + +export class MaterialMatchingDialog { + constructor(readonly page: Page) {} + + /** Waits for the dialog, which only ever appears for material-station printers. */ + static async waitFor(electronApp: ElectronApplication, timeoutMs = 30_000): Promise { + const page = await waitForWindowWithSelector(electronApp, '#material-mappings', timeoutMs); + return new MaterialMatchingDialog(page); + } + + /** + * Returns the dialog if it appears within the (short) timeout, else null. + * Used for the negative assertion on 5M-series and legacy printers. + */ + static async findOptional( + electronApp: ElectronApplication, + timeoutMs = 5_000 + ): Promise { + const page = await findWindowWithSelector(electronApp, '#material-mappings', timeoutMs); + return page ? new MaterialMatchingDialog(page) : null; + } + + async getRequirementCount(): Promise { + return await this.page.locator('.requirement-item').count(); + } + + /** Assigns a tool requirement to a specific material station slot. */ + async assignToolToSlot(toolId: number, slotId: number): Promise { + await this.#selectRequirement(toolId); + + const slot = this.page.locator(`.slot-item[data-slot-id="${slotId}"]:not(.disabled):not(.assigned)`).first(); + await expect(slot, `slot ${slotId} should be selectable for tool ${toolId}`).toBeVisible(); + await slot.click(); + } + + /** + * Assigns a tool to whichever slot is currently selectable. + * + * Slot numbers are not interchangeable on real hardware: the dialog disables empty + * slots and slots whose material does not match the tool, so which slot is usable + * depends on what filament is physically loaded. On this bench's AD5X only slot 4 + * holds filament, so assuming slot 1 fails. Picking the first available slot is both + * what a user does and portable across machines. + */ + async assignToolToFirstAvailableSlot(toolId: number): Promise { + await this.#selectRequirement(toolId); + + const slot = this.page.locator('.slot-item:not(.disabled):not(.assigned)').first(); + await expect(slot, `no selectable material station slot for tool ${toolId}`).toBeVisible(); + + const slotId = await slot.getAttribute('data-slot-id'); + await slot.click(); + + return Number(slotId ?? 0); + } + + async #selectRequirement(toolId: number): Promise { + const requirement = this.page.locator(`.requirement-item[data-tool-id="${toolId}"]`).first(); + await expect(requirement).toBeVisible(); + await requirement.click(); + } + + async confirm(): Promise { + const confirmButton = this.page.locator('#btn-confirm'); + await expect(confirmButton).toBeEnabled(); + await confirmButton.click(); + } + + async cancel(): Promise { + await this.page.locator('#btn-cancel').click(); + } +} + +export class FileManagerDialog { + constructor(readonly page: Page) {} + + static async waitFor(electronApp: ElectronApplication, timeoutMs = 60_000): Promise { + const page = await waitForWindowWithSelector(electronApp, '#fm-grid', timeoutMs); + return new FileManagerDialog(page); + } + + /** Waits for the SFTP listing to finish loading. */ + async waitForListing(timeoutMs = 60_000): Promise { + await expect(this.page.locator('#fm-loading')).toBeHidden({ timeout: timeoutMs }); + } + + /** + * Tiles are keyed by full remote path (e.g. /usr/data/gcodes/foo.3mf), so match on + * the trailing path segment rather than requiring the spec to know the directory. + */ + fileEntry(fileName: string) { + return this.page.locator(`#fm-grid .fm-item[data-path$="/${fileName}"]`).first(); + } + + async hasFile(fileName: string): Promise { + return (await this.fileEntry(fileName).count()) > 0; + } + + async refresh(): Promise { + await this.page.locator('#btn-refresh').click(); + await this.waitForListing(); + } + + /** Selects a file and deletes it, confirming the overlay prompt. */ + async deleteFile(fileName: string): Promise { + const entry = this.fileEntry(fileName); + await expect(entry).toBeVisible(); + await entry.click(); + + const deleteButton = this.page.locator('#btn-delete-selected'); + await expect(deleteButton).toBeEnabled(); + await deleteButton.click(); + + const confirmOverlay = this.page.locator('#confirm-overlay'); + await expect(confirmOverlay).toBeVisible(); + await this.page.locator('#btn-confirm-delete').click(); + await expect(confirmOverlay).toBeHidden({ timeout: 30_000 }); + } + + async close(): Promise { + await this.page.locator('#btn-close-footer').click(); + } +} diff --git a/tests/e2e/electron/pages/main-window.ts b/tests/e2e/electron/pages/main-window.ts new file mode 100644 index 0000000..c549277 --- /dev/null +++ b/tests/e2e/electron/pages/main-window.ts @@ -0,0 +1,161 @@ +/** + * @fileoverview Page object for the FlashForgeUI main window. + * + * Wraps the shell chrome that every scenario touches: opening the connect flow, + * waiting for a printer context to come up, reading printer tabs, driving the LED + * controls, and opening shortcut-only dialogs such as the file manager. + * + * Selectors live here and nowhere else. When a flow changes (as the connect flow did + * in 1.0.5-alpha.9), this is the single file that needs updating instead of every spec. + */ + +import { type ElectronApplication, expect, type Page } from '@playwright/test'; + +const CONNECT_TIMEOUT_MS = 60_000; + +export class MainWindow { + constructor( + readonly page: Page, + readonly electronApp: ElectronApplication + ) {} + + /** + * Opens the connect flow from whichever entry point is currently showing. + * Before any printer is connected the app shows a placeholder button; afterwards + * the same flow is only reachable through the hamburger menu. + */ + async openConnectFlow(): Promise { + const placeholderButton = this.page.locator('#placeholder-connect-btn'); + if (await placeholderButton.isVisible().catch(() => false)) { + await placeholderButton.click(); + return; + } + + await expect(this.page.locator('#btn-main-menu')).toBeVisible(); + await this.page.locator('#btn-main-menu').click(); + + const connectMenuItem = this.page.locator('#main-menu-dropdown .menu-item[data-action="connect"]'); + await expect(connectMenuItem).toBeVisible(); + await connectMenuItem.click(); + } + + /** Clicks the "+" tab button to connect an additional printer. */ + async addPrinterTab(): Promise { + const button = this.page.locator('#add-printer-tab'); + await expect(button).toBeVisible(); + await button.click(); + } + + /** Number of printer tabs currently in the connected state. */ + async getConnectedTabCount(): Promise { + return await this.page.locator('#printer-tabs-container .printer-tab.status-connected').count(); + } + + async getTabNames(): Promise { + return await this.page.locator('#printer-tabs-container .printer-tab .tab-name').allTextContents(); + } + + /** Waits until at least `expected` printer tabs report connected. */ + async waitForConnectedPrinters(expected = 1, timeoutMs = CONNECT_TIMEOUT_MS): Promise { + await expect + .poll(async () => await this.getConnectedTabCount(), { + timeout: timeoutMs, + message: `Expected at least ${expected} connected printer tab(s)`, + }) + .toBeGreaterThanOrEqual(expected); + } + + /** Asserts the dashboard replaced the empty-state placeholder. */ + async expectDashboardVisible(): Promise { + await expect(this.page.locator('#grid-placeholder')).toBeHidden(); + await expect(this.page.locator('.grid-stack')).toBeVisible(); + } + + async getStatusText(): Promise { + const text = await this.page.locator('#printer-status-text').first().textContent(); + return (text ?? '').replace(/\s+/g, ' ').trim(); + } + + /** + * Waits until the controls grid reports a live connection. + * + * A printer tab flips to "connected" as soon as the connection is established, but + * the control buttons stay disabled until the first polling update delivers + * connectionState. Those are seconds apart, so specs must wait for this rather than + * for the tab, or they race the poll and see "Disabled: No connection". + */ + async waitForControlsReady(timeoutMs = 60_000): Promise { + await expect(this.page.locator('#btn-led-on')).toBeEnabled({ timeout: timeoutMs }); + } + + async clickLedOn(): Promise { + const button = this.page.locator('#btn-led-on'); + await expect(button).toBeVisible(); + await expect(button).toBeEnabled(); + await button.click(); + } + + async clickLedOff(): Promise { + const button = this.page.locator('#btn-led-off'); + await expect(button).toBeVisible(); + await expect(button).toBeEnabled(); + await button.click(); + } + + /** + * Pins a shortcut-only component to a topbar slot if it is not already there. + * + * Shortcut assignments default to empty and live in renderer localStorage + * ('shortcut-buttons-config'), not in the userData files the profile seeder writes, + * so a fresh isolated profile shows no shortcut buttons at all. Components that are + * only reachable this way - the file manager has no menu entry - therefore have to be + * pinned before a test can open them. The renderer reads the config once at startup, + * hence the reload. + */ + async ensureShortcut(componentId: string, slot: 1 | 2 | 3 = 1): Promise { + const visible = await this.page.locator(`[data-component-id="${componentId}"]:not(.hidden)`).count(); + if (visible > 0) { + return; + } + + await this.page.evaluate( + ({ id, slotNumber }) => { + const config = { + version: 1, + slots: { slot1: null as string | null, slot2: null as string | null, slot3: null as string | null }, + lastModified: new Date().toISOString(), + }; + config.slots[`slot${slotNumber}` as 'slot1' | 'slot2' | 'slot3'] = id; + localStorage.setItem('shortcut-buttons-config', JSON.stringify(config)); + }, + { id: componentId, slotNumber: slot } + ); + + await this.page.reload(); + await expect(this.page.locator('.title')).toHaveText('FlashForgeUI'); + await expect(this.page.locator(`[data-component-id="${componentId}"]:not(.hidden)`).first()).toBeVisible({ + timeout: 30_000, + }); + } + + /** Opens a shortcut-only dialog (file manager, etc.) from the topbar. */ + async openShortcut(componentId: string): Promise { + const button = this.page.locator(`[data-component-id="${componentId}"]:not(.hidden)`).first(); + await expect(button).toBeVisible(); + await button.click(); + } + + /** + * Opens the job uploader from the controls grid. + * + * The button is intentionally not gated on an active connection (you can stage an + * upload before connecting) but IS disabled during an active job, so specs must + * ensure the printer is idle first. + */ + async openJobUploader(): Promise { + const button = this.page.locator('#btn-upload-job'); + await expect(button).toBeVisible(); + await expect(button).toBeEnabled(); + await button.click(); + } +} diff --git a/tests/e2e/electron/specs/connect.spec.ts b/tests/e2e/electron/specs/connect.spec.ts new file mode 100644 index 0000000..6a0373d --- /dev/null +++ b/tests/e2e/electron/specs/connect.spec.ts @@ -0,0 +1,129 @@ +/** + * @fileoverview Connection coverage: saved-printer auto-connect, network discovery, + * and the manual connect form. + * + * Runs against whichever track FFUI_E2E_TRACK selects, so the same assertions cover + * emulated printers in CI and real printers on a bench. + * + * The manual connect case is the one that matters most here. Since 1.0.5-alpha.9 a + * named printer type skips the TCP probe, which means the form has to supply the + * serial and check code the discovery broadcast would have carried - and the check + * code it collects must be used directly, with no second prompt. That regression is + * exactly what this spec pins down. + */ + +import { expect, test } from '@playwright/test'; +import { + CheckCodePrompt, + ConnectChoiceDialog, + DiscoveryTable, + dismissConnectedWarningIfPresent, + ManualConnectDialog, +} from '../pages/connect-dialogs'; +import { MainWindow } from '../pages/main-window'; +import { closeFFUI, launchFFUI, type LaunchedApp } from '../support/electron-app'; +import type { PrinterTarget } from '../support/printer-target'; +import { describeTrackSkipReason, getTrack, listTargetDescriptors } from '../support/track'; + +const descriptors = listTargetDescriptors(); +const skipReason = describeTrackSkipReason(descriptors); + +test.describe(`connect (${getTrack()} track)`, () => { + test.skip(skipReason !== null, skipReason ?? ''); + + for (const descriptor of descriptors) { + test.describe(descriptor.label, () => { + let target: PrinterTarget; + let app: LaunchedApp; + + test.beforeAll(async () => { + target = await descriptor.create(); + }); + + test.afterAll(async () => { + await target?.dispose(); + }); + + test.afterEach(async () => { + if (app) { + await closeFFUI(app); + } + }); + + test('connects automatically to a saved printer', async () => { + app = await launchFFUI({ seededPrinters: [target.toSeededPrinter()] }); + const mainWindow = new MainWindow(app.mainWindow, app.electronApp); + + await mainWindow.waitForConnectedPrinters(1); + await mainWindow.expectDashboardVisible(); + + const tabNames = await mainWindow.getTabNames(); + expect(tabNames.join(' ')).toContain(target.toSeededPrinter().Name); + + app.assertNoRendererErrors(); + }); + + test('finds the printer through network discovery and connects', async () => { + app = await launchFFUI(); + const mainWindow = new MainWindow(app.mainWindow, app.electronApp); + + await mainWindow.openConnectFlow(); + const connectChoice = await ConnectChoiceDialog.waitFor(app.electronApp); + await connectChoice.chooseScanNetwork(); + + const discoveryTable = await DiscoveryTable.waitFor(app.electronApp); + // Match on serial: it is the only identity that survives a DHCP lease change, + // and other printers may legitimately be on the same network. + await discoveryTable.connectTo(target.serialNumber); + + const prompt = await CheckCodePrompt.findOptional(app.electronApp, 5_000); + if (prompt) { + await prompt.submit(target.checkCode); + } + + await mainWindow.waitForConnectedPrinters(1); + await mainWindow.expectDashboardVisible(); + + app.assertNoRendererErrors(); + }); + + test('connects through the manual connect form without prompting twice for the check code', async () => { + test.skip( + !descriptor.supportsManualConnect, + 'Manual connect always dials the firmware default ports (8899/8898); this emulator instance runs on alternate ports so only one instance per machine can be reached this way.' + ); + + app = await launchFFUI(); + const mainWindow = new MainWindow(app.mainWindow, app.electronApp); + + await mainWindow.openConnectFlow(); + const connectChoice = await ConnectChoiceDialog.waitFor(app.electronApp); + await connectChoice.chooseEnterIp(); + + const manualConnect = await ManualConnectDialog.waitFor(app.electronApp); + + // Modern types must ask for credentials; legacy must not. + expect(await manualConnect.requiresCredentials()).toBe(target.manualConnectType !== 'legacy'); + + await manualConnect.fill({ + ipAddress: target.ipAddress, + type: target.manualConnectType, + serialNumber: target.serialNumber, + checkCode: target.checkCode, + }); + await manualConnect.submit(); + + await dismissConnectedWarningIfPresent(app.electronApp); + + // The form already collected the check code, so a second prompt is a regression. + const duplicatePrompt = await CheckCodePrompt.findOptional(app.electronApp, 4_000); + expect(duplicatePrompt, 'manual connect should not prompt for the check code twice').toBeNull(); + + await mainWindow.waitForConnectedPrinters(1); + await mainWindow.expectDashboardVisible(); + + app.assertNoRendererErrors(); + }); + }); + } +}); diff --git a/tests/e2e/electron/specs/led.spec.ts b/tests/e2e/electron/specs/led.spec.ts new file mode 100644 index 0000000..46649df --- /dev/null +++ b/tests/e2e/electron/specs/led.spec.ts @@ -0,0 +1,70 @@ +/** + * @fileoverview LED control coverage: on -> off -> on. + * + * Every assertion reads lightStatus back from the printer's own /detail endpoint + * rather than inspecting the button's rendered state. A button that toggles its own + * styling while the command never reaches the printer is precisely the failure this + * is meant to catch, so trusting the UI here would defeat the purpose. + * + * The cycle ends with the LED back on, which is the state a user leaves a printer in. + */ + +import { expect, test } from '@playwright/test'; +import { MainWindow } from '../pages/main-window'; +import { closeFFUI, launchFFUI, type LaunchedApp } from '../support/electron-app'; +import type { PrinterTarget } from '../support/printer-target'; +import { describeTrackSkipReason, getTrack, listTargetDescriptors } from '../support/track'; + +const descriptors = listTargetDescriptors(); +const skipReason = describeTrackSkipReason(descriptors); + +test.describe(`LED control (${getTrack()} track)`, () => { + test.skip(skipReason !== null, skipReason ?? ''); + + for (const descriptor of descriptors) { + test.describe(descriptor.label, () => { + let target: PrinterTarget; + let app: LaunchedApp; + + test.beforeAll(async () => { + target = await descriptor.create(); + }); + + test.afterAll(async () => { + await target?.dispose(); + }); + + test.afterEach(async () => { + if (app) { + await closeFFUI(app); + } + }); + + test('cycles the LED on, off, and back on', async () => { + app = await launchFFUI({ seededPrinters: [target.toSeededPrinter()] }); + const mainWindow = new MainWindow(app.mainWindow, app.electronApp); + + await mainWindow.waitForConnectedPrinters(1); + await mainWindow.expectDashboardVisible(); + await mainWindow.waitForControlsReady(); + + // Start from a known state so the first assertion cannot pass by accident. + await target.client.setLight('close'); + expect(await target.client.waitForLightStatus('close')).toBe(true); + + await mainWindow.clickLedOn(); + expect(await target.client.waitForLightStatus('open'), 'LED should report open after clicking on').toBe(true); + + await mainWindow.clickLedOff(); + expect(await target.client.waitForLightStatus('close'), 'LED should report close after clicking off').toBe( + true + ); + + await mainWindow.clickLedOn(); + expect(await target.client.waitForLightStatus('open'), 'LED should report open again').toBe(true); + + app.assertNoRendererErrors(); + }); + }); + } +}); diff --git a/tests/e2e/electron/specs/multi-printer.spec.ts b/tests/e2e/electron/specs/multi-printer.spec.ts new file mode 100644 index 0000000..6f5d0bb --- /dev/null +++ b/tests/e2e/electron/specs/multi-printer.spec.ts @@ -0,0 +1,120 @@ +/** + * @fileoverview Multi-printer coverage: two printers connected at once, each in its + * own context. + * + * Multi-context is where cross-talk bugs hide - one printer's polling updating another + * printer's tab, or a context switch leaving the dashboard showing stale data. The + * check that matters is that both tabs report connected simultaneously and that each + * tab carries its own printer's name. + * + * This follows the real user flow rather than a shortcut. With more than one saved + * printer the app does not silently connect them all: it raises the auto-connect + * choice dialog, the user picks one, and the second is added afterwards with the "+" + * tab button. Seeding two printers and waiting for two tabs would simply hang. + */ + +import { expect, test } from '@playwright/test'; +import { + AutoConnectChoiceDialog, + CheckCodePrompt, + ConnectChoiceDialog, + DiscoveryTable, + dismissConnectedWarningIfPresent, +} from '../pages/connect-dialogs'; +import { MainWindow } from '../pages/main-window'; +import { closeFFUI, launchFFUI, type LaunchedApp } from '../support/electron-app'; +import type { PrinterTarget } from '../support/printer-target'; +import { describeTrackSkipReason, getTrack, listMultiPrinterDescriptors } from '../support/track'; + +const descriptors = listMultiPrinterDescriptors(); +const skipReason = describeTrackSkipReason(descriptors); +const hasTwoPrinters = descriptors.length >= 2; + +test.describe(`multi-printer contexts (${getTrack()} track)`, () => { + test.skip(skipReason !== null, skipReason ?? ''); + test.skip(!hasTwoPrinters, 'Multi-printer coverage needs at least two printers on this track.'); + + const targets: PrinterTarget[] = []; + let app: LaunchedApp; + + test.beforeAll(async () => { + for (const descriptor of descriptors.slice(0, 2)) { + targets.push(await descriptor.create()); + } + }); + + test.afterAll(async () => { + for (const target of targets) { + await target.dispose(); + } + }); + + test.afterEach(async () => { + if (app) { + await closeFFUI(app); + } + }); + + test('connects two printers into separate contexts', async () => { + const [first, second] = targets; + + app = await launchFFUI({ seededPrinters: targets.map((target) => target.toSeededPrinter()) }); + const mainWindow = new MainWindow(app.mainWindow, app.electronApp); + + // Two saved printers means the app asks which one to start with. Depending on what + // discovery turns up that is either the auto-connect choice dialog or the saved + // printer table, so handle whichever appears rather than assuming one. + const autoConnectChoice = await AutoConnectChoiceDialog.findOptional(app.electronApp, 10_000); + if (autoConnectChoice) { + await autoConnectChoice.connectToLastUsed(); + } else { + const savedTable = await DiscoveryTable.waitFor(app.electronApp, 20_000); + await savedTable.connectTo(first.serialNumber); + } + + const firstPrompt = await CheckCodePrompt.findOptional(app.electronApp, 5_000); + if (firstPrompt) { + await firstPrompt.submit(first.checkCode); + } + + await mainWindow.waitForConnectedPrinters(1); + await mainWindow.expectDashboardVisible(); + + // Add the second printer the way a user would. + const alreadyConnected = await mainWindow.getTabNames(); + const pending = alreadyConnected.some((name) => name.includes(first.toSeededPrinter().Name)) ? second : first; + + await mainWindow.addPrinterTab(); + + // With a printer already connected, "+" first raises a warning explaining that a + // second connection is about to be opened. It must be acknowledged before any + // connect UI appears. + await dismissConnectedWarningIfPresent(app.electronApp, 10_000); + + // "+" then lands on whichever entry point the app considers most useful given what + // is saved and discoverable, so accept any of them and steer to the printer table. + const savedTable = await DiscoveryTable.findOptional(app.electronApp, 8_000); + if (!savedTable) { + const connectChoice = await ConnectChoiceDialog.waitFor(app.electronApp); + await connectChoice.chooseScanNetwork(); + } + + const discoveryTable = savedTable ?? (await DiscoveryTable.waitFor(app.electronApp)); + await discoveryTable.connectTo(pending.serialNumber); + await dismissConnectedWarningIfPresent(app.electronApp); + + const prompt = await CheckCodePrompt.findOptional(app.electronApp, 5_000); + if (prompt) { + await prompt.submit(pending.checkCode); + } + + await mainWindow.waitForConnectedPrinters(2); + + const tabNames = (await mainWindow.getTabNames()).join(' '); + for (const target of targets) { + expect(tabNames, `expected a tab for ${target.label}`).toContain(target.toSeededPrinter().Name); + } + + app.assertNoRendererErrors(); + }); +}); diff --git a/tests/e2e/electron/specs/sftp-roundtrip.spec.ts b/tests/e2e/electron/specs/sftp-roundtrip.spec.ts new file mode 100644 index 0000000..71ed191 --- /dev/null +++ b/tests/e2e/electron/specs/sftp-roundtrip.spec.ts @@ -0,0 +1,129 @@ +/** + * @fileoverview Full SFTP round-trip: upload a file through the GUI, see it in the + * file manager, delete it there, and confirm it is gone. + * + * Hardware only. The emulator implements the printer HTTP/TCP APIs but runs no SSH + * server, so there is nothing for the file manager to talk to on that track. + * + * This doubles as the cleanup for the upload specs: the test file those leave behind + * is the file this one deletes. It therefore also proves the SSH/SFTP stack still + * works end to end - credentials resolved from SSHSettingsService, connection pooled + * per context, listing and delete both routed over SFTP. + * + * Requires FlashForge-EasySSH provisioning on the target printer (root/flashforge). + */ + +import { expect, test } from '@playwright/test'; +import { FileManagerDialog, JobUploaderDialog, MaterialMatchingDialog, stubFileDialog } from '../pages/job-dialogs'; +import { MainWindow } from '../pages/main-window'; +import { closeFFUI, launchFFUI, type LaunchedApp } from '../support/electron-app'; +import { resolveFixture, simplestFixtureFor } from '../support/fixtures'; +import { assertNotPrinting } from '../support/printer-client'; +import type { PrinterTarget } from '../support/printer-target'; +import { describeTrackSkipReason, getTrack, listTargetDescriptors } from '../support/track'; + +const descriptors = listTargetDescriptors().filter((descriptor) => descriptor.supportsSftp); +const skipReason = describeTrackSkipReason(listTargetDescriptors()); + +test.describe(`SFTP round-trip (${getTrack()} track)`, () => { + test.skip(skipReason !== null, skipReason ?? ''); + test.skip( + descriptors.length === 0, + 'No SFTP-capable printers on this track (the emulator has no SSH server; real printers need FlashForge-EasySSH).' + ); + + for (const descriptor of descriptors) { + test.describe(descriptor.label, () => { + let target: PrinterTarget; + let app: LaunchedApp; + + test.beforeAll(async () => { + target = await descriptor.create(); + }); + + test.afterAll(async () => { + await target?.dispose(); + }); + + test.afterEach(async () => { + if (app) { + await closeFFUI(app); + } + }); + + test('uploads a file, finds it over SFTP, deletes it, and confirms removal', async () => { + const fixture = simplestFixtureFor(descriptor.hasMaterialStation); + + app = await launchFFUI({ seededPrinters: [target.toSeededPrinter()] }); + const mainWindow = new MainWindow(app.mainWindow, app.electronApp); + + await mainWindow.waitForConnectedPrinters(1); + await mainWindow.expectDashboardVisible(); + await mainWindow.waitForControlsReady(); + + await stubFileDialog(app.electronApp, resolveFixture(fixture)); + await mainWindow.openJobUploader(); + + const uploader = await JobUploaderDialog.waitFor(app.electronApp); + await uploader.browseForFile(); + + // Material-station printers require every 3MF to be mapped to slots before the + // uploader's OK button enables. + if (descriptor.hasMaterialStation) { + const materialDialog = await MaterialMatchingDialog.waitFor(app.electronApp); + for (let toolId = 0; toolId < fixture.toolCount; toolId += 1) { + await materialDialog.assignToolToFirstAvailableSlot(toolId); + } + await materialDialog.confirm(); + } + + await uploader.ensureStartNowUnchecked(); + await uploader.confirm(); + await uploader.waitForUploadToComplete(app.electronApp); + + expect( + await target.waitForUploadedFile(fixture.remoteName), + 'file should be on the printer before the SFTP checks begin' + ).toBe(true); + + const safety = await assertNotPrinting(target.client); + if (safety.notes.length > 0) { + console.warn(safety.notes.join('\n')); + } + expect(safety.wasPrinting, `a print started despite Start Now being unchecked: ${safety.notes.join(' ')}`).toBe( + false + ); + + // Now the SFTP half: the file manager reads the printer's filesystem directly. + // It is shortcut-only, and a fresh profile has no shortcuts pinned. + await mainWindow.ensureShortcut('file-manager'); + await mainWindow.openShortcut('file-manager'); + const fileManager = await FileManagerDialog.waitFor(app.electronApp); + await fileManager.waitForListing(); + + expect( + await fileManager.hasFile(fixture.remoteName), + `${fixture.remoteName} should be listed by the SFTP file manager` + ).toBe(true); + + await fileManager.deleteFile(fixture.remoteName); + await fileManager.refresh(); + + expect( + await fileManager.hasFile(fixture.remoteName), + `${fixture.remoteName} should be gone from the listing after delete` + ).toBe(false); + + await fileManager.close(); + + // Confirm against the printer itself, not just the dialog's own rendering. + expect( + await target.waitForUploadedFile(fixture.remoteName, 5_000), + 'the printer should no longer report the deleted file' + ).toBe(false); + + app.assertNoRendererErrors(); + }); + }); + } +}); diff --git a/tests/e2e/electron/specs/upload.spec.ts b/tests/e2e/electron/specs/upload.spec.ts new file mode 100644 index 0000000..61ee9a9 --- /dev/null +++ b/tests/e2e/electron/specs/upload.spec.ts @@ -0,0 +1,155 @@ +/** + * @fileoverview Upload coverage, including the material matching dialog rules. + * + * This is the regression net for the 1.0.5-alpha.10 hotfix: pressing OK in the job + * uploader threw ReferenceError: isAD5X is not defined and silently uploaded nothing. + * A test that only checked the dialog rendered would have missed it - the failure was + * in the confirm handler - so every case here confirms the file actually landed on + * the printer via /gcodeList. + * + * Safety: uploads always run with Start Now explicitly unchecked, and every upload is + * followed by assertNotPrinting(), which cancels and clears the platform if a print + * ever started. That path should never fire; if it does the test fails loudly. + * + * Material matching rules under test: + * - any 3MF + material-station printer (AD5X) -> dialog appears, mapping required + * - multi-filament file + 5M-series printer -> dialog must NOT appear + * + * Note that on a material-station printer the dialog is not reserved for multi-colour + * files: the uploader raises it for every 3MF, single filament included, because each + * tool still has to be bound to a physical slot before the firmware can print. + */ + +import { expect, test } from '@playwright/test'; +import { JobUploaderDialog, MaterialMatchingDialog, stubFileDialog } from '../pages/job-dialogs'; +import { MainWindow } from '../pages/main-window'; +import { closeFFUI, launchFFUI, type LaunchedApp } from '../support/electron-app'; +import { PRINT_FIXTURES, resolveFixture, simplestFixtureFor } from '../support/fixtures'; +import { assertNotPrinting } from '../support/printer-client'; +import type { PrinterTarget } from '../support/printer-target'; +import { describeTrackSkipReason, getTrack, listTargetDescriptors } from '../support/track'; + +const descriptors = listTargetDescriptors(); +const skipReason = describeTrackSkipReason(descriptors); + +test.describe(`job upload (${getTrack()} track)`, () => { + test.skip(skipReason !== null, skipReason ?? ''); + + for (const descriptor of descriptors) { + test.describe(descriptor.label, () => { + let target: PrinterTarget; + let app: LaunchedApp; + + test.beforeAll(async () => { + target = await descriptor.create(); + }); + + test.afterAll(async () => { + await target?.dispose(); + }); + + test.afterEach(async () => { + if (app) { + await closeFFUI(app); + } + + // Uploads land on a real printer's filesystem and would otherwise accumulate + // with every run. Best-effort: a cleanup failure must not mask a test result. + for (const fixture of [PRINT_FIXTURES.ad5xSingleTool, PRINT_FIXTURES.adventurer5mSingleColor]) { + await target?.removeUploadedFile(fixture.remoteName).catch(() => { + // File was never uploaded, or the printer has no SFTP - nothing to clean. + }); + } + }); + + test('uploads a file without starting a print', async () => { + const fixture = simplestFixtureFor(descriptor.hasMaterialStation); + + app = await launchFFUI({ seededPrinters: [target.toSeededPrinter()] }); + const mainWindow = new MainWindow(app.mainWindow, app.electronApp); + + await mainWindow.waitForConnectedPrinters(1); + await mainWindow.expectDashboardVisible(); + await mainWindow.waitForControlsReady(); + + await stubFileDialog(app.electronApp, resolveFixture(fixture)); + await mainWindow.openJobUploader(); + + const uploader = await JobUploaderDialog.waitFor(app.electronApp); + await uploader.browseForFile(); + + expect(await uploader.getSelectedFileName()).toContain(fixture.fileName); + + // On a material-station printer every 3MF must be mapped to slots first, and + // the OK button stays disabled until that mapping is confirmed. + if (descriptor.hasMaterialStation) { + const materialDialog = await MaterialMatchingDialog.waitFor(app.electronApp); + for (let toolId = 0; toolId < fixture.toolCount; toolId += 1) { + await materialDialog.assignToolToFirstAvailableSlot(toolId); + } + await materialDialog.confirm(); + } + + await uploader.ensureStartNowUnchecked(); + expect(await uploader.isConfirmEnabled(), 'OK should be enabled once the job is ready').toBe(true); + + await uploader.confirm(); + await uploader.waitForUploadToComplete(app.electronApp); + + // The real assertion: the printer has the file. This is what the alpha.9 + // ReferenceError broke while the UI still looked like it had worked. + expect( + await target.waitForUploadedFile(fixture.remoteName), + `${fixture.remoteName} should be present on the printer after upload` + ).toBe(true); + + const safety = await assertNotPrinting(target.client); + if (safety.notes.length > 0) { + console.warn(safety.notes.join('\n')); + } + expect(safety.wasPrinting, `a print started despite Start Now being unchecked: ${safety.notes.join(' ')}`).toBe( + false + ); + + app.assertNoRendererErrors(); + }); + + test('shows the material matching dialog only on material-station printers', async () => { + const fixture = PRINT_FIXTURES.ad5xMultiTool; + + app = await launchFFUI({ seededPrinters: [target.toSeededPrinter()] }); + const mainWindow = new MainWindow(app.mainWindow, app.electronApp); + + await mainWindow.waitForConnectedPrinters(1); + await mainWindow.expectDashboardVisible(); + await mainWindow.waitForControlsReady(); + + await stubFileDialog(app.electronApp, resolveFixture(fixture)); + await mainWindow.openJobUploader(); + + const uploader = await JobUploaderDialog.waitFor(app.electronApp); + await uploader.browseForFile(); + + const materialDialog = await MaterialMatchingDialog.findOptional(app.electronApp, 10_000); + + if (descriptor.hasMaterialStation) { + expect(materialDialog, 'AD5X / Creator 5 should raise the material matching dialog').not.toBeNull(); + + // One requirement row per filament the slicer recorded. + await expect + .poll(async () => await materialDialog?.getRequirementCount(), { timeout: 10_000 }) + .toBe(fixture.toolCount); + + await materialDialog?.cancel(); + } else { + // 5M-series and legacy printers have no material station, so mapping tools to + // slots is meaningless and the dialog must never appear. + expect(materialDialog, '5M-series printers should not raise the material matching dialog').toBeNull(); + await uploader.cancel(); + } + + app.assertNoRendererErrors(); + }); + }); + } +}); diff --git a/tests/e2e/electron/support/electron-app.ts b/tests/e2e/electron/support/electron-app.ts new file mode 100644 index 0000000..c8fb0d0 --- /dev/null +++ b/tests/e2e/electron/support/electron-app.ts @@ -0,0 +1,272 @@ +/** + * @fileoverview Launches and tears down FlashForgeUI under Playwright with a fully + * isolated userData profile. + * + * Every run gets a fresh temp directory handed to the app through FFUI_USER_DATA_DIR, + * and the launch asserts the app actually honored it before any test touches the UI. + * That assertion is the guard that keeps a run from ever reading or mutating the + * developer's real %APPDATA%/FlashForgeUI profile. + * + * Key exports: + * - launchFFUI(): start the app with an optional seeded printer list + * - closeFFUI(): close the app and remove its temp profile + * - waitForWindowWithSelector() / findWindowWithSelector(): resolve dialog windows + * - expectWindowWithSelectorToClose(): assert a dialog window went away + */ + +import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { type ElectronApplication, _electron as electron, expect, type Page } from '@playwright/test'; + +const WINDOW_POLL_INTERVAL_MS = 25; + +/** Renderer console noise that Electron emits on every launch and never indicates a fault. */ +const CONSOLE_ERROR_ALLOWLIST: readonly RegExp[] = [/Autofill\.enable/i, /Autofill\.setAddresses/i]; + +/** + * A printer entry written into the seeded profile's printer_details.json. + * Mirrors the persisted PrinterDetails shape the app reads on boot. + */ +export interface SeededPrinter { + Name: string; + IPAddress: string; + SerialNumber: string; + CheckCode: string; + ClientType: 'legacy' | 'new'; + printerModel: string; + modelType?: string; + commandPort?: number; + httpPort?: number; + forceLegacyMode?: boolean; + webUIEnabled?: boolean; + customCameraEnabled?: boolean; + customLedsEnabled?: boolean; +} + +export interface LaunchedApp { + electronApp: ElectronApplication; + mainWindow: Page; + /** Temp directory containing the isolated profile; removed on close. */ + appDataRoot: string; + /** Throws if the renderer logged an unexpected error during the test. */ + assertNoRendererErrors: () => void; + disposeErrorGuard: () => void; +} + +const sleep = async (ms: number): Promise => + await new Promise((resolve) => { + setTimeout(resolve, ms); + }); + +const getUserDataPath = (appDataRoot: string): string => path.join(appDataRoot, 'FlashForgeUI'); + +const seedPrinterDetails = async (userDataPath: string, printers: readonly SeededPrinter[]): Promise => { + if (printers.length === 0) { + return; + } + + await mkdir(userDataPath, { recursive: true }); + + const nowIso = new Date().toISOString(); + const entries: Record> = {}; + for (const printer of printers) { + entries[printer.SerialNumber] = { ...printer, lastConnected: nowIso }; + } + + const payload = { + lastUsedPrinterSerial: printers[0]?.SerialNumber ?? null, + printers: entries, + }; + + await writeFile(path.join(userDataPath, 'printer_details.json'), `${JSON.stringify(payload, null, 2)}\n`, 'utf-8'); +}; + +interface RendererErrorGuard { + assertNoRendererErrors: () => void; + dispose: () => void; +} + +const createRendererErrorGuard = (electronApp: ElectronApplication): RendererErrorGuard => { + const unexpectedErrors: string[] = []; + const disposers: Array<() => void> = []; + + const record = (message: string): void => { + if (CONSOLE_ERROR_ALLOWLIST.some((pattern) => pattern.test(message))) { + return; + } + unexpectedErrors.push(message); + }; + + const attachWindow = (windowPage: Page): void => { + const onPageError = (error: Error): void => { + record(`[pageerror] ${error.message}`); + }; + + const onConsole = (message: { type: () => string; text: () => string; location: () => { url?: string } }): void => { + if (message.type() !== 'error') { + return; + } + record(`[console.error] ${message.location().url ?? 'unknown'}: ${message.text()}`); + }; + + windowPage.on('pageerror', onPageError); + windowPage.on('console', onConsole); + disposers.push(() => { + windowPage.off('pageerror', onPageError); + windowPage.off('console', onConsole); + }); + }; + + for (const windowPage of electronApp.windows()) { + attachWindow(windowPage); + } + + const onWindowOpened = (windowPage: Page): void => attachWindow(windowPage); + electronApp.on('window', onWindowOpened); + disposers.push(() => electronApp.off('window', onWindowOpened)); + + return { + assertNoRendererErrors: () => { + if (unexpectedErrors.length > 0) { + throw new Error(`Unexpected renderer errors detected:\n${unexpectedErrors.join('\n')}`); + } + }, + dispose: () => { + for (const disposer of disposers) { + disposer(); + } + }, + }; +}; + +/** Polls every open window for one containing `selector`, or null on timeout. */ +export const findWindowWithSelector = async ( + electronApp: ElectronApplication, + selector: string, + timeoutMs = 10_000 +): Promise => { + const deadline = Date.now() + timeoutMs; + + while (Date.now() < deadline) { + for (const windowPage of electronApp.windows()) { + try { + if ((await windowPage.locator(selector).count()) > 0) { + return windowPage; + } + } catch { + // Window was closing mid-poll; ignore and keep looking. + } + } + await sleep(WINDOW_POLL_INTERVAL_MS); + } + + return null; +}; + +/** Like findWindowWithSelector but throws a descriptive error instead of returning null. */ +export const waitForWindowWithSelector = async ( + electronApp: ElectronApplication, + selector: string, + timeoutMs = 10_000 +): Promise => { + const found = await findWindowWithSelector(electronApp, selector, timeoutMs); + if (found) { + return found; + } + throw new Error(`Timed out waiting for window with selector "${selector}" after ${timeoutMs}ms`); +}; + +export const expectWindowWithSelectorToClose = async ( + electronApp: ElectronApplication, + selector: string, + timeoutMs = 10_000 +): Promise => { + await expect + .poll(async () => ((await findWindowWithSelector(electronApp, selector, 250)) ? 1 : 0), { timeout: timeoutMs }) + .toBe(0); +}; + +const hasMainUiMarkers = async (windowPage: Page): Promise => { + try { + if ((await windowPage.locator('#btn-main-menu').count()) > 0) { + return true; + } + return (await windowPage.locator('#placeholder-connect-btn').count()) > 0; + } catch { + return false; + } +}; + +const resolveMainWindow = async (electronApp: ElectronApplication, timeoutMs = 20_000): Promise => { + const deadline = Date.now() + timeoutMs; + let lastWindowCount = 0; + + while (Date.now() < deadline) { + const windows = electronApp.windows(); + lastWindowCount = windows.length; + + for (const windowPage of windows) { + if (await hasMainUiMarkers(windowPage)) { + return windowPage; + } + } + await sleep(WINDOW_POLL_INTERVAL_MS); + } + + throw new Error(`Unable to locate main window after ${timeoutMs}ms (observed ${lastWindowCount} window(s))`); +}; + +/** + * Launches FlashForgeUI against a throwaway profile. + * + * The userData assertion below is deliberate and must not be relaxed: if the app + * ignored FFUI_USER_DATA_DIR the run would operate on the developer's real profile, + * so failing loudly here is far better than a test quietly rewriting saved printers. + */ +export const launchFFUI = async (params?: { seededPrinters?: readonly SeededPrinter[] }): Promise => { + const appDataRoot = await mkdtemp(path.join(os.tmpdir(), 'ffui-e2e-')); + const userDataPath = getUserDataPath(appDataRoot); + + if (params?.seededPrinters && params.seededPrinters.length > 0) { + await seedPrinterDetails(userDataPath, params.seededPrinters); + } + + const electronApp = await electron.launch({ + args: ['.'], + cwd: process.cwd(), + timeout: 120_000, + env: { ...process.env, FFUI_USER_DATA_DIR: userDataPath }, + }); + + const errorGuard = createRendererErrorGuard(electronApp); + + const actualUserDataPath = await electronApp.evaluate(async ({ app }) => app.getPath('userData')); + if (actualUserDataPath.toLowerCase() !== userDataPath.toLowerCase()) { + await electronApp.close(); + throw new Error( + `Profile isolation failed: app is using "${actualUserDataPath}" instead of "${userDataPath}". ` + + 'Refusing to run against a non-isolated profile.' + ); + } + + const mainWindow = await resolveMainWindow(electronApp); + await expect(mainWindow.locator('.title')).toHaveText('FlashForgeUI'); + + return { + electronApp, + mainWindow, + appDataRoot, + assertNoRendererErrors: errorGuard.assertNoRendererErrors, + disposeErrorGuard: errorGuard.dispose, + }; +}; + +export const closeFFUI = async (launched: LaunchedApp): Promise => { + try { + await launched.electronApp.close(); + } finally { + launched.disposeErrorGuard(); + await rm(launched.appDataRoot, { recursive: true, force: true }); + } +}; diff --git a/tests/e2e/electron/support/fixtures.ts b/tests/e2e/electron/support/fixtures.ts new file mode 100644 index 0000000..c8a539f --- /dev/null +++ b/tests/e2e/electron/support/fixtures.ts @@ -0,0 +1,73 @@ +/** + * @fileoverview Locates the print files the upload specs feed to FlashForgeUI. + * + * Files live in-repo under tests/fixtures/print-files so a run never depends on a + * sibling checkout. They are real slicer output, not synthetic stubs, because the + * upload path parses embedded metadata (and, for 3MF, per-tool filament data) - a + * hand-written file would exercise none of that. + * + * Key exports: + * - PRINT_FIXTURES: the available files and what each is for + * - resolveFixture(): absolute path, asserting the file exists + */ + +import { existsSync } from 'node:fs'; +import path from 'node:path'; + +const FIXTURE_DIR = path.resolve(process.cwd(), 'tests', 'fixtures', 'print-files'); + +export interface PrintFixture { + fileName: string; + /** Name the file will have on the printer after upload. */ + remoteName: string; + description: string; + toolCount: number; +} + +/* + * Tool counts below were read from the parser, not from the upstream file names. + * Those names are actively misleading: slicer-meta's "twocolors" 3MF records only one + * filament with real usage, while its "pla-silk" 3MF records two (PLA + SILK). The + * fixtures here are renamed after what the parser actually reports, because that is + * what decides whether the material matching dialog appears. + */ +export const PRINT_FIXTURES = { + /** One filament: the simplest 3MF an AD5X will accept. */ + ad5xSingleTool: { + fileName: 'ad5x-single-tool.3mf', + remoteName: 'ad5x-single-tool.3mf', + description: 'AD5X 3MF with one filament (orca-flashforge 1.4.2)', + toolCount: 1, + }, + /** Two filaments: drives the multi-tool material matching path. */ + ad5xMultiTool: { + fileName: 'ad5x-multi-tool.3mf', + remoteName: 'ad5x-multi-tool.3mf', + description: 'AD5X 3MF with two filaments, PLA + SILK (orca-flashforge 1.4.2)', + toolCount: 2, + }, + /** Plain single-colour gcode for 5M-series printers. */ + adventurer5mSingleColor: { + fileName: 'adventurer5m-single-color.gcode', + remoteName: 'adventurer5m-single-color.gcode', + description: 'Adventurer 5M single-colour gcode (orca-flashforge 1.3.0)', + toolCount: 1, + }, +} as const satisfies Record; + +export const resolveFixture = (fixture: PrintFixture): string => { + const fullPath = path.join(FIXTURE_DIR, fixture.fileName); + if (!existsSync(fullPath)) { + throw new Error(`Print fixture missing: ${fullPath}. Expected "${fixture.description}".`); + } + return fullPath; +}; + +/** + * Picks the simplest uploadable fixture for a target. + * + * Material-station printers (AD5X / Creator 5) only accept 3MF; everything else gets + * plain single-colour gcode, which is what a 5M-series user actually uploads. + */ +export const simplestFixtureFor = (hasMaterialStation: boolean): PrintFixture => + hasMaterialStation ? PRINT_FIXTURES.ad5xSingleTool : PRINT_FIXTURES.adventurer5mSingleColor; diff --git a/tests/e2e/electron/support/hardware-config.ts b/tests/e2e/electron/support/hardware-config.ts new file mode 100644 index 0000000..f9caa26 --- /dev/null +++ b/tests/e2e/electron/support/hardware-config.ts @@ -0,0 +1,247 @@ +/** + * @fileoverview Resolves the real printers the hardware track runs against. + * + * Credentials deliberately live OUTSIDE the repository working tree so they can + * never be committed, even if .gitignore is wrong. Resolution order: + * + * 1. $FFUI_E2E_HARDWARE_CONFIG (explicit path to a JSON config) + * 2. ~/.flashforgeui-e2e/hardware-printers.json + * 3. The developer's real FlashForgeUI profile (READ ONLY), which already holds + * serials and check codes for every printer they use. + * + * IP addresses are never taken from any of those sources. They are resolved live + * by UDP discovery keyed on serial number, because printer IPs move with DHCP - + * the AD5X on this bench moved .132 -> .133 between two runs. Serial is the only + * stable identity a printer has. + * + * Key exports: + * - loadHardwarePrinters(): configured printers, without addresses + * - resolveHardwarePrinter(): one printer with its current IP, via discovery + */ + +import { readFileSync } from 'node:fs'; +import { readFile } from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; + +/** Serial prefixes/names used by emulator instances, never treated as real hardware. */ +const EMULATOR_MARKERS: readonly RegExp[] = [/emulator/i, /^E2E-/i]; + +export type HardwarePrinterKind = 'ad5x' | 'adventurer-5m-pro' | 'adventurer-5m' | 'creator-5' | 'creator-5-pro'; + +export interface HardwarePrinterConfig { + /** Human label used in test titles. */ + label: string; + serialNumber: string; + checkCode: string; + kind: HardwarePrinterKind; + /** Root SSH/SFTP credentials provisioned by FlashForge-EasySSH. */ + ssh?: { + username: string; + password: string; + port: number; + }; +} + +export interface ResolvedHardwarePrinter extends HardwarePrinterConfig { + ipAddress: string; + commandPort: number; + httpPort: number; +} + +interface RawPrinterDetailsEntry { + Name?: string; + SerialNumber?: string; + CheckCode?: string; + modelType?: string; + printerModel?: string; + commandPort?: number; + httpPort?: number; +} + +const DEFAULT_SSH = { username: 'root', password: 'flashforge', port: 22 } as const; + +const isEmulatorEntry = (serial: string, name: string): boolean => + EMULATOR_MARKERS.some((pattern) => pattern.test(serial) || pattern.test(name)); + +const toKind = (entry: RawPrinterDetailsEntry): HardwarePrinterKind | null => { + const raw = (entry.modelType ?? entry.printerModel ?? '').toLowerCase(); + if (raw.includes('ad5x') || raw.includes('5x')) { + return 'ad5x'; + } + if (raw.includes('5m pro') || raw.includes('5m-pro')) { + return 'adventurer-5m-pro'; + } + if (raw.includes('5m')) { + return 'adventurer-5m'; + } + if (raw.includes('creator-5-pro') || raw.includes('creator 5 pro')) { + return 'creator-5-pro'; + } + if (raw.includes('creator')) { + return 'creator-5'; + } + return null; +}; + +const readJsonFile = async (filePath: string): Promise => { + try { + return JSON.parse(await readFile(filePath, 'utf-8')) as T; + } catch { + return null; + } +}; + +const getRealProfilePath = (): string => { + const appData = process.env.APPDATA ?? path.join(os.homedir(), 'AppData', 'Roaming'); + return path.join(appData, 'FlashForgeUI', 'printer_details.json'); +}; + +/** + * Derives hardware targets from the developer's real FlashForgeUI profile. + * This only ever READS that file - the app under test always runs against an + * isolated temp profile (see electron-app.ts). + */ +const loadFromRealProfile = async (): Promise => { + const parsed = await readJsonFile<{ printers?: Record }>(getRealProfilePath()); + if (!parsed?.printers) { + return []; + } + + const configs: HardwarePrinterConfig[] = []; + for (const entry of Object.values(parsed.printers)) { + const serialNumber = entry.SerialNumber ?? ''; + const checkCode = entry.CheckCode ?? ''; + const label = entry.Name ?? serialNumber; + + if (!serialNumber || !checkCode || isEmulatorEntry(serialNumber, label)) { + continue; + } + + const kind = toKind(entry); + if (!kind) { + continue; + } + + configs.push({ label, serialNumber, checkCode, kind, ssh: { ...DEFAULT_SSH } }); + } + + return configs; +}; + +export const loadHardwarePrinters = async (): Promise => { + const explicitPath = process.env.FFUI_E2E_HARDWARE_CONFIG?.trim(); + const candidatePaths = [ + explicitPath && explicitPath.length > 0 ? path.resolve(explicitPath) : null, + path.join(os.homedir(), '.flashforgeui-e2e', 'hardware-printers.json'), + ].filter((value): value is string => value !== null); + + for (const candidate of candidatePaths) { + const parsed = await readJsonFile<{ printers?: HardwarePrinterConfig[] }>(candidate); + if (parsed?.printers && parsed.printers.length > 0) { + return parsed.printers.map((printer) => ({ ...printer, ssh: printer.ssh ?? { ...DEFAULT_SSH } })); + } + } + + return await loadFromRealProfile(); +}; + +/** + * Synchronous variant of loadHardwarePrinters(). + * + * Playwright evaluates test.describe() bodies synchronously at collection time, so + * parameterizing specs over the configured printers cannot await. Reading a small + * local JSON file synchronously at collection is the pragmatic way to enumerate them. + */ +export const loadHardwarePrintersSync = (): HardwarePrinterConfig[] => { + const readSync = (filePath: string): T | null => { + try { + return JSON.parse(readFileSync(filePath, 'utf-8')) as T; + } catch { + return null; + } + }; + + const explicitPath = process.env.FFUI_E2E_HARDWARE_CONFIG?.trim(); + const candidatePaths = [ + explicitPath && explicitPath.length > 0 ? path.resolve(explicitPath) : null, + path.join(os.homedir(), '.flashforgeui-e2e', 'hardware-printers.json'), + ].filter((value): value is string => value !== null); + + for (const candidate of candidatePaths) { + const parsed = readSync<{ printers?: HardwarePrinterConfig[] }>(candidate); + if (parsed?.printers && parsed.printers.length > 0) { + return parsed.printers.map((printer) => ({ ...printer, ssh: printer.ssh ?? { ...DEFAULT_SSH } })); + } + } + + const profile = readSync<{ printers?: Record }>(getRealProfilePath()); + if (!profile?.printers) { + return []; + } + + const configs: HardwarePrinterConfig[] = []; + for (const entry of Object.values(profile.printers)) { + const serialNumber = entry.SerialNumber ?? ''; + const checkCode = entry.CheckCode ?? ''; + const label = entry.Name ?? serialNumber; + const kind = toKind(entry); + + if (!serialNumber || !checkCode || !kind || isEmulatorEntry(serialNumber, label)) { + continue; + } + configs.push({ label, serialNumber, checkCode, kind, ssh: { ...DEFAULT_SSH } }); + } + + return configs; +}; + +interface DiscoveredPrinter { + name: string; + ipAddress: string; + serialNumber: string; + commandPort: number; + eventPort: number; + productId: number; +} + +/** + * Runs a real UDP discovery sweep and returns every printer that answered. + * Imported lazily so that emulator-only runs never load the printer library. + */ +export const discoverPrinters = async (timeoutMs = 8_000): Promise => { + const { PrinterDiscovery } = (await import('@ghosttypes/ff-api')) as unknown as { + PrinterDiscovery: new () => { discover: (timeout: number) => Promise }; + }; + + const discovery = new PrinterDiscovery(); + return await discovery.discover(timeoutMs); +}; + +/** + * Resolves a configured printer to its current address. + * Throws with the list of what *was* found, so a powered-off printer produces an + * actionable message rather than a bare timeout later in the test. + */ +export const resolveHardwarePrinter = async ( + config: HardwarePrinterConfig, + timeoutMs = 8_000 +): Promise => { + const discovered = await discoverPrinters(timeoutMs); + const match = discovered.find((printer) => printer.serialNumber === config.serialNumber); + + if (!match) { + const seen = discovered.map((printer) => `${printer.name} (${printer.serialNumber} @ ${printer.ipAddress})`); + throw new Error( + `Printer "${config.label}" (${config.serialNumber}) did not answer discovery within ${timeoutMs}ms. ` + + `Is it powered on and on this network?\nDiscovered instead: ${seen.length > 0 ? seen.join(', ') : 'nothing'}` + ); + } + + return { + ...config, + ipAddress: match.ipAddress, + commandPort: match.commandPort, + httpPort: match.eventPort, + }; +}; diff --git a/tests/e2e/electron/support/printer-client.ts b/tests/e2e/electron/support/printer-client.ts new file mode 100644 index 0000000..1909a81 --- /dev/null +++ b/tests/e2e/electron/support/printer-client.ts @@ -0,0 +1,177 @@ +/** + * @fileoverview Minimal HTTP client for asserting printer state during E2E runs. + * + * Talks the modern FlashForge HTTP API, which the emulator implements faithfully, + * so the same client backs both the emulator and hardware tracks. This is an + * out-of-band observer: tests drive the GUI and then verify the printer actually + * changed through this client, rather than trusting the UI's own rendering. + * + * Also implements the print-safety recovery path. Uploads in this suite always run + * with "Start Now" unchecked, so a print must never begin - but if one ever does, + * assertNotPrinting() cancels it and clears the platform rather than leaving a real + * machine heating unattended. + * + * Key exports: + * - PrinterClient: detail/gcodeList/LED/job-control wrapper + * - assertNotPrinting(): the post-upload safety gate + */ + +export interface PrinterDetail { + status: string; + lightStatus: 'open' | 'close'; + printFileName: string; + [key: string]: unknown; +} + +export interface GcodeListEntry { + gcodeFileName: string; + gcodeToolCnt: number; + useMatlStation: boolean; +} + +/** Machine statuses that mean material is actively being laid down or prepared. */ +const ACTIVE_PRINT_STATUSES: readonly string[] = ['printing', 'heating', 'calibrating', 'pausing', 'paused']; + +const sleep = async (ms: number): Promise => + await new Promise((resolve) => { + setTimeout(resolve, ms); + }); + +export class PrinterClient { + readonly #baseUrl: string; + readonly #auth: { serialNumber: string; checkCode: string }; + + constructor(params: { ipAddress: string; httpPort: number; serialNumber: string; checkCode: string }) { + this.#baseUrl = `http://${params.ipAddress}:${params.httpPort}`; + this.#auth = { serialNumber: params.serialNumber, checkCode: params.checkCode }; + } + + async #post(endpoint: string, body: Record = {}): Promise { + const response = await fetch(`${this.#baseUrl}${endpoint}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ ...this.#auth, ...body }), + }); + + if (!response.ok) { + throw new Error(`${endpoint} responded ${response.status} ${response.statusText}`); + } + + return (await response.json()) as T; + } + + async getDetail(): Promise { + const payload = await this.#post<{ detail?: PrinterDetail }>('/detail'); + if (!payload.detail) { + throw new Error('/detail response contained no detail object'); + } + return payload.detail; + } + + async getGcodeList(): Promise { + const payload = await this.#post<{ gcodeListDetail?: GcodeListEntry[] }>('/gcodeList'); + return payload.gcodeListDetail ?? []; + } + + async hasFile(fileName: string): Promise { + const files = await this.getGcodeList(); + return files.some((file) => file.gcodeFileName === fileName); + } + + async #control(cmd: string, args: Record): Promise { + await this.#post('/control', { payload: { cmd, args } }); + } + + async setLight(state: 'open' | 'close'): Promise { + await this.#control('lightControl_cmd', { status: state }); + } + + async cancelPrint(): Promise { + await this.#control('jobCtl_cmd', { jobID: '', action: 'cancel' }); + } + + async clearPlatform(): Promise { + await this.#control('stateCtrl_cmd', { action: 'setClearPlatform' }); + } + + /** Polls until lightStatus matches, returning false if it never does. */ + async waitForLightStatus(expected: 'open' | 'close', timeoutMs = 15_000): Promise { + const deadline = Date.now() + timeoutMs; + while (Date.now() < deadline) { + const detail = await this.getDetail().catch(() => null); + if (detail?.lightStatus === expected) { + return true; + } + await sleep(500); + } + return false; + } + + async waitForFile(fileName: string, timeoutMs = 60_000): Promise { + const deadline = Date.now() + timeoutMs; + while (Date.now() < deadline) { + if (await this.hasFile(fileName).catch(() => false)) { + return true; + } + await sleep(1_000); + } + return false; + } +} + +export interface SafetyCheckResult { + wasPrinting: boolean; + status: string; + recovered: boolean; + notes: string[]; +} + +/** + * Verifies no print started after an upload, and recovers the machine if one did. + * + * Recovery mirrors the documented manual procedure: cancel the job, wait for the + * firmware to settle, then clear the platform so the printer accepts control again. + * The caller is expected to fail the test loudly on wasPrinting - recovery makes the + * hardware safe, it does not make the run a pass. + */ +export const assertNotPrinting = async ( + client: PrinterClient, + params?: { settleMs?: number; clearPlatformDelayMs?: number } +): Promise => { + const notes: string[] = []; + const settleMs = params?.settleMs ?? 5_000; + const clearPlatformDelayMs = params?.clearPlatformDelayMs ?? 15_000; + + // Give the printer a moment to react before judging - an upload that was going + // to auto-start would have done so by now. + await sleep(settleMs); + + const detail = await client.getDetail(); + const status = (detail.status ?? '').toLowerCase(); + const wasPrinting = ACTIVE_PRINT_STATUSES.some((active) => status.includes(active)); + + if (!wasPrinting) { + return { wasPrinting: false, status: detail.status, recovered: true, notes }; + } + + notes.push(`SAFETY: printer entered "${detail.status}" after an upload with Start Now unchecked.`); + + try { + await client.cancelPrint(); + notes.push('SAFETY: sent jobCtl_cmd cancel.'); + + await sleep(clearPlatformDelayMs); + + await client.clearPlatform(); + notes.push('SAFETY: sent stateCtrl_cmd setClearPlatform.'); + + const after = await client.getDetail(); + notes.push(`SAFETY: status after recovery is "${after.status}".`); + + return { wasPrinting: true, status: detail.status, recovered: true, notes }; + } catch (error) { + notes.push(`SAFETY: recovery FAILED - ${error instanceof Error ? error.message : String(error)}`); + notes.push('SAFETY: the printer may still be printing. Check it physically.'); + return { wasPrinting: true, status: detail.status, recovered: false, notes }; + } +}; diff --git a/tests/e2e/electron/support/printer-target.ts b/tests/e2e/electron/support/printer-target.ts new file mode 100644 index 0000000..0e57c41 --- /dev/null +++ b/tests/e2e/electron/support/printer-target.ts @@ -0,0 +1,260 @@ +/** + * @fileoverview The abstraction that lets one spec run against the emulator in CI and + * against real printers on a developer bench. + * + * A PrinterTarget is "a printer this test can drive": an address, credentials, the + * seed entry needed to pre-populate the app profile, and a PrinterClient for + * out-of-band assertions. Emulator targets are created on demand; hardware targets + * are resolved live by serial through UDP discovery. + * + * Capability flags (hasMaterialStation, supportsSftp) let a shared spec skip the parts + * a given target genuinely cannot do, instead of forking whole specs per track. + * + * Key exports: + * - PrinterTarget: the common shape + * - createEmulatorTarget(): boot an emulator instance as a target + * - createHardwareTarget(): resolve a configured real printer as a target + */ + +import type { SeededPrinter } from './electron-app'; +import { type EmulatorModel, startEmulatorInstance } from '../helpers/emulator-harness'; +import { type HardwarePrinterConfig, resolveHardwarePrinter } from './hardware-config'; +import { PrinterClient } from './printer-client'; +import { deleteRemoteFile, remoteGcodeDirFor, waitForRemoteFile } from './sftp'; + +export interface PrinterTarget { + /** Label used in test titles and failure messages. */ + label: string; + ipAddress: string; + serialNumber: string; + checkCode: string; + commandPort: number; + httpPort: number; + /** Manual-connect dropdown token for this printer. */ + manualConnectType: 'adventurer-5m' | 'adventurer-5m-pro' | 'ad5x' | 'creator-5' | 'creator-5-pro' | 'legacy'; + /** AD5X and Creator 5 have a 4-slot material station; 5M-series and legacy do not. */ + hasMaterialStation: boolean; + /** Only real printers provisioned by FlashForge-EasySSH expose SSH/SFTP. */ + supportsSftp: boolean; + ssh?: { username: string; password: string; port: number }; + /** Out-of-band client for asserting real printer state. */ + client: PrinterClient; + /** + * Waits for an uploaded file to be visible on the printer. + * + * Hardware checks the filesystem over SFTP; the emulator falls back to /gcodeList. + * They are not interchangeable: on real firmware /gcodeList only reports *recent* + * files, so a freshly uploaded file that has never printed is absent from it even + * though the upload succeeded. + */ + waitForUploadedFile(fileName: string, timeoutMs?: number): Promise; + /** Removes an uploaded file, so hardware runs leave no residue. */ + removeUploadedFile(fileName: string): Promise; + /** Profile entry used to pre-seed the app so it can auto-connect. */ + toSeededPrinter(): SeededPrinter; + /** Releases any resources (stops an emulator instance; no-op for hardware). */ + dispose(): Promise; +} + +const MATERIAL_STATION_TYPES = new Set(['ad5x', 'creator-5', 'creator-5-pro']); + +interface EmulatorTargetParams { + label: string; + model: EmulatorModel; + serial: string; + checkCode: string; + machineName: string; + tcpPort: number; + httpPort: number; + discoveryEnabled?: boolean; +} + +/** Maps an emulator model token to the app's manual-connect dropdown token. */ +const emulatorModelToManualType = (model: EmulatorModel): PrinterTarget['manualConnectType'] => { + switch (model) { + case 'adventurer-5m': + return 'adventurer-5m'; + case 'adventurer-5m-pro': + return 'adventurer-5m-pro'; + case 'adventurer-5x': + return 'ad5x'; + default: + // adventurer-3 / adventurer-4 are genuine legacy printers with no product ID. + return 'legacy'; + } +}; + +const emulatorModelToPrinterModel = (model: EmulatorModel): string => { + switch (model) { + case 'adventurer-5m': + return 'Adventurer 5M'; + case 'adventurer-5m-pro': + return 'Adventurer 5M Pro'; + case 'adventurer-5x': + return 'AD5X'; + case 'adventurer-3': + return 'Adventurer 3'; + case 'adventurer-4': + return 'Adventurer 4'; + default: + return model; + } +}; + +export const createEmulatorTarget = async (params: EmulatorTargetParams): Promise => { + const instance = await startEmulatorInstance({ + instance: { + instanceId: `${params.label.toLowerCase().replace(/[^a-z0-9]+/g, '-')}-${params.tcpPort}`, + model: params.model, + serial: params.serial, + checkCode: params.checkCode, + machineName: params.machineName, + tcpPort: params.tcpPort, + httpPort: params.httpPort, + discoveryEnabled: params.discoveryEnabled ?? true, + simulationMode: 'manual', + simulationSpeed: 100, + }, + }); + + const ready = instance.readyPayloads[0]; + if (!ready) { + await instance.stop(); + throw new Error(`Emulator instance for "${params.label}" never reported ready`); + } + + const manualConnectType = emulatorModelToManualType(params.model); + const isLegacy = manualConnectType === 'legacy'; + + return { + label: params.label, + ipAddress: ready.ip, + serialNumber: params.serial, + checkCode: params.checkCode, + commandPort: params.tcpPort, + httpPort: params.httpPort, + manualConnectType, + hasMaterialStation: MATERIAL_STATION_TYPES.has(manualConnectType), + // The emulator implements the printer HTTP/TCP APIs but runs no SSH server. + supportsSftp: false, + client: new PrinterClient({ + ipAddress: ready.ip, + httpPort: params.httpPort, + serialNumber: params.serial, + checkCode: params.checkCode, + }), + // No SSH on the emulator, so /gcodeList is the only listing available - and it is + // sufficient there because the emulator does report uploads through it. + waitForUploadedFile: async (fileName: string, timeoutMs = 60_000) => + await new PrinterClient({ + ipAddress: ready.ip, + httpPort: params.httpPort, + serialNumber: params.serial, + checkCode: params.checkCode, + }).waitForFile(fileName, timeoutMs), + removeUploadedFile: async () => { + // Emulator state is discarded when the instance stops. + }, + toSeededPrinter: () => ({ + Name: params.machineName, + IPAddress: ready.ip, + SerialNumber: params.serial, + CheckCode: params.checkCode, + ClientType: isLegacy ? 'legacy' : 'new', + printerModel: emulatorModelToPrinterModel(params.model), + commandPort: params.tcpPort, + httpPort: params.httpPort, + forceLegacyMode: isLegacy, + }), + dispose: async () => { + await instance.stop(); + }, + }; +}; + +const hardwareKindToManualType = (kind: HardwarePrinterConfig['kind']): PrinterTarget['manualConnectType'] => kind; + +const hardwareKindToPrinterModel = (kind: HardwarePrinterConfig['kind']): string => { + switch (kind) { + case 'ad5x': + return 'AD5X'; + case 'adventurer-5m': + return 'Adventurer 5M'; + case 'adventurer-5m-pro': + return 'Adventurer 5M Pro'; + case 'creator-5': + return 'Creator 5'; + case 'creator-5-pro': + return 'Creator 5 Pro'; + default: + return kind; + } +}; + +/** + * Resolves a real printer to a target. + * + * The address always comes from live discovery, never from saved config - printer IPs + * move with DHCP and a stale address produces a confusing mid-test failure instead of + * a clear "printer not found" one. + */ +export const createHardwareTarget = async (config: HardwarePrinterConfig): Promise => { + const resolved = await resolveHardwarePrinter(config); + const manualConnectType = hardwareKindToManualType(config.kind); + + return { + label: config.label, + ipAddress: resolved.ipAddress, + serialNumber: config.serialNumber, + checkCode: config.checkCode, + commandPort: resolved.commandPort, + httpPort: resolved.httpPort, + manualConnectType, + hasMaterialStation: MATERIAL_STATION_TYPES.has(manualConnectType), + supportsSftp: config.ssh !== undefined, + ssh: config.ssh, + client: new PrinterClient({ + ipAddress: resolved.ipAddress, + httpPort: resolved.httpPort, + serialNumber: config.serialNumber, + checkCode: config.checkCode, + }), + waitForUploadedFile: async (fileName: string, timeoutMs = 120_000) => { + if (!config.ssh) { + // Without SFTP the only option is the recent-files list, which is unreliable + // for never-printed uploads; say so rather than reporting a false negative. + throw new Error( + `Cannot verify uploads on "${config.label}": no SSH credentials configured, and /gcodeList does not list freshly uploaded files on real firmware.` + ); + } + return await waitForRemoteFile( + { host: resolved.ipAddress, port: config.ssh.port, username: config.ssh.username, password: config.ssh.password }, + remoteGcodeDirFor(config.kind), + fileName, + timeoutMs + ); + }, + removeUploadedFile: async (fileName: string) => { + if (!config.ssh) { + return; + } + await deleteRemoteFile( + { host: resolved.ipAddress, port: config.ssh.port, username: config.ssh.username, password: config.ssh.password }, + remoteGcodeDirFor(config.kind), + fileName + ); + }, + toSeededPrinter: () => ({ + Name: config.label, + IPAddress: resolved.ipAddress, + SerialNumber: config.serialNumber, + CheckCode: config.checkCode, + ClientType: 'new', + printerModel: hardwareKindToPrinterModel(config.kind), + commandPort: resolved.commandPort, + httpPort: resolved.httpPort, + }), + // Hardware isn't ours to shut down. + dispose: async () => {}, + }; +}; diff --git a/tests/e2e/electron/support/sftp.ts b/tests/e2e/electron/support/sftp.ts new file mode 100644 index 0000000..0e79946 --- /dev/null +++ b/tests/e2e/electron/support/sftp.ts @@ -0,0 +1,114 @@ +/** + * @fileoverview SFTP helpers for verifying files directly on a real printer. + * + * Needed because /gcodeList is a *recent files* list, not a directory listing. On real + * firmware a freshly uploaded file that has never been printed does not appear there, + * so asserting on it reports a false failure for an upload that genuinely worked. (The + * emulator's /gcodeList does list uploads, which is why this only bites on hardware.) + * + * Reading the filesystem over SFTP is the authoritative check. Requires + * FlashForge-EasySSH provisioning, so it is hardware-only. + * + * Key exports: + * - remoteGcodeDirFor(): where each printer family stores print files + * - listRemoteFiles() / hasRemoteFile() / deleteRemoteFile() + */ + +import { Client, type SftpClient } from 'ssh2'; +import type { HardwarePrinterKind } from './hardware-config'; + +export interface SftpCredentials { + host: string; + port: number; + username: string; + password: string; +} + +/** + * Print-file directory per printer family, matching FlashForge-EasySSH's layout. + * AD5X keeps gcode/3MF in /usr/data/gcodes; the 5M series uses /data. + */ +export const remoteGcodeDirFor = (kind: HardwarePrinterKind): string => + kind === 'ad5x' ? '/usr/data/gcodes' : '/data'; + +const withSftp = async (credentials: SftpCredentials, action: (sftp: SftpClient) => Promise): Promise => { + const client = new Client(); + + const session = await new Promise((resolve, reject) => { + client.on('ready', () => { + client.sftp((error, sftp) => { + if (error) { + reject(error); + return; + } + resolve(sftp); + }); + }); + client.on('error', reject); + client.connect({ ...credentials, readyTimeout: 20_000 }); + }); + + try { + return await action(session); + } finally { + client.end(); + } +}; + +export const listRemoteFiles = async (credentials: SftpCredentials, directory: string): Promise => + await withSftp( + credentials, + async (sftp) => + await new Promise((resolve, reject) => { + sftp.readdir(directory, (error, list) => { + if (error) { + reject(new Error(`SFTP readdir ${directory} failed: ${error.message}`)); + return; + } + resolve(list.map((entry) => entry.filename)); + }); + }) + ); + +export const hasRemoteFile = async ( + credentials: SftpCredentials, + directory: string, + fileName: string +): Promise => (await listRemoteFiles(credentials, directory)).includes(fileName); + +/** Polls for a file to appear, since large uploads finish after the dialog closes. */ +export const waitForRemoteFile = async ( + credentials: SftpCredentials, + directory: string, + fileName: string, + timeoutMs = 120_000 +): Promise => { + const deadline = Date.now() + timeoutMs; + while (Date.now() < deadline) { + if (await hasRemoteFile(credentials, directory, fileName).catch(() => false)) { + return true; + } + await new Promise((resolve) => setTimeout(resolve, 2_000)); + } + return false; +}; + +/** Removes a file, used to clean up after hardware upload runs. */ +export const deleteRemoteFile = async ( + credentials: SftpCredentials, + directory: string, + fileName: string +): Promise => + await withSftp( + credentials, + async (sftp) => + await new Promise((resolve, reject) => { + sftp.unlink(`${directory}/${fileName}`, (error) => { + if (error) { + reject(new Error(`SFTP unlink ${directory}/${fileName} failed: ${error.message}`)); + return; + } + resolve(); + }); + }) + ); diff --git a/tests/e2e/electron/support/ssh2-shim.d.ts b/tests/e2e/electron/support/ssh2-shim.d.ts new file mode 100644 index 0000000..e65d044 --- /dev/null +++ b/tests/e2e/electron/support/ssh2-shim.d.ts @@ -0,0 +1,35 @@ +/** + * @fileoverview Minimal ambient types for the `ssh2` package. + * + * ssh2 ships no declarations and @types/ssh2 is not installed. Rather than add a + * dependency for test-only code, this declares just the surface the SFTP helpers use. + * Scoped to tsconfig.e2e.json, so it cannot affect application type-checking. + */ + +declare module 'ssh2' { + export interface SftpFileEntry { + filename: string; + attrs: { size: number; mtime: number }; + } + + export interface SftpClient { + readdir(path: string, callback: (error: Error | null, list: SftpFileEntry[]) => void): void; + unlink(path: string, callback: (error: Error | null) => void): void; + } + + export interface ConnectConfig { + host: string; + port: number; + username: string; + password: string; + readyTimeout?: number; + } + + export class Client { + on(event: 'ready', listener: () => void): this; + on(event: 'error', listener: (error: Error) => void): this; + sftp(callback: (error: Error | null, sftp: SftpClient) => void): void; + connect(config: ConnectConfig): this; + end(): this; + } +} diff --git a/tests/e2e/electron/support/track.ts b/tests/e2e/electron/support/track.ts new file mode 100644 index 0000000..c22dc56 --- /dev/null +++ b/tests/e2e/electron/support/track.ts @@ -0,0 +1,168 @@ +/** + * @fileoverview Selects which track a run exercises and enumerates its printers. + * + * One spec file serves both tracks. The track is chosen by FFUI_E2E_TRACK: + * + * emulator (default) - boots flashforge-emulator-v2 instances; safe for CI + * hardware - drives the real printers on the developer's bench + * + * Descriptors are enumerated synchronously because Playwright collects + * test.describe() bodies before any await is possible. The expensive work (booting an + * emulator, resolving a real printer by discovery) happens inside create(). + * + * Key exports: + * - getTrack(): the active track + * - listTargetDescriptors(): printers to parameterize specs over + * - describeForTrack(): skips a spec that the active track cannot support + */ + +import type { EmulatorModel } from '../helpers/emulator-harness'; +import { loadHardwarePrintersSync } from './hardware-config'; +import { createEmulatorTarget, createHardwareTarget, type PrinterTarget } from './printer-target'; + +export type Track = 'emulator' | 'hardware'; + +export interface TargetDescriptor { + label: string; + /** True for AD5X / Creator 5, which show the material matching dialog. */ + hasMaterialStation: boolean; + /** True only on real EasySSH-provisioned printers. */ + supportsSftp: boolean; + /** + * Whether the manual connect form can reach this printer. + * + * The form collects IP + type + serial + check code but no ports, so it always + * dials the firmware defaults (8899/8898). Real printers always listen there, but + * only one emulator instance per machine can, so additional emulator instances run + * on alternate ports and are reachable by discovery and saved-profile connect only. + */ + supportsManualConnect: boolean; + create: () => Promise; +} + +/** Ports real FlashForge firmware always listens on. */ +const DEFAULT_COMMAND_PORT = 8899; +const DEFAULT_HTTP_PORT = 8898; + +export const getTrack = (): Track => (process.env.FFUI_E2E_TRACK === 'hardware' ? 'hardware' : 'emulator'); + +/** + * Emulator port allocation. + * + * Fixed, well-spaced ports keep parallel-safe isolation simple and make a stray + * instance easy to identify by port when something leaks. + */ +const EMULATOR_PRINTERS: ReadonlyArray<{ + label: string; + model: EmulatorModel; + serial: string; + machineName: string; + tcpPort: number; + httpPort: number; + hasMaterialStation: boolean; +}> = [ + { + label: 'Adventurer 5M Pro (emulated)', + model: 'adventurer-5m-pro', + serial: 'E2E-SN-5MPRO', + machineName: 'E2E-5MPro', + tcpPort: 8899, + httpPort: 8898, + hasMaterialStation: false, + }, + { + label: 'AD5X (emulated)', + model: 'adventurer-5x', + serial: 'E2E-SN-AD5X', + machineName: 'E2E-AD5X', + tcpPort: 8899, + httpPort: 8898, + hasMaterialStation: true, + }, +]; + +const EMULATOR_CHECK_CODE = '123'; + +export const listTargetDescriptors = (): TargetDescriptor[] => { + if (getTrack() === 'hardware') { + return loadHardwarePrintersSync().map((config) => ({ + label: config.label, + hasMaterialStation: config.kind === 'ad5x' || config.kind.startsWith('creator-5'), + supportsSftp: config.ssh !== undefined, + // Real printers always listen on the firmware default ports. + supportsManualConnect: true, + create: async () => await createHardwareTarget(config), + })); + } + + return EMULATOR_PRINTERS.map((printer) => ({ + label: printer.label, + hasMaterialStation: printer.hasMaterialStation, + // The emulator runs no SSH server, so SFTP scenarios never apply here. + supportsSftp: false, + supportsManualConnect: printer.tcpPort === DEFAULT_COMMAND_PORT && printer.httpPort === DEFAULT_HTTP_PORT, + create: async () => + await createEmulatorTarget({ + label: printer.label, + model: printer.model, + serial: printer.serial, + checkCode: EMULATOR_CHECK_CODE, + machineName: printer.machineName, + tcpPort: printer.tcpPort, + httpPort: printer.httpPort, + }), + })); +}; + +/** + * Descriptors for running two printers at once. + * + * Single-printer specs each get an instance on the firmware default ports, which is + * fine because their describes run sequentially and tear down before the next starts. + * Running two at once needs distinct ports, so every instance after the first is + * shifted. Those shifted instances are still reachable by discovery and by a seeded + * profile (both carry explicit ports); only the manual connect form, which assumes the + * defaults, cannot reach them. + */ +export const listMultiPrinterDescriptors = (): TargetDescriptor[] => { + if (getTrack() === 'hardware') { + return listTargetDescriptors(); + } + + return EMULATOR_PRINTERS.map((printer, index) => { + const portOffset = index * 100; + const tcpPort = printer.tcpPort + portOffset; + const httpPort = printer.httpPort + portOffset; + + return { + label: printer.label, + hasMaterialStation: printer.hasMaterialStation, + supportsSftp: false, + supportsManualConnect: tcpPort === DEFAULT_COMMAND_PORT && httpPort === DEFAULT_HTTP_PORT, + create: async () => + await createEmulatorTarget({ + label: printer.label, + model: printer.model, + serial: printer.serial, + checkCode: EMULATOR_CHECK_CODE, + machineName: printer.machineName, + tcpPort, + httpPort, + }), + }; + }); +}; + +/** + * Explains why a track has nothing to run, so a skipped suite reports a reason + * instead of silently passing with zero tests. + */ +export const describeTrackSkipReason = (descriptors: readonly TargetDescriptor[]): string | null => { + if (descriptors.length > 0) { + return null; + } + + return getTrack() === 'hardware' + ? 'No hardware printers configured. Set FFUI_E2E_HARDWARE_CONFIG, create ~/.flashforgeui-e2e/hardware-printers.json, or connect a printer in FlashForgeUI first.' + : 'No emulator printers defined.'; +}; diff --git a/tests/fixtures/print-files/ad5x-multi-tool.3mf b/tests/fixtures/print-files/ad5x-multi-tool.3mf new file mode 100644 index 0000000000000000000000000000000000000000..f3cdba52a53372a4815a965e5eb267945daf5aa5 GIT binary patch literal 842441 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%0DJX(ce(GaZF|9r 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

slW(j{QV@n_)Q92gTr%%H`Q> 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%0AnNX5m>i+@oQ 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�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 z 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

8b+X{45hI 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

RkC8Bd+y(wkinBF3mV6IdVh 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 literal 0 HcmV?d00001 diff --git a/tests/fixtures/print-files/ad5x-single-tool.3mf b/tests/fixtures/print-files/ad5x-single-tool.3mf new file mode 100644 index 0000000000000000000000000000000000000000..3c3d62acc87d6fadc55cd9efbdfa418be5f46512 GIT binary patch literal 664764 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 z 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

diff --git a/src/shared/types/config.ts b/src/shared/types/config.ts index 12e557e..7ac3aad 100644 --- a/src/shared/types/config.ts +++ b/src/shared/types/config.ts @@ -110,6 +110,7 @@ export interface AppConfig { readonly webUIThemeProfiles: readonly ThemeProfile[]; readonly StartAtBoot: boolean; readonly StartMinimized: boolean; + readonly MinimizeToTray: boolean; } /** @@ -151,6 +152,7 @@ export interface MutableAppConfig { webUIThemeProfiles: readonly ThemeProfile[]; StartAtBoot: boolean; StartMinimized: boolean; + MinimizeToTray: boolean; } /** @@ -297,6 +299,10 @@ export const DEFAULT_CONFIG: AppConfig = { webUIThemeProfiles: [...SYSTEM_THEME_PROFILES], StartAtBoot: false, StartMinimized: false, + // Off by default: hiding the window is only safe when the tray icon is actually visible, and + // tray support is not guaranteed on Linux (stock GNOME needs an AppIndicator extension). Opting + // in after seeing the icon avoids stranding users with no way back to the window. + MinimizeToTray: false, } as const; /** From 99ad79fb1ce6642dce19e5bdf2fe56f9d9e2941c Mon Sep 17 00:00:00 2001 From: GhostTypes <106415648+GhostTypes@users.noreply.github.com> Date: Fri, 31 Jul 2026 16:42:13 -0400 Subject: [PATCH 53/93] test(webui): run browser E2E against the real headless server --- .github/workflows/ci.yml | 19 +- CLAUDE.md | 21 +- docs/TESTING.md | 363 +++++++++++++++ package.json | 2 +- playwright.config.ts | 7 +- scripts/run-playwright-browser.cjs | 56 +++ tests/e2e/browser/helpers/headless-webui.ts | 392 ++++++++++++++++ .../browser/helpers/webui-fixture-server.ts | 430 ------------------ tests/e2e/browser/webui-auth.spec.ts | 175 +++++-- tests/e2e/browser/webui-smoke.spec.ts | 233 ++++++---- .../e2e/electron/helpers/emulator-harness.ts | 9 +- 11 files changed, 1133 insertions(+), 574 deletions(-) create mode 100644 docs/TESTING.md create mode 100644 scripts/run-playwright-browser.cjs create mode 100644 tests/e2e/browser/helpers/headless-webui.ts delete mode 100644 tests/e2e/browser/helpers/webui-fixture-server.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20b3e63..879deb9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: run: pnpm test e2e-emulator: - name: E2E (emulator track) + name: E2E (emulator + WebUI) runs-on: ubuntu-latest needs: verify steps: @@ -102,8 +102,9 @@ jobs: working-directory: emulator run: npm ci - - name: Install Playwright system dependencies - run: pnpm exec playwright install-deps chromium + # The browser track needs the chromium binary itself, not just its system libraries. + - name: Install Playwright chromium + run: pnpm exec playwright install --with-deps chromium # Electron refuses to start if its SUID sandbox helper is not root-owned and # setuid, which is how pnpm unpacks it. Fixing the binary keeps the app launching @@ -120,11 +121,21 @@ jobs: env: FF_EMULATOR_ROOT: ${{ github.workspace }}/emulator + # Browser coverage of the WebUI. It launches the real app with --headless against the + # same emulator, so it needs Electron and a display too - hence this job rather than + # the fast verify one. Runs even if the Electron track failed, since the two cover + # different surfaces and one failing should not hide the other. + - name: Run WebUI browser E2E + if: success() || failure() + run: xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" pnpm test:e2e + env: + FF_EMULATOR_ROOT: ${{ github.workspace }}/emulator + - name: Upload Playwright artifacts if: failure() uses: actions/upload-artifact@v4 with: - name: playwright-emulator-artifacts + name: playwright-e2e-artifacts path: | test-results/ playwright-report/ diff --git a/CLAUDE.md b/CLAUDE.md index a57ec4b..b6d80e8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # FlashForgeUI-Electron Development Guide -**Last Updated:** 2026-07-09 15:16 ET (America/New_York) +**Last Updated:** 2026-07-31 16:11 ET (America/New_York) This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. @@ -38,6 +38,7 @@ For detailed architectural information, see the comprehensive reference document - **[INTEGRATIONS.md](ai_docs/INTEGRATIONS.md)** - Camera streaming, Spoolman, notifications, Discord, persistence - **[THEME_SYSTEM.md](ai_docs/THEME_SYSTEM.md)** - CSS variables, theme computation, design patterns, hardcoded CSS detection - **[TOOLING.md](ai_docs/TOOLING.md)** - Development tools, commands, testing constraints, code search MCP tools +- **[docs/TESTING.md](docs/TESTING.md)** - Test surfaces, the emulator/hardware E2E tracks, CI pipeline, known coverage gaps --- @@ -57,7 +58,7 @@ For detailed architectural information, see the comprehensive reference document - **Documentation**: every repo-maintained `.ts`, `.tsx`, `.js`, `.jsx`, and `.cjs` source file should begin with an `@fileoverview` block describing purpose, key exports, and relationships. Use `pnpm docs:check` to catch gaps under `src/` and `pnpm docs:combine` to refresh `fileoverview-report.md`. -- **Testing workflow**: `pnpm test` runs Jest over `src/`, `pnpm test:e2e` runs browser Playwright against the built WebUI fixture server, and `pnpm test:e2e:electron*` covers desktop Playwright flows. `test:all` currently excludes the Electron suites, so run the Electron slice explicitly when desktop behavior changes. +- **Testing workflow**: **ALWAYS read [docs/TESTING.md](docs/TESTING.md) before writing, changing, or reasoning about any test.** It is the authoritative description of every test surface, the two Electron E2E tracks (`emulator` vs `hardware`, selected by `FFUI_E2E_TRACK`), what each spec actually proves, the CI pipeline, and the known coverage gaps. In brief: `pnpm test` runs Jest over `src/`, `pnpm test:e2e` runs browser Playwright against the built WebUI fixture server, `pnpm test:e2e:electron:emulator` runs the CI-safe Electron track against `flashforge-emulator-v2`, and `pnpm test:e2e:electron:hardware` runs the same specs against real bench printers. `test:all` excludes the Electron suites, so run the Electron slice explicitly when desktop behavior changes. - **Validation**: run the smallest meaningful checks (`pnpm type-check`, `pnpm lint`, targeted scripts) before handing work back. Reserve `pnpm build*` for user requests or when architectural changes demand it. @@ -102,7 +103,7 @@ For detailed architectural information, see the comprehensive reference document 12. **WebUI cache regressions**: built WebUI assets must remain version-stamped and served with no-cache headers. The browser Playwright suite exists specifically to catch stale asset mixes, icon hydration mismatches, and camera bootstrap regressions before release. -13. **Desktop E2E boundaries**: use `tests/e2e/electron/desktop-smoke.spec.ts` for live `%APPDATA%` smoke coverage and `tests/e2e/electron/desktop-emulator.spec.ts` for isolated emulator-backed lifecycle coverage. On Windows, prefer the dedicated `package.json` scripts over ad hoc Playwright grep invocations. +13. **Desktop E2E is two tracks over one set of specs**: `tests/e2e/electron/specs/*.spec.ts` run against either the emulator or real hardware depending on `FFUI_E2E_TRACK`; specs branch on target *capabilities* (`hasMaterialStation`, `supportsSftp`, `supportsManualConnect`), never on the track name. Don't fork a spec per track. Prefer the dedicated `package.json` scripts over ad hoc Playwright invocations. See [docs/TESTING.md](docs/TESTING.md). 14. **Release builds are unsigned (no code-signing cert)**: there is no Windows (or macOS) code-signing certificate, so every release artifact - both CI and local `pnpm build:win` - is `NotSigned`. The `signtool.exe` lines in the local build log run but produce no valid Authenticode signature. This is expected, not a regression; Windows users get the normal SmartScreen "unknown publisher" prompt. Don't chase a "missing signature" as a bug. @@ -208,13 +209,17 @@ Currently targets AD5X + Adventurer 5M / 5M Pro only (Creator 5 / Creator 5 Pro ### Testing & Automation +**Authoritative reference: [docs/TESTING.md](docs/TESTING.md)** - read it before touching any test. + - `src/**/__tests__/*` - Jest coverage for managers, services, calibration, WebUI server/routes, WebUI static helpers, and build utilities - `tests/e2e/browser/webui-smoke.spec.ts`, `tests/e2e/browser/webui-auth.spec.ts`, `tests/e2e/browser/helpers/webui-fixture-server.ts` - browser Playwright coverage for the built WebUI -- `tests/e2e/electron/desktop-smoke.spec.ts` - live desktop smoke test against the local FlashForgeUI profile -- `tests/e2e/electron/desktop-emulator.spec.ts`, `tests/e2e/electron/helpers/emulator-harness.ts` - emulator-backed Electron lifecycle coverage across modern and legacy printers -- `tests/fixtures/calibration/` - synthetic calibration fixture data (not referenced by automated tests; used for manual local testing) -- `scripts/run-playwright-electron-live.cjs`, `scripts/run-playwright-electron-emulator.cjs` - entry points for the Electron Playwright suites -- `package.json` - canonical place for the Electron slice scripts (`test:e2e:electron:emulator`, `:legacy`, `:legacy-multi`, `:modern-multi`, `:smoke`, `:live`) +- `tests/e2e/electron/specs/*.spec.ts` - connect, upload, LED, multi-printer, and SFTP round-trip coverage; each runs on whichever track `FFUI_E2E_TRACK` selects +- `tests/e2e/electron/support/track.ts` - track selection and target enumeration; `printer-target.ts` - the emulator/hardware abstraction; `hardware-config.ts` - out-of-tree credential resolution + discovery-by-serial +- `tests/e2e/electron/helpers/emulator-harness.ts` - boots/tears down `flashforge-emulator-v2` instances (process-group kill on POSIX; see docs/TESTING.md before changing teardown) +- `tests/e2e/electron/discord-hardware.spec.ts` - hardware-only Discord webhook coverage, deliberately outside `specs/` so the emulator runner skips it +- `tests/fixtures/print-files/` - real slicer output driving the upload specs; `tests/fixtures/calibration/` - synthetic calibration data for manual local testing +- `scripts/run-playwright-electron-{emulator,hardware,discord}.cjs` - entry points for the Electron Playwright tracks +- `.github/workflows/ci.yml` - `verify` (type-check, lint, build, Jest) + `e2e-emulator` (emulator track under xvfb) --- diff --git a/docs/TESTING.md b/docs/TESTING.md new file mode 100644 index 0000000..08df223 --- /dev/null +++ b/docs/TESTING.md @@ -0,0 +1,363 @@ +# Testing Guide + +**Last Updated:** 2026-07-31 + +This document describes every automated test surface in FlashForgeUI, what each one +actually proves, and where the gaps are. Read it before adding tests so new coverage +lands on the right surface, and before trusting a green run to mean "this works." + +--- + +## The Four Surfaces + +| Surface | Runner | Command | Needs | In CI | +| --- | --- | --- | --- | --- | +| Unit / integration | Jest | `pnpm test` | nothing | yes | +| WebUI browser E2E | Playwright (chromium) | `pnpm test:e2e` | emulator + Electron | yes | +| Electron E2E — **emulator track** | Playwright (`_electron`) | `pnpm test:e2e:electron:emulator` | `flashforge-emulator-v2` checkout | yes | +| Electron E2E — **hardware track** | Playwright (`_electron`) | `pnpm test:e2e:electron:hardware` | real printers on the LAN | no (impossible) | +| Discord webhook (hardware) | Playwright (`_electron`) | `pnpm test:e2e:electron:discord` | real AD5X + webhook relay | no | + +`pnpm type-check` covers **both** `tsconfig.json` (`src/`) and `tsconfig.e2e.json` +(`tests/` + both Playwright configs). This matters: before the e2e tsconfig was wired +in, the Electron suite rotted for months without a single type error surfacing. + +--- + +## Track Selection + +The Electron suite has one set of spec files serving two tracks. The track is chosen +by a single environment variable read in `tests/e2e/electron/support/track.ts`: + +``` +FFUI_E2E_TRACK=emulator # default — boots flashforge-emulator-v2 instances +FFUI_E2E_TRACK=hardware # drives the real printers on the developer's bench +``` + +The runner scripts set it for you; you should never need to export it by hand. + +Specs never fork on the track name. They parameterize over **target descriptors** and +branch on *capabilities*: + +- `hasMaterialStation` — AD5X / Creator 5 raise the material matching dialog +- `supportsSftp` — only real EasySSH-provisioned printers have an SSH server +- `supportsManualConnect` — see the port note below + +A track with nothing to run reports a **skip reason** rather than silently passing with +zero tests (`describeTrackSkipReason()`). + +### Why `supportsManualConnect` exists + +The manual connect form collects IP + type + serial + check code but no ports, so it +always dials the firmware defaults `8899`/`8898`. Real printers always listen there. +Only one emulator instance per machine can, so the multi-printer descriptors shift +every instance after the first by +100 (`8999`/`8998`). Shifted instances stay +reachable by discovery and by a seeded profile — both carry explicit ports — but not by +the manual form, so that one case skips itself with an explanatory message. + +--- + +## Emulator Track + +**Command:** `pnpm test:e2e:electron:emulator` (builds first, then runs +`tests/e2e/electron/specs`) + +**Printers:** two instances booted per describe block, from +[`flashforge-emulator-v2`](https://github.com/GhostTypes/flashforge-emulator-v2): + +| Label | Model | Serial | Ports | Material station | +| --- | --- | --- | --- | --- | +| Adventurer 5M Pro (emulated) | `adventurer-5m-pro` | `E2E-SN-5MPRO` | 8899 / 8898 | no | +| AD5X (emulated) | `adventurer-5x` | `E2E-SN-AD5X` | 8899 / 8898 | yes | + +Check code is `123`. Simulation runs in `manual` mode so nothing advances on its own. + +**Emulator location:** defaults to `../flashforge-emulator-v2` beside this checkout; +override with `FF_EMULATOR_ROOT`. CI checks the public repo out into `emulator/`. + +**Current size:** 13 tests, ~3 minutes, one worker. + +### Process-group teardown (do not "simplify" this) + +`emulator-harness.ts` spawns `npm run headless:instance`, so the process that actually +binds the printer ports is a **grandchild** (npm → tsx). npm does not forward `SIGTERM` +to it. Signalling the child alone leaves the grandchild alive still holding 8899/8898, +and the next describe dies with `EADDRINUSE`. + +The harness therefore spawns `detached` on POSIX and signals the whole process group +via `process.kill(-pid, …)`. Windows has no process groups and uses `taskkill /T` +instead, which is why this bug was invisible locally and only appeared on the first CI +run. + +--- + +## Hardware Track + +**Command:** `pnpm test:e2e:electron:hardware` + +Same specs, real printers. Cannot run in CI — it needs printers on the LAN. + +### Credential resolution + +Deliberately **outside** the working tree so they can never be committed even if +`.gitignore` is wrong. In order: + +1. `$FFUI_E2E_HARDWARE_CONFIG` — explicit path to a JSON config +2. `~/.flashforgeui-e2e/hardware-printers.json` +3. The developer's real FlashForgeUI profile (**read-only**), which already holds + serials and check codes + +**IP addresses are never read from any of those.** They resolve live by UDP discovery +keyed on serial, because printer IPs move with DHCP — the bench AD5X moved `.132` → +`.133` between two runs. Serial is the only stable identity a printer has. A +powered-off printer produces "did not answer discovery… discovered instead: …" rather +than a bare timeout mid-test. + +### Safety protocol + +Uploads always run with **Start Now explicitly unchecked**, and every upload is +followed by `assertNotPrinting()`, which reads `/detail` back and — if a print somehow +started — cancels it, waits, and sends Clear Platform to return the printer to a +controllable state. That path should never fire; if it does, the test fails loudly. +Uploaded fixtures are removed in `afterEach` so hardware runs leave no residue. + +### Profile isolation + +Every launch gets a fresh temp `userData` via `FFUI_USER_DATA_DIR`, and +`launchFFUI()` asserts the app *honored* it before any test touches the UI. If the app +ignored the variable the run would mutate the developer's real `%APPDATA%/FlashForgeUI` +profile, so it refuses to continue. **Do not relax that assertion.** + +--- + +## What The Tracks Test + +### `specs/connect.spec.ts` — 3 tests per printer + +- **Saved-printer auto-connect** — seeded `printer_details.json`, app connects on boot, + dashboard renders, tab carries the printer's name +- **Network discovery** — open connect flow → scan → match the row **by serial** (the + only identity that survives DHCP) → connect +- **Manual connect** — the regression net for 1.0.5-alpha.9. A named printer type skips + the TCP probe, so the form must supply the serial and check code the discovery + broadcast would have carried, and must use the check code it collected **without a + second prompt**. Also asserts modern types require credentials and legacy does not. + +### `specs/upload.spec.ts` — 2 tests per printer + +- **Upload without starting a print** — the regression net for the 1.0.5-alpha.10 + hotfix, where pressing OK threw `ReferenceError: isAD5X is not defined` and silently + uploaded nothing. A test that only checked the dialog rendered would have missed it, + because the failure was in the confirm handler. So the assertion is that the file + **actually landed on the printer**, verified out of band. +- **Material matching dialog rules** — appears for every 3MF on a material-station + printer (single filament included, since each tool must still be bound to a slot); + must **never** appear on 5M-series. Requirement-row count matches the filament count + the parser reported. + +Fixtures are real slicer output (`tests/fixtures/print-files/`), not synthetic stubs, +because the upload path parses embedded metadata and per-tool filament data. Their +tool counts were read from the parser, not from upstream file names — those names are +actively misleading. + +### `specs/led.spec.ts` — 1 test per printer + +On → off → on, with every assertion reading `lightStatus` back from the printer's own +`/detail` endpoint rather than the button's rendered state. A button that toggles its +own styling while the command never reaches the printer is exactly the failure this +catches, so trusting the UI here would defeat the purpose. Ends with the LED back on. + +### `specs/multi-printer.spec.ts` — 1 test + +Two printers connected simultaneously, each in its own context; both tabs report +connected and each carries its own printer's name. This is where cross-talk bugs hide — +one printer's polling updating another's tab, or a context switch leaving stale data. + +Follows the real user flow rather than a shortcut: with more than one saved printer the +app raises the auto-connect choice dialog, the user picks one, and the second is added +with the "+" tab button (which itself raises a warning that must be acknowledged). +Seeding two printers and waiting for two tabs would simply hang. + +### `specs/sftp-roundtrip.spec.ts` — hardware only + +Upload through the GUI → find it in the SFTP file manager → delete it there → confirm +it is gone from the printer itself, not just from the dialog's rendering. Proves the +whole SSH stack: credentials from `SSHSettingsService`, pooled connection per context, +listing and delete both over SFTP. Skipped on the emulator track, which runs no SSH +server. + +### `discord-hardware.spec.ts` — hardware only, separate runner + +Lives outside `specs/` so the emulator runner never collects it. Drives a real AD5X +with a local webhook relay and asserts the Discord payload — including camera snapshots +— matches what the UI is showing. Needs `FFUI_E2E_AD5X_IP` + `FFUI_E2E_AD5X_CHECK_CODE`. + +### Cross-cutting: renderer error guard + +Every Electron test ends with `assertNoRendererErrors()`, which fails the test on any +`pageerror` or `console.error` from **any** window (allowlisting only Electron's +built-in Autofill noise). This is what turns "the UI looked fine" into a real +assertion, and it is how a silent `ReferenceError` in a confirm handler gets caught. + +--- + +## Unit / Integration (Jest) + +55 suites, ~1,880 tests, `src/**/__tests__/`. Node environment, ts-jest. `electron-log` +is mocked so tests can never write to the real user-profile log. + +Heaviest coverage: + +- **WebUI server** (14 suites) — AuthManager, WebSocketManager, WebUIManager, + CameraStreamProxy, security middleware, static asset options, and every route module +- **Calibration** (8 suites) — FFT processing, shaper analysis, bed/screw solving, + Klipper config parsing, deviation analysis, workflow engine +- **Services** (12 suites) — connection establishment, polling coordination, discovery, + data transformation, SSH settings, Go2rtc, saved printers +- **WebUI static client** (9 suites) — Transport, authentication, camera, + context-switching, Spoolman, icons, palette, formatting +- **Shared** — material colour matching (CIEDE2000), palettes, printer settings defaults + +--- + +## WebUI Browser E2E (Playwright) + +`tests/e2e/browser/`, 8 tests, ~20 seconds. Runs in the CI `e2e` job. + +**There is no fixture server and nothing is stubbed.** `startHeadlessWebUI()` boots +emulator printers, seeds an isolated profile, launches the real app with +`--headless --all-saved-printers`, and waits for the WebUI server *the app itself* +starts. Every response comes from the production stack: real `createAPIRoutes`, real +`AuthManager` and auth middleware, real security and static-asset middleware, real +`WebSocketManager` broadcasting real polling data from the emulated printers. + +This also gives headless mode its only end-to-end coverage. + +| Test | Proves | +| --- | --- | +| rejects a bad password | the real `AuthManager` refuses it and the UI stays locked with no token stored | +| logs in / remembers token | dashboard appears, `#connection-text` reads `Connected` (so the websocket passed the real auth gate), and the stored token is accepted by the real auth middleware | +| restores the session | a remembered token survives reload with no second prompt | +| refuses API access | anonymous and forged tokens both get a real 401 | +| revokes on logout | a logged-out token stops working — a real security property the fixture never implemented | +| versioned assets | every local ``/`