@@ -14,6 +14,7 @@ import {
1414 AACSemanticIntent ,
1515 AACTreeMetadata ,
1616} from '../core/treeStructure' ;
17+ import type { AACPageMutation } from '../types/aac' ;
1718import { generateCloneId } from '../utilities/analytics/utils/idGenerator' ;
1819import { ValidationResult } from '../validation/validationTypes' ;
1920import {
@@ -681,6 +682,55 @@ class ObfProcessor extends BaseProcessor {
681682 return { rows : totalRows , columns : totalColumns , order, buttonPositions } ;
682683 }
683684
685+ /**
686+ * Apply mutations to a buttons array for OBF export
687+ * Returns a modified copy of the buttons array with mutations applied
688+ *
689+ * Note: addButton mutations are NOT applied because the button is already
690+ * in the buttons array (added by page.addButton()). We only apply
691+ * removeButton and updateButton mutations.
692+ */
693+ private applyMutationsToButtons (
694+ buttons : AACButton [ ] ,
695+ mutations : readonly AACPageMutation [ ]
696+ ) : AACButton [ ] {
697+ let modifiedButtons = [ ...buttons ] ;
698+
699+ for ( const mutation of mutations ) {
700+ switch ( mutation . type ) {
701+ case 'addButton' :
702+ // Skip - button is already in the array from page.addButton()
703+ break ;
704+
705+ case 'removeButton' : {
706+ modifiedButtons = modifiedButtons . filter ( ( b ) => b . id !== mutation . buttonId ) ;
707+ break ;
708+ }
709+
710+ case 'updateButton' : {
711+ modifiedButtons = modifiedButtons . map ( ( b ) => {
712+ if ( b . id === mutation . buttonId ) {
713+ // Create a new AACButton instance with the patched properties
714+ const patched = Object . create ( Object . getPrototypeOf ( b ) as object ) ;
715+ Object . assign ( patched , b , mutation . patch ) ;
716+ return patched as AACButton ;
717+ }
718+ return b ;
719+ } ) ;
720+ break ;
721+ }
722+
723+ case 'addWordListItem' :
724+ case 'removeWordListItem' :
725+ case 'clearWordList' :
726+ // OBF doesn't have WordList - skip
727+ break ;
728+ }
729+ }
730+
731+ return modifiedButtons ;
732+ }
733+
684734 private createObfBoardFromPage (
685735 page : AACPage ,
686736 fallbackName : string ,
@@ -700,6 +750,12 @@ class ObfProcessor extends BaseProcessor {
700750 } ) ;
701751 }
702752
753+ // Apply mutations if present
754+ const buttons =
755+ page . pendingMutations . length > 0
756+ ? this . applyMutationsToButtons ( page . buttons , page . pendingMutations )
757+ : page . buttons ;
758+
703759 return {
704760 format : OBF_FORMAT_VERSION ,
705761 id : page . id ,
@@ -715,7 +771,7 @@ class ObfProcessor extends BaseProcessor {
715771 columns,
716772 order,
717773 } ,
718- buttons : page . buttons . map ( ( button ) => {
774+ buttons : buttons . map ( ( button ) => {
719775 const extraButtonInfo = button as AACButton & {
720776 image_id ?: string ;
721777 imageId ?: string ;
@@ -893,21 +949,10 @@ class ObfProcessor extends BaseProcessor {
893949 const obfFilename = this . getPageFilename ( page . id , tree . metadata ) ;
894950 modifiedObfFiles . add ( obfFilename ) ;
895951
896- // NEW: Check if page has mutations to apply
897- const hasMutations = page . pendingMutations && page . pendingMutations . length > 0 ;
898-
899- if ( hasMutations ) {
900- // Apply mutations to the page before creating OBF board
901- const pageWithMutations = this . applyMutationsToPage ( page ) ;
902- const obfBoard = this . createObfBoardFromPage ( pageWithMutations , 'Board' , tree . metadata ) ;
903- const obfContent = JSON . stringify ( obfBoard , null , 2 ) ;
904- newObfFiles . set ( obfFilename , obfContent ) ;
905- } else {
906- // No mutations, use original page
907- const obfBoard = this . createObfBoardFromPage ( page , 'Board' , tree . metadata ) ;
908- const obfContent = JSON . stringify ( obfBoard , null , 2 ) ;
909- newObfFiles . set ( obfFilename , obfContent ) ;
910- }
952+ // createObfBoardFromPage will automatically apply mutations if present
953+ const obfBoard = this . createObfBoardFromPage ( page , 'Board' , tree . metadata ) ;
954+ const obfContent = JSON . stringify ( obfBoard , null , 2 ) ;
955+ newObfFiles . set ( obfFilename , obfContent ) ;
911956 }
912957
913958 // Generate updated manifest if we have pages
0 commit comments