Skip to content

Commit 0d64d53

Browse files
feat(ui): improved undo/redo history grouping
1 parent 1bae158 commit 0d64d53

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts

+29-2
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,23 @@ const isHighFrequencyFormChangeAction = isAnyOf(
816816
formElementContainerDataChanged
817817
);
818818

819+
// Match workflow changes that are high frequency and should be grouped together - for example, when a user is
820+
// updating the workflow description, we don't want to create a new undo group for every keystroke.
821+
const isHighFrequencyWorkflowDetailsAction = isAnyOf(
822+
workflowNameChanged,
823+
workflowDescriptionChanged,
824+
workflowTagsChanged,
825+
workflowAuthorChanged,
826+
workflowNotesChanged,
827+
workflowVersionChanged,
828+
workflowContactChanged
829+
);
830+
831+
// Match node-scoped actions that are high frequency and should be grouped together - for example, when a user is
832+
// updating the node label, we don't want to create a new undo group for every keystroke. Or when a user is writing
833+
// a note in a notes node, we don't want to create a new undo group for every keystroke.
834+
const isHighFrequencyNodeScopedAction = isAnyOf(nodeLabelChanged, nodeNotesChanged, notesNodeValueChanged);
835+
819836
export const nodesUndoableConfig: UndoableOptions<NodesState, UnknownAction> = {
820837
limit: 64,
821838
undoType: nodesSlice.actions.undo.type,
@@ -826,21 +843,31 @@ export const nodesUndoableConfig: UndoableOptions<NodesState, UnknownAction> = {
826843
return history.group;
827844
}
828845
if (isHighFrequencyFieldChangeAction(action)) {
829-
// Group high frequency field changes together when they are of the same type and for the same field
846+
// Group by type, node id and field name
830847
const { type, payload } = action;
831848
const { nodeId, fieldName } = payload;
832849
return `${type}-${nodeId}-${fieldName}`;
833850
}
834851
if (isDimensionsOrPositionAction(action)) {
835852
const ids = action.payload.map((change) => change.id).join(',');
853+
// Group by type and node ids
836854
return `dimensions-or-position-${ids}`;
837855
}
838856
if (isHighFrequencyFormChangeAction(action)) {
839-
// Group high frequency form changes together when they are of the same type and for the same element
857+
// Group by type and form element id
840858
const { type, payload } = action;
841859
const { id } = payload;
842860
return `${type}-${id}`;
843861
}
862+
if (isHighFrequencyWorkflowDetailsAction(action)) {
863+
return 'workflow-details';
864+
}
865+
if (isHighFrequencyNodeScopedAction(action)) {
866+
const { type, payload } = action;
867+
const { nodeId } = payload;
868+
// Group by type and node id
869+
return `${type}-${nodeId}`;
870+
}
844871
return null;
845872
},
846873
filter: (action, _state, _history) => {

0 commit comments

Comments
 (0)