Remove effect such as MergeView

Hi,

I am dynamically adding a unifiedMergeView effect as shown below but I couldn’t figure out how to dynamically remove it - can someone tell me how to do that?

Thank you!

  async showMergeView(xmlPathOrString){
    this.hideMergeView();  // remove existing merge view
    const xml = await this.fetchXml(xmlPathOrString);
    this.mergeViewExt = unifiedMergeView({
      original: xml,
    })
    this.view.dispatch({
      effects: StateEffect.appendConfig.of([this.mergeViewExt])
    });
  }

  hideMergeView() {
    if (this.mergeViewExt) {
      // remove it?
    }
  }

You’ll need to use a configuration compartment.

Thank you - I’ll try that!

Hi again. I have tried, with the help of the documentation and ai, to understand how this works, but I unfortunately wasn’t successful. Here’s the latest code that was suggested:


class MergeViewCompartment extends Compartment {
  constructor(mergeViewExt) {
    super();
    this.mergeViewExt = mergeViewExt;
  }
}

class MyEditor {

  // ...
  showMergeView(xml){
    this.hideMergeView()
    this.#mergeViewExt = unifiedMergeView({
      original: xml,
      diffConfig: {scanLimit: 50000, timeout: 20000}
    })
    this.#mergeViewCompartment = new MergeViewCompartment(this.#mergeViewExt);
    this.#view.dispatch({
       effects: StateEffect.appendConfig.of([this.#mergeViewCompartment])
   });
  }

  hideMergeView(){
    if (this.#mergeViewCompartment) {
      this.#view.dispatch({
        effects: StateEffect.reconfigure.of(
          (s) => s.filter(e => e !== this.#mergeViewCompartment)
        ),
      });
      this.#mergeViewCompartment = null;
      this.#mergeViewExt = null;
    }
  }

  // ...
}

For this, I get Uncaught (in promise) Error: Unrecognized extension value in extension set ([object Object]). This sometimes happens because multiple instances of @codemirror/state are loaded, breaking instanceof checks. I checked but all @codemirror/state packages are deduped to @codemirror/state@6.5.2 ).

This works flawlessly:

    this.#view.dispatch({
      effects: StateEffect.appendConfig.of([this.#mergeViewExt])
    });

But I cannot remove the merge view afterwards without destroying the editor state, obviously.

Please advise, I am still struggling to understand the architecture and the example in the documentation, according to Gemini, is not suited to complex extensions such as the merge view. I tried and it did not work either. Maybe I did something wrong.

Thanks for any pointer!

I recommend you stop trying to get the AI to make sense (it generally won’t, for questions that it hasn’t seen answered a hundred times) and read the link I gave you. It walks through a bit of code that reconfigures an editor.

Thank you for the fast feedback. For the record, what I did wrong was that I failed to include the compartment into list of extensions when the editor state is first configured, and instead tried to add it when showMergeView() was called. This works:

constructor(editorDivId) {
    // ...
    this.#mergeViewCompartment = new Compartment()
    // ...
    const extensions = [
      //..
      this.#mergeViewCompartment.of([]),
    ];
    this.#view = new EditorView({
      state: EditorState.create({ doc: "", extensions }),
      parent: editorDiv
    });
  }

  async showMergeView(xml){
    this.hideMergeView()
    this.#mergeViewExt = unifiedMergeView({
      original: xml
    })
    this.#view.dispatch({
       effects: this.#mergeViewCompartment.reconfigure([this.#mergeViewExt])
    });
  }

  hideMergeView(){
    if (this.#mergeViewExt) {
      this.#view.dispatch({
        effects: this.#mergeViewCompartment.reconfigure([])
     });
      this.#mergeViewExt = null;
    }
  }

In this case, you are right that ai was useless and suggested nonsense. However, it had been very helpful for getting other stuff right about codemirror, probably where more examples existed on the web.