Problem with history preserveItems

I have a view with history plugin with preserveItems: true I now get a doc (checkpoint) and a bunch of steps forward from that doc

I now try to add them to the editor and history like this:

			let editState=EditorState.create({
				schema, doc: doc, plugins: getState().plugins
			});

			for (let i=0; i<steps.length; i++) {
				let tr=editState.tr;
				tr.step(steps[i]);
				editState = editState.apply(tr);
				view.updateState(editState);
			}

When they appear I press ctrl+z but the undo erases all added steps whereas I expected separate undo for each step.

What am I doing wrong ? how to get a single undo per step ?

ok I realize this has to do with newGroupDelay

So one way will be to change the history newGroupDelay to 0, then push the steps with a 1ms delay, then return newGroupDelay to the original value.

I got it to work like this:

				let editState=EditorState.create({
					schema, doc: doc, plugins: getState().plugins
				});
				let history=historyKey.get(editState);
				let orgNewGroupDelay=history.spec.config.newGroupDelay;
				history.spec.config.newGroupDelay=0;

				let addSteps = steps => {
					if (steps.length===0) {
					    let history=historyKey.get(editState);
						history.spec.config.newGroupDelay=orgNewGroupDelay;
						view.updateState(editState);
						return;
					}
					let tr=editState.tr.step(steps.shift());
					editState = editState.apply(tr);
					setTimeout(() => addSteps(steps), 1);
				};

				addSteps(steps);

Which works. This can be turned into a promise to look better but overall is very ugly.

Is there a better way ?

There’s a currently undocumented (and thus not part of the stable API) function closeHistory exported from the history module. You can do state.apply(closeHistory(state)) to force a new history event to start. I guess I should make this a proper command and document it.

This commit makes closeHistory part of the public API (with a slightly different signature from what it had in 0.18).

ok thanks ! that’s very useful…

Another thing worth thinking about is for the outside to know when a new undo event happens and it’s content (steps).

ATM in the collab demo for example, steps are written whenever they are available which will usually be too often. The client will want to throttle sends in some custom way, but another useful option can be to know when an undo step occurred and send it. This will keep the logic of dividing steps into ‘chunks’ in one place (history) and sync the history and collab better especially in the case were steps are loaded into the undo on startup (as I proposed in the other thread).

Any thoughts on this ?

Also I’m curious why closeHistory is a separate function and not a setMeta like “addToHistory” ? or the other way around ?

Because it uses a private symbol, rather than a plain string, for its meta property, mostly because I expected addToHistory to be used by widely different modules that may not directly depend on the history module, whereas closing the history is a specialized thing that you probably only do when you’re already directly interacting with the history module.