Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
ComfyUI
Commits
34eccd86
Commit
34eccd86
authored
Nov 27, 2023
by
pythongosssss
Browse files
Add simple undo redo history
parent
39e75862
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
150 additions
and
0 deletions
+150
-0
web/extensions/core/undoRedo.js
web/extensions/core/undoRedo.js
+150
-0
No files found.
web/extensions/core/undoRedo.js
0 → 100644
View file @
34eccd86
import
{
app
}
from
"
../../scripts/app.js
"
;
const
MAX_HISTORY
=
50
;
let
undo
=
[];
let
redo
=
[];
let
activeState
=
null
;
let
isOurLoad
=
false
;
function
checkState
()
{
const
currentState
=
app
.
graph
.
serialize
();
if
(
!
graphEqual
(
activeState
,
currentState
))
{
undo
.
push
(
activeState
);
if
(
undo
.
length
>
MAX_HISTORY
)
{
undo
.
shift
();
}
activeState
=
clone
(
currentState
);
redo
.
length
=
0
;
}
}
const
loadGraphData
=
app
.
loadGraphData
;
app
.
loadGraphData
=
async
function
()
{
const
v
=
await
loadGraphData
.
apply
(
this
,
arguments
);
if
(
isOurLoad
)
{
isOurLoad
=
false
;
}
else
{
checkState
();
}
return
v
;
};
function
clone
(
obj
)
{
try
{
if
(
typeof
structuredClone
!==
"
undefined
"
)
{
return
structuredClone
(
obj
);
}
}
catch
(
error
)
{
// structuredClone is stricter than using JSON.parse/stringify so fallback to that
}
return
JSON
.
parse
(
JSON
.
stringify
(
obj
));
}
function
graphEqual
(
a
,
b
,
root
=
true
)
{
if
(
a
===
b
)
return
true
;
if
(
typeof
a
==
"
object
"
&&
a
&&
typeof
b
==
"
object
"
&&
b
)
{
const
keys
=
Object
.
getOwnPropertyNames
(
a
);
if
(
keys
.
length
!=
Object
.
getOwnPropertyNames
(
b
).
length
)
{
return
false
;
}
for
(
const
key
of
keys
)
{
let
av
=
a
[
key
];
let
bv
=
b
[
key
];
if
(
root
&&
key
===
"
nodes
"
)
{
// Nodes need to be sorted as the order changes when selecting nodes
av
=
[...
av
].
sort
((
a
,
b
)
=>
a
.
id
-
b
.
id
);
bv
=
[...
bv
].
sort
((
a
,
b
)
=>
a
.
id
-
b
.
id
);
}
if
(
!
graphEqual
(
av
,
bv
,
false
))
{
return
false
;
}
}
return
true
;
}
return
false
;
}
const
undoRedo
=
async
(
e
)
=>
{
if
(
e
.
ctrlKey
||
e
.
metaKey
)
{
if
(
e
.
key
===
"
y
"
)
{
const
prevState
=
redo
.
pop
();
if
(
prevState
)
{
undo
.
push
(
activeState
);
isOurLoad
=
true
;
await
app
.
loadGraphData
(
prevState
);
activeState
=
prevState
;
}
return
true
;
}
else
if
(
e
.
key
===
"
z
"
)
{
const
prevState
=
undo
.
pop
();
if
(
prevState
)
{
redo
.
push
(
activeState
);
isOurLoad
=
true
;
await
app
.
loadGraphData
(
prevState
);
activeState
=
prevState
;
}
return
true
;
}
}
};
const
bindInput
=
(
activeEl
)
=>
{
if
(
activeEl
?.
tagName
!==
"
CANVAS
"
&&
activeEl
?.
tagName
!==
"
BODY
"
)
{
for
(
const
evt
of
[
"
change
"
,
"
input
"
,
"
blur
"
])
{
if
(
`on
${
evt
}
`
in
activeEl
)
{
const
listener
=
()
=>
{
checkState
();
activeEl
.
removeEventListener
(
evt
,
listener
);
};
activeEl
.
addEventListener
(
evt
,
listener
);
return
true
;
}
}
}
};
window
.
addEventListener
(
"
keydown
"
,
(
e
)
=>
{
requestAnimationFrame
(
async
()
=>
{
const
activeEl
=
document
.
activeElement
;
if
(
activeEl
?.
tagName
===
"
INPUT
"
||
activeEl
?.
type
===
"
textarea
"
)
{
// Ignore events on inputs, they have their native history
return
;
}
// Check if this is a ctrl+z ctrl+y
if
(
await
undoRedo
(
e
))
return
;
// If our active element is some type of input then handle changes after they're done
if
(
bindInput
(
activeEl
))
return
;
checkState
();
});
},
true
);
// Handle clicking DOM elements (e.g. widgets)
window
.
addEventListener
(
"
mouseup
"
,
()
=>
{
checkState
();
});
// Handle litegraph clicks
const
processMouseUp
=
LGraphCanvas
.
prototype
.
processMouseUp
;
LGraphCanvas
.
prototype
.
processMouseUp
=
function
(
e
)
{
const
v
=
processMouseUp
.
apply
(
this
,
arguments
);
checkState
();
return
v
;
};
const
processMouseDown
=
LGraphCanvas
.
prototype
.
processMouseDown
;
LGraphCanvas
.
prototype
.
processMouseDown
=
function
(
e
)
{
const
v
=
processMouseDown
.
apply
(
this
,
arguments
);
checkState
();
return
v
;
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment