@@ -24,6 +24,7 @@ interface SpoolQRCodePrintingDialog {
2424 spoolIds : number [ ] ;
2525}
2626
27+ // Adapt spool records into the generic QR print dialog while keeping spool presets isolated from export-specific buckets.
2728const SpoolQRCodePrintingDialog = ( { spoolIds } : SpoolQRCodePrintingDialog ) => {
2829 const t = useTranslate ( ) ;
2930 const currentPresetType = "spool" ;
@@ -83,11 +84,10 @@ const SpoolQRCodePrintingDialog = ({ spoolIds }: SpoolQRCodePrintingDialog) => {
8384 } )
8485 . filter ( ( item ) => item !== null ) as ISpool [ ] ;
8586
86- // Selected preset state
87+ // Selected preset state.
8788 const [ selectedPresetState , setSelectedPresetState ] = useSavedState < string | undefined > ( "selectedPreset" , undefined ) ;
8889
89- // Keep a local copy of the settings which is what's actually displayed. Use the remote state only for saving.
90- // This decouples the debounce stuff from the UI
90+ // Keep edits local until the user explicitly saves so partially edited presets do not overwrite stored defaults.
9191 const [ localCurrentPresets , setLocalCurrentPresets ] = useState < SpoolQRCodePrintSettings [ ] | undefined > ( ) ;
9292 const remoteCurrentPresets = useGetPrintPresets ( ) ;
9393 const remoteOtherPresets = useGetPrintPresets ( "print_presets_filament" ) ;
@@ -96,12 +96,13 @@ const SpoolQRCodePrintingDialog = ({ spoolIds }: SpoolQRCodePrintingDialog) => {
9696 const currentPresets = localCurrentPresets ?? remoteCurrentPresets ;
9797 const otherPresets = remoteOtherPresets ?? [ ] ;
9898
99- const savePresetsRemote = ( ) => {
99+ const savePresetsRemote = async ( ) => {
100100 if ( ! localCurrentPresets ) return ;
101- setRemotePresets ( localCurrentPresets ) ;
101+ await setRemotePresets ( localCurrentPresets ) ;
102102 } ;
103103
104- // Functions to update settings
104+ // Functions to update settings.
105+ // New presets need an id immediately so the selector can switch to them before they are persisted.
105106 const addNewPreset = ( ) => {
106107 if ( ! currentPresets ) return ;
107108 const newId = uuidv4 ( ) ;
@@ -110,6 +111,7 @@ const SpoolQRCodePrintingDialog = ({ spoolIds }: SpoolQRCodePrintingDialog) => {
110111 setSelectedPresetState ( toPresetValue ( currentPresetType , newId ) ) ;
111112 return newPreset ;
112113 } ;
114+ // Imported filament presets become spool-owned copies immediately so later edits never touch the source preset.
113115 const promotePresetToCurrentType = ( preset : SpoolQRCodePrintSettings ) : SpoolQRCodePrintSettings | undefined => {
114116 if ( ! currentPresets ) return ;
115117 const baseName = ( preset . labelSettings . printSettings ?. name ?? defaultPresetName ) . trim ( ) || defaultPresetName ;
@@ -119,6 +121,7 @@ const SpoolQRCodePrintingDialog = ({ spoolIds }: SpoolQRCodePrintingDialog) => {
119121 setSelectedPresetState ( toPresetValue ( currentPresetType , promotedPreset . labelSettings . printSettings . id ) ) ;
120122 return promotedPreset ;
121123 } ;
124+ // Duplicates get a fresh id so later edits do not mutate the original preset in place.
122125 const duplicateCurrentPreset = ( ) => {
123126 if ( ! currentPresets ) return ;
124127 const newPreset = {
@@ -129,6 +132,7 @@ const SpoolQRCodePrintingDialog = ({ spoolIds }: SpoolQRCodePrintingDialog) => {
129132 setLocalCurrentPresets ( [ ...currentPresets , newPreset ] ) ;
130133 setSelectedPresetState ( toPresetValue ( currentPresetType , newPreset . labelSettings . printSettings . id ) ) ;
131134 } ;
135+ // Replace only the active preset inside the working copy shown by this dialog.
132136 const updateCurrentPreset = ( newSettings : SpoolQRCodePrintSettings ) => {
133137 if ( ! currentPresets ) return ;
134138 const parsed = parsePresetValue ( selectedPresetState ) ;
@@ -142,6 +146,7 @@ const SpoolQRCodePrintingDialog = ({ spoolIds }: SpoolQRCodePrintingDialog) => {
142146 ) ,
143147 ) ;
144148 } ;
149+ // Clearing the selection lets the fallback logic choose the next valid preset on the next render.
145150 const deleteCurrentPreset = ( ) => {
146151 if ( ! currentPresets ) return ;
147152 const parsed = parsePresetValue ( selectedPresetState ) ;
@@ -150,10 +155,10 @@ const SpoolQRCodePrintingDialog = ({ spoolIds }: SpoolQRCodePrintingDialog) => {
150155 setSelectedPresetState ( undefined ) ;
151156 } ;
152157
153- // Initialize presets
158+ // Initialize presets.
154159 let curPreset : SpoolQRCodePrintSettings ;
155160 if ( currentPresets === undefined ) {
156- // DB not loaded yet, use a temporary one
161+ // Use a temporary preset while settings are still loading so the dialog can render immediately.
157162 curPreset = {
158163 labelSettings : {
159164 printSettings : {
@@ -163,36 +168,34 @@ const SpoolQRCodePrintingDialog = ({ spoolIds }: SpoolQRCodePrintingDialog) => {
163168 } ,
164169 } ;
165170 } else {
166- // DB is loaded, find the selected setting
167171 if ( currentPresets . length === 0 ) {
168- // DB loaded, but no settings found, add a new one and select it
172+ // First-time users still need one editable preset so the dialog never opens into an empty state.
169173 const newSetting = addNewPreset ( ) ;
170174 if ( ! newSetting ) {
171175 console . error ( "Error adding new setting, this should never happen" ) ;
172176 return ;
173177 }
174178
175- // Mutate the allPrintSettings list so that the rest of the UI will work fine
179+ // The rest of this render expects the working list to already contain the preset it should show.
176180 currentPresets . push ( newSetting ) ;
177181 curPreset = newSetting ;
178182 } else {
179183 const parsedSelectedPreset = parsePresetValue ( selectedPresetState ) ;
180184 if ( ! parsedSelectedPreset ) {
181- // No setting has been selected, select the first one
185+ // Default to the first saved preset until the user picks a different one.
182186 curPreset = currentPresets [ 0 ] ;
183187 setSelectedPresetState ( toPresetValue ( currentPresetType , currentPresets [ 0 ] . labelSettings . printSettings . id ) ) ;
184188 } else if ( parsedSelectedPreset . type === otherPresetType ) {
185189 curPreset = currentPresets [ 0 ] ;
186190 setSelectedPresetState ( toPresetValue ( currentPresetType , currentPresets [ 0 ] . labelSettings . printSettings . id ) ) ;
187191 } else {
188- // A setting has been selected, find it
189192 const foundSetting = currentPresets . find (
190193 ( settings ) => settings . labelSettings . printSettings . id === parsedSelectedPreset . id ,
191194 ) ;
192195 if ( foundSetting ) {
193196 curPreset = foundSetting ;
194197 } else {
195- // Selected setting not found, reset to first available preset.
198+ // Fall back to the first saved preset when the remembered selection no longer exists .
196199 curPreset = currentPresets [ 0 ] ;
197200 setSelectedPresetState ( toPresetValue ( currentPresetType , currentPresets [ 0 ] . labelSettings . printSettings . id ) ) ;
198201 }
@@ -277,6 +280,7 @@ Spool Weight: {filament.spool_weight} g
277280 } ) ;
278281 }
279282
283+ // Expose spool, filament, and vendor placeholders because the same tag picker drives preview text and labels.
280284 const templateTags = [ ...spoolTags , ...filamentTags , ...vendorTags ] ;
281285
282286 return (
@@ -439,9 +443,13 @@ Spool Weight: {filament.spool_weight} g
439443 type = "primary"
440444 size = "large"
441445 icon = { < SaveOutlined /> }
442- onClick = { ( ) => {
443- savePresetsRemote ( ) ;
444- messageApi . success ( t ( "notifications.saveSuccessful" ) ) ;
446+ onClick = { async ( ) => {
447+ try {
448+ await savePresetsRemote ( ) ;
449+ messageApi . success ( t ( "notifications.saveSuccessful" ) ) ;
450+ } catch ( error ) {
451+ messageApi . error ( error instanceof Error ? error . message : "Save failed" ) ;
452+ }
445453 } }
446454 >
447455 { t ( "printing.generic.saveSetting" ) }
0 commit comments