archiveAmsMapping.ts 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /**
  2. * Reading the archive's saved slicer AMS-slot pick back out of `extra_data`.
  3. *
  4. * A virtual printer with "Save AMS mapping" on stores the slicer's own
  5. * live-resolved tray choice on the archive as
  6. * `extra_data.slicer_ams_mapping = { mapping, printer_id }` (written by
  7. * `ArchiveService.archive_print`). The tray IDs in `mapping` are global tray
  8. * IDs, which only mean something against the AMS layout of the one printer
  9. * they were resolved against — slot 3 on another printer can hold a completely
  10. * different spool. `printer_id` records which printer that was.
  11. *
  12. * Lives here rather than inline in the modal so the printer-scoping rule can
  13. * be tested on its own: it is the only thing standing between a saved mapping
  14. * and the wrong physical spool.
  15. */
  16. /** Shape of `extra_data.slicer_ams_mapping`. Every field optional — this is
  17. * free-form JSON off the wire, and older archives predate the key entirely. */
  18. export interface SavedSlicerAmsMapping {
  19. mapping?: number[];
  20. printer_id?: number;
  21. }
  22. /**
  23. * The saved mapping, but only when it is safe to apply to `printerId`.
  24. *
  25. * Returns `undefined` — meaning "no saved mapping in scope, behave as before" —
  26. * when the archive has none, when the stored value is malformed, when no
  27. * printer is selected yet, or when the selected printer is not the one the
  28. * mapping was resolved against.
  29. */
  30. export function resolveArchiveSlicerAmsMapping(
  31. extraData: Record<string, unknown> | null | undefined,
  32. printerId: number | null | undefined,
  33. ): number[] | undefined {
  34. // No printer selected means there is nothing to compare against. Bailing
  35. // here also stops `undefined === undefined` from reading as a match below.
  36. if (printerId == null) return undefined;
  37. const saved = extraData?.slicer_ams_mapping as SavedSlicerAmsMapping | undefined;
  38. if (!saved || typeof saved !== 'object') return undefined;
  39. if (saved.printer_id !== printerId) return undefined;
  40. if (!Array.isArray(saved.mapping) || saved.mapping.length === 0) return undefined;
  41. return saved.mapping;
  42. }
  43. /**
  44. * The slicer's saved pick for the print being set up, if it applies to `printerId`.
  45. *
  46. * A virtual printer's queue job prints a File Manager file and has no archive
  47. * until it prints, so while editing one its own kept pick (`slicer_ams_mapping`,
  48. * for the job's printer) is the one. Otherwise the archive's, as
  49. * `resolveArchiveSlicerAmsMapping`; a library file without a job has none.
  50. */
  51. export function resolveSlicerAmsMapping({
  52. queueItem,
  53. isLibraryFile,
  54. archiveExtraData,
  55. printerId,
  56. }: {
  57. queueItem?: { printer_id: number | null; slicer_ams_mapping?: number[] | null } | null;
  58. isLibraryFile: boolean;
  59. archiveExtraData: Record<string, unknown> | null | undefined;
  60. printerId: number | null | undefined;
  61. }): number[] | undefined {
  62. if (queueItem?.slicer_ams_mapping?.length && printerId != null && queueItem.printer_id === printerId) {
  63. return queueItem.slicer_ams_mapping;
  64. }
  65. return isLibraryFile ? undefined : resolveArchiveSlicerAmsMapping(archiveExtraData, printerId);
  66. }