Remove last transaction from UndoManager history

I am dragging and dropping an item into a diagram. In certain cases I don’t want this action to be adde to the history of undoManager. The transaction that is added for this to the undoManager.history is ‘external copy’.
There are different kind of items that I am dragging and dropping, for certain cases I do not want this transaction to be added to the undoManager history.
I am identifying which kind of item was dragged and dropped by listening to the event ‘ExternalObjectsDropped.’ Setting skipsUndoManager did not work for me, I think because I recognize this transaction after it’s already done. Recognizing this by transaction name will also not work because I have different kinds of ‘external copy’ transactions.
I tried undomanager.history.pop() but got an exception.
I was wondering if there is a way to handle this.

Yes, it’s too late to set skipsUndoManager after the ChangedEvents have already happened.

[EDIT] You could try something like:

  new go.Diagram(. . .,
      "ExternalObjectsDropped": e => {
        if (e.subject.first(). . . ) {  // test the dropped Node(s)
          e.diagram.toolManager.draggingTool.transactionResult = null;
      . . .

diagram.currentTool.doCancel() did not work.
Also, I don’t want to cancel the dragging operation, I just don’t want it recorded in the history of the undoManager.

Sorry, I misunderstood you. Yes, undo/redo state is somewhat locked-down, to reduce the chances for problem states.

I’ll look for a solution for you, if one exists. The problem is that a transaction, such as one executing when an “ExternalObjectsDropped” DiagramEvent occurs, might result in a lot of ChangedEvents being recorded in the current Transaction, not just the addition of a node data object to the model and a Node to the Diagram. How can one know which ChangedEvents should be removed from the history and which ones should be kept?

I suppose it’s easier if you can decide that for your app you can remove the whole transaction from the undo history. This gets close to what you ask for:

      "ExternalObjectsDropped": e => {
        if (e.subject.first(). . .) {
          const curr = e.diagram.undoManager.currentTransaction;
          if (curr) curr.clear();

But it leaves an empty Transaction in the history list.

I want to remove the whole transaction of ‘external copy’ from the history.
I can’t override the undo function and ignore ‘external copy’ transactions because I have other ‘external copy’ transactions from dragging and dropping other items that I want to keep in the history.
From what I see in the documentation transaction.clear() will clear all saved changes. Does this means it will undo the changes or just removes them from the changes list of the transaction?

It does not undo those ChangedEvents.

I added diagram.undoManager.currentTransaction.clear(); inside the listener for “ExternalObjectsDropped”
and I added

diagram.addModelChangedListener((evt) => {
		if (evt.propertyName === 'CommittedTransaction')
			if(evt.oldValue === 'ExternalCopy' && evt.object.changes.toArray().length === 0) {

In order to remove the empty transaction. It seems to work well.

But that does an undo, which I thought you didn’t want to have happen. And after calling UndoManager.discardHistoryAfterIndex you won’t be able to redo that external drop.

After clearing all the changedEvents from the transactions it seems to me like the undo() doesn’t do anything. (It just does undo to an empty transaction.)
Is there a way I can remove a transaction from the history without loosing all the transactions of redo and without ending up with an empty transaction?

If I had devised such a solution I would have told you.

By the way, the ability to call Transaction.clear seems like a mis-implementation “feature” – one shouldn’t be able to modify transactions in that circumstance. But maybe we are being over-restrictive on the (in)ability for programmers to modify the undo history. It’s just that with these restrictions we basically never get any problems relating to undo/redo, a pleasant situation that is rarer than you might expect.

Maybe you could override UndoManager.undo and redo to skip over empty Transactions. (Sorry, I can’t try that for you at the moment.)

Another possibility: if what has just been drag-and-dropped you want to have happen but don’t want to record in the UndoManager, you could remember the dropped node data object and then cancel the drop (as shown in my post above). Then in a separate top-level transaction you could temporarily set skipsUndoManager to true and perform a transaction to add that node data object again.