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
a5c5c97d
"library/src/host_tensor/device.cpp" did not exist on "6fe3627a9eb35f1237266f1b6cc8fd3456aed67d"
Commit
a5c5c97d
authored
Mar 03, 2023
by
pythongosssss
Browse files
More work on UI
parent
5e66b68d
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
315 additions
and
275 deletions
+315
-275
server.py
server.py
+6
-1
web/index.html
web/index.html
+0
-175
web/scripts/api.js
web/scripts/api.js
+62
-4
web/scripts/app.js
web/scripts/app.js
+38
-8
web/scripts/extensions.js
web/scripts/extensions.js
+9
-0
web/scripts/ui.js
web/scripts/ui.js
+157
-81
web/style.css
web/style.css
+43
-6
No files found.
server.py
View file @
a5c5c97d
...
@@ -144,7 +144,12 @@ class PromptServer():
...
@@ -144,7 +144,12 @@ class PromptServer():
self
.
prompt_queue
.
delete_queue_item
(
delete_func
)
self
.
prompt_queue
.
delete_queue_item
(
delete_func
)
return
web
.
Response
(
status
=
200
)
return
web
.
Response
(
status
=
200
)
@
routes
.
post
(
"/interrupt"
)
async
def
post_interrupt
(
request
):
nodes
.
interrupt_processing
()
return
web
.
Response
(
status
=
200
)
@
routes
.
post
(
"/history"
)
@
routes
.
post
(
"/history"
)
async
def
post_history
(
request
):
async
def
post_history
(
request
):
json_data
=
await
request
.
json
()
json_data
=
await
request
.
json
()
...
...
web/index.html
View file @
a5c5c97d
...
@@ -20,30 +20,6 @@
...
@@ -20,30 +20,6 @@
let
progress
=
null
;
let
progress
=
null
;
let
clientId
=
null
;
let
clientId
=
null
;
function
clearGraph
()
{
graph
.
clear
();
}
function
loadTxt2Img
()
{
loadGraphData
(
graph
,
default_graph
);
}
function
saveGraph
()
{
var
json
=
JSON
.
stringify
(
graph
.
serialize
());
// convert the data to a JSON string
var
blob
=
new
Blob
([
json
],
{
type
:
"
application/json
"
});
var
url
=
URL
.
createObjectURL
(
blob
);
var
a
=
document
.
createElement
(
"
a
"
);
a
.
style
=
"
display: none
"
;
a
.
href
=
url
;
a
.
download
=
"
workflow.json
"
;
document
.
body
.
appendChild
(
a
);
a
.
click
();
setTimeout
(
function
()
{
document
.
body
.
removeChild
(
a
);
window
.
URL
.
revokeObjectURL
(
url
);
},
0
);
}
var
input
=
document
.
createElement
(
"
input
"
);
var
input
=
document
.
createElement
(
"
input
"
);
input
.
setAttribute
(
"
type
"
,
"
file
"
);
input
.
setAttribute
(
"
type
"
,
"
file
"
);
input
.
setAttribute
(
"
accept
"
,
"
.json,image/png
"
);
input
.
setAttribute
(
"
accept
"
,
"
.json,image/png
"
);
...
@@ -58,157 +34,6 @@
...
@@ -58,157 +34,6 @@
function
loadGraph
()
{
function
loadGraph
()
{
input
.
click
();
input
.
click
();
}
}
document
.
addEventListener
(
"
paste
"
,
(
e
)
=>
{
let
data
=
(
e
.
clipboardData
||
window
.
clipboardData
).
getData
(
"
text/plain
"
);
console
.
log
(
data
);
try
{
data
=
data
.
slice
(
data
.
indexOf
(
"
{
"
));
j
=
JSON
.
parse
(
data
);
}
catch
(
err
)
{
data
=
data
.
slice
(
data
.
indexOf
(
"
workflow
\n
"
));
data
=
data
.
slice
(
data
.
indexOf
(
"
{
"
));
j
=
JSON
.
parse
(
data
);
}
if
(
Object
.
hasOwn
(
j
,
"
version
"
)
&&
Object
.
hasOwn
(
j
,
"
nodes
"
)
&&
Object
.
hasOwn
(
j
,
"
extra
"
))
{
loadGraphData
(
graph
,
j
);
}
});
function
deleteQueueElement
(
type
,
delete_id
,
then
)
{
fetch
(
"
/
"
+
type
,
{
method
:
"
POST
"
,
headers
:
{
"
Content-Type
"
:
"
application/json
"
,
},
body
:
JSON
.
stringify
({
delete
:
[
delete_id
]
}),
})
.
then
((
data
)
=>
{
console
.
log
(
data
);
then
();
})
.
catch
((
error
)
=>
console
.
error
(
error
));
}
function
loadQueue
()
{
loadItems
(
"
queue
"
);
}
function
loadHistory
()
{
loadItems
(
"
history
"
);
}
function
loadItems
(
type
)
{
fetch
(
"
/
"
+
type
)
.
then
((
response
)
=>
response
.
json
())
.
then
((
data
)
=>
{
var
queue_div
=
document
.
getElementById
(
type
+
"
button-content
"
);
queue_div
.
style
.
display
=
"
block
"
;
var
see_queue_button
=
document
.
getElementById
(
"
see
"
+
type
+
"
button
"
);
let
old_w
=
see_queue_button
.
style
.
width
;
see_queue_button
.
innerHTML
=
"
Close
"
;
let
runningcontents
;
if
(
type
===
"
queue
"
)
{
runningcontents
=
document
.
getElementById
(
"
runningcontents
"
);
runningcontents
.
innerHTML
=
""
;
}
let
queuecontents
=
document
.
getElementById
(
type
+
"
contents
"
);
queuecontents
.
innerHTML
=
""
;
function
append_to_list
(
list_element
,
append_to_element
,
append_delete
,
state
)
{
let
number
=
list_element
[
0
];
let
id
=
list_element
[
1
];
let
prompt
=
list_element
[
2
];
let
workflow
=
list_element
[
3
].
extra_pnginfo
.
workflow
;
let
a
=
document
.
createElement
(
"
a
"
);
a
.
innerHTML
=
number
+
"
:
"
;
append_to_element
.
appendChild
(
a
);
let
button
=
document
.
createElement
(
"
button
"
);
button
.
innerHTML
=
"
Load
"
;
button
.
style
.
fontSize
=
"
10px
"
;
button
.
workflow
=
workflow
;
button
.
onclick
=
function
(
event
)
{
loadGraphData
(
graph
,
event
.
target
.
workflow
);
if
(
state
)
{
nodeOutputs
=
state
;
}
};
append_to_element
.
appendChild
(
button
);
if
(
append_delete
)
{
let
button
=
document
.
createElement
(
"
button
"
);
button
.
innerHTML
=
"
Delete
"
;
button
.
style
.
fontSize
=
"
10px
"
;
button
.
delete_id
=
id
;
button
.
onclick
=
function
(
event
)
{
deleteQueueElement
(
type
,
event
.
target
.
delete_id
,
()
=>
loadItems
(
type
));
};
append_to_element
.
appendChild
(
button
);
}
append_to_element
.
appendChild
(
document
.
createElement
(
"
br
"
));
}
if
(
runningcontents
)
{
for
(
let
x
in
data
.
queue_running
)
{
append_to_list
(
data
.
queue_running
[
x
],
runningcontents
,
false
);
}
}
let
items
;
if
(
type
===
"
queue
"
)
{
items
=
data
.
queue_pending
;
}
else
{
items
=
Object
.
values
(
data
);
}
items
.
sort
((
a
,
b
)
=>
a
[
0
]
-
b
[
0
]);
for
(
let
i
of
items
)
{
append_to_list
(
type
===
"
queue
"
?
i
:
i
.
prompt
,
queuecontents
,
true
,
i
.
outputs
);
}
})
.
catch
((
response
)
=>
{
console
.
log
(
response
);
});
}
function
seeItems
(
type
)
{
var
queue_div
=
document
.
getElementById
(
type
+
"
button-content
"
);
if
(
queue_div
.
style
.
display
==
"
block
"
)
{
closeItems
(
type
);
}
else
{
loadItems
(
type
);
}
}
function
seeQueue
()
{
closeItems
(
"
history
"
);
seeItems
(
"
queue
"
);
}
function
seeHistory
()
{
closeItems
(
"
queue
"
);
seeItems
(
"
history
"
);
}
function
closeItems
(
type
)
{
var
queue_div
=
document
.
getElementById
(
type
+
"
button-content
"
);
queue_div
.
style
.
display
=
"
none
"
;
var
see_queue_button
=
document
.
getElementById
(
"
see
"
+
type
+
"
button
"
);
see_queue_button
.
innerHTML
=
"
See
"
+
type
[
0
].
toUpperCase
()
+
type
.
substr
(
1
);
}
function
clearItems
(
type
)
{
fetch
(
"
/
"
+
type
,
{
method
:
"
POST
"
,
headers
:
{
"
Content-Type
"
:
"
application/json
"
,
},
body
:
JSON
.
stringify
({
clear
:
true
}),
})
.
then
((
data
)
=>
{
loadItems
(
type
);
})
.
catch
((
error
)
=>
console
.
error
(
error
));
}
</script>
</script>
</body>
</body>
</html>
</html>
web/scripts/api.js
View file @
a5c5c97d
class
ComfyApi
extends
EventTarget
{
class
ComfyApi
extends
EventTarget
{
constructor
()
{
constructor
()
{
super
();
super
();
}
}
#
pollQueue
()
{
#
pollQueue
()
{
...
@@ -74,9 +74,9 @@ class ComfyApi extends EventTarget {
...
@@ -74,9 +74,9 @@ class ComfyApi extends EventTarget {
});
});
}
}
init
()
{
init
()
{
this
.
#
createSocket
();
this
.
#
createSocket
();
}
}
async
getNodeDefs
()
{
async
getNodeDefs
()
{
const
resp
=
await
fetch
(
"
object_info
"
,
{
cache
:
"
no-store
"
});
const
resp
=
await
fetch
(
"
object_info
"
,
{
cache
:
"
no-store
"
});
...
@@ -110,6 +110,64 @@ class ComfyApi extends EventTarget {
...
@@ -110,6 +110,64 @@ class ComfyApi extends EventTarget {
};
};
}
}
}
}
async
getItems
(
type
)
{
if
(
type
===
"
queue
"
)
{
return
this
.
getQueue
();
}
return
this
.
getHistory
();
}
async
getQueue
()
{
try
{
const
res
=
await
fetch
(
"
/queue
"
);
const
data
=
await
res
.
json
();
return
{
// Running action uses a different endpoint for cancelling
Running
:
data
.
queue_running
.
map
((
prompt
)
=>
({
prompt
,
remove
:
{
name
:
"
Cancel
"
,
cb
:
()
=>
api
.
interrupt
()
}
})),
Pending
:
data
.
queue_pending
.
map
((
prompt
)
=>
({
prompt
})),
};
}
catch
(
error
)
{
console
.
error
(
error
);
return
{
Running
:
[],
Pending
:
[]
};
}
}
async
getHistory
()
{
try
{
const
res
=
await
fetch
(
"
/history
"
);
return
{
History
:
Object
.
values
(
await
res
.
json
())
};
}
catch
(
error
)
{
console
.
error
(
error
);
return
{
History
:
[]
};
}
}
async
#
postItem
(
type
,
body
)
{
try
{
await
fetch
(
"
/
"
+
type
,
{
method
:
"
POST
"
,
headers
:
{
"
Content-Type
"
:
"
application/json
"
,
},
body
:
body
?
JSON
.
stringify
(
body
)
:
undefined
,
});
}
catch
(
error
)
{
console
.
error
(
error
);
}
}
async
deleteItem
(
type
,
id
)
{
await
this
.
#
postItem
(
type
,
{
delete
:
[
id
]
});
}
async
clearItems
(
type
)
{
await
this
.
#
postItem
(
type
,
{
clear
:
true
});
}
async
interrupt
()
{
await
this
.
#
postItem
(
"
interrupt
"
,
null
);
}
}
}
export
const
api
=
new
ComfyApi
();
export
const
api
=
new
ComfyApi
();
web/scripts/app.js
View file @
a5c5c97d
...
@@ -313,8 +313,27 @@ class ComfyApp {
...
@@ -313,8 +313,27 @@ class ComfyApp {
};
};
reader
.
readAsText
(
file
);
reader
.
readAsText
(
file
);
}
}
});
}
#
addPasteHandler
()
{
document
.
addEventListener
(
"
paste
"
,
(
e
)
=>
{
let
data
=
(
e
.
clipboardData
||
window
.
clipboardData
).
getData
(
"
text/plain
"
);
let
workflow
;
try
{
data
=
data
.
slice
(
data
.
indexOf
(
"
{
"
));
workflow
=
JSON
.
parse
(
data
);
}
catch
(
err
)
{
try
{
data
=
data
.
slice
(
data
.
indexOf
(
"
workflow
\n
"
));
data
=
data
.
slice
(
data
.
indexOf
(
"
{
"
));
workflow
=
JSON
.
parse
(
data
);
}
catch
(
error
)
{}
}
prompt_file_load
(
file
);
if
(
workflow
&&
workflow
.
version
&&
workflow
.
nodes
&&
workflow
.
extra
)
{
this
.
loadGraphData
(
workflow
);
}
});
});
}
}
...
@@ -367,13 +386,17 @@ class ComfyApp {
...
@@ -367,13 +386,17 @@ class ComfyApp {
}
}
#
addApiUpdateHandlers
()
{
#
addApiUpdateHandlers
()
{
api
.
addEventListener
(
"
status
"
,
(
status
)
=>
{
api
.
addEventListener
(
"
status
"
,
(
{
detail
}
)
=>
{
console
.
log
(
status
);
this
.
ui
.
setStatus
(
detail
);
});
});
api
.
addEventListener
(
"
reconnecting
"
,
()
=>
{});
api
.
addEventListener
(
"
reconnecting
"
,
()
=>
{
this
.
ui
.
dialog
.
show
(
"
Reconnecting...
"
);
});
api
.
addEventListener
(
"
reconnected
"
,
()
=>
{});
api
.
addEventListener
(
"
reconnected
"
,
()
=>
{
this
.
ui
.
dialog
.
close
();
});
api
.
addEventListener
(
"
progress
"
,
({
detail
})
=>
{
api
.
addEventListener
(
"
progress
"
,
({
detail
})
=>
{
this
.
progress
=
detail
;
this
.
progress
=
detail
;
...
@@ -386,7 +409,9 @@ class ComfyApp {
...
@@ -386,7 +409,9 @@ class ComfyApp {
this
.
graph
.
setDirtyCanvas
(
true
,
false
);
this
.
graph
.
setDirtyCanvas
(
true
,
false
);
});
});
api
.
addEventListener
(
"
executed
"
,
(
e
)
=>
{});
api
.
addEventListener
(
"
executed
"
,
({
detail
})
=>
{
this
.
nodeOutputs
[
detail
.
node
]
=
detail
.
output
;
});
api
.
init
();
api
.
init
();
}
}
...
@@ -431,7 +456,7 @@ class ComfyApp {
...
@@ -431,7 +456,7 @@ class ComfyApp {
// We failed to restore a workflow so load the default
// We failed to restore a workflow so load the default
if
(
!
restored
)
{
if
(
!
restored
)
{
this
.
loadGraphData
(
defaultGraph
);
this
.
loadGraphData
();
}
}
// Save current workflow automatically
// Save current workflow automatically
...
@@ -440,6 +465,8 @@ class ComfyApp {
...
@@ -440,6 +465,8 @@ class ComfyApp {
this
.
#
addDrawNodeProgressHandler
();
this
.
#
addDrawNodeProgressHandler
();
this
.
#
addApiUpdateHandlers
();
this
.
#
addApiUpdateHandlers
();
this
.
#
addDropHandler
();
this
.
#
addDropHandler
();
this
.
#
addPasteHandler
();
await
this
.
#
invokeExtensionsAsync
(
"
setup
"
);
await
this
.
#
invokeExtensionsAsync
(
"
setup
"
);
}
}
...
@@ -511,6 +538,9 @@ class ComfyApp {
...
@@ -511,6 +538,9 @@ class ComfyApp {
* @param {*} graphData A serialized graph object
* @param {*} graphData A serialized graph object
*/
*/
loadGraphData
(
graphData
)
{
loadGraphData
(
graphData
)
{
if
(
!
graphData
)
{
graphData
=
defaultGraph
;
}
this
.
graph
.
configure
(
graphData
);
this
.
graph
.
configure
(
graphData
);
for
(
const
node
of
this
.
graph
.
_nodes
)
{
for
(
const
node
of
this
.
graph
.
_nodes
)
{
...
@@ -526,7 +556,7 @@ class ComfyApp {
...
@@ -526,7 +556,7 @@ class ComfyApp {
if
(
node
.
type
==
"
KSampler
"
||
node
.
type
==
"
KSamplerAdvanced
"
)
{
if
(
node
.
type
==
"
KSampler
"
||
node
.
type
==
"
KSamplerAdvanced
"
)
{
if
(
widget
.
name
==
"
sampler_name
"
)
{
if
(
widget
.
name
==
"
sampler_name
"
)
{
if
(
widget
.
value
.
startsWith
(
"
sample_
"
))
{
if
(
widget
.
value
.
startsWith
(
"
sample_
"
))
{
wid
.
value
=
widget
.
value
.
slice
(
7
);
wid
get
.
value
=
widget
.
value
.
slice
(
7
);
}
}
}
}
}
}
...
...
web/scripts/extensions.js
0 → 100644
View file @
a5c5c97d
export
class
ComfyExtension
{
init
(
app
)
{}
setup
(
app
)
{}
loadedGraphNode
(
node
,
app
)
{}
addCustomNodeDefs
(
defs
,
app
)
{}
getCustomWidgets
(
app
)
{}
beforeRegisterNode
(
nodeType
,
nodeData
,
app
)
{}
registerCustomNodes
(
app
)
{}
}
\ No newline at end of file
web/scripts/ui.js
View file @
a5c5c97d
import
{
api
}
from
"
./api.js
"
;
import
{
api
}
from
"
./api.js
"
;
function
$el
(
tag
,
propsOrChildren
,
children
)
{
const
split
=
tag
.
split
(
"
.
"
);
const
element
=
document
.
createElement
(
split
.
shift
());
element
.
classList
.
add
(...
split
);
if
(
propsOrChildren
)
{
if
(
Array
.
isArray
(
propsOrChildren
))
{
element
.
append
(...
propsOrChildren
);
}
else
{
const
parent
=
propsOrChildren
.
parent
;
delete
propsOrChildren
.
parent
;
const
cb
=
propsOrChildren
.
$
;
delete
propsOrChildren
.
$
;
Object
.
assign
(
element
,
propsOrChildren
);
if
(
children
)
{
element
.
append
(...
children
);
}
if
(
parent
)
{
parent
.
append
(
element
);
}
if
(
cb
)
{
cb
(
element
);
}
}
}
return
element
;
}
class
ComfyDialog
{
class
ComfyDialog
{
constructor
()
{
constructor
()
{
this
.
element
=
document
.
createElement
(
"
div
"
);
this
.
element
=
$el
(
"
div.comfy-modal
"
,
{
parent
:
document
.
body
},
[
this
.
element
.
classList
.
add
(
"
comfy-modal
"
);
$el
(
"
div.comfy-modal-content
"
,
[
$el
(
"
p
"
,
{
$
:
(
p
)
=>
(
this
.
textElement
=
p
)
}),
const
content
=
document
.
createElement
(
"
div
"
);
$el
(
"
button
"
,
{
content
.
classList
.
add
(
"
comfy-modal-content
"
);
type
:
"
button
"
,
this
.
textElement
=
document
.
createElement
(
"
p
"
);
textContent
:
"
CLOSE
"
,
content
.
append
(
this
.
textElement
);
onclick
:
()
=>
this
.
close
(),
}),
const
closeBtn
=
document
.
createElement
(
"
button
"
);
]),
closeBtn
.
type
=
"
button
"
;
]);
closeBtn
.
textContent
=
"
CLOSE
"
;
content
.
append
(
closeBtn
);
closeBtn
.
onclick
=
()
=>
this
.
close
();
this
.
element
.
append
(
content
);
document
.
body
.
append
(
this
.
element
);
}
}
close
()
{
close
()
{
...
@@ -31,10 +55,14 @@ class ComfyDialog {
...
@@ -31,10 +55,14 @@ class ComfyDialog {
}
}
class
ComfyList
{
class
ComfyList
{
constructor
()
{
#
type
;
this
.
element
=
document
.
createElement
(
"
div
"
);
#
text
;
constructor
(
text
,
type
)
{
this
.
#
text
=
text
;
this
.
#
type
=
type
||
text
.
toLowerCase
();
this
.
element
=
$el
(
"
div.comfy-list
"
);
this
.
element
.
style
.
display
=
"
none
"
;
this
.
element
.
style
.
display
=
"
none
"
;
this
.
element
.
textContent
=
"
hello
"
;
}
}
get
visible
()
{
get
visible
()
{
...
@@ -42,7 +70,51 @@ class ComfyList {
...
@@ -42,7 +70,51 @@ class ComfyList {
}
}
async
load
()
{
async
load
()
{
// const queue = await api.getQueue();
const
items
=
await
api
.
getItems
(
this
.
#
type
);
this
.
element
.
replaceChildren
(
...
Object
.
keys
(
items
).
flatMap
((
section
)
=>
[
$el
(
"
h4
"
,
{
textContent
:
section
,
}),
$el
(
"
div.comfy-list-items
"
,
[
...
items
[
section
].
map
((
item
)
=>
{
// Allow items to specify a custom remove action (e.g. for interrupt current prompt)
const
removeAction
=
item
.
remove
||
{
name
:
"
Delete
"
,
cb
:
()
=>
api
.
deleteItem
(
this
.
#
type
,
item
.
prompt
[
1
]),
};
return
$el
(
"
div
"
,
{
textContent
:
item
.
prompt
[
0
]
+
"
:
"
},
[
$el
(
"
button
"
,
{
textContent
:
"
Load
"
,
onclick
:
()
=>
{
if
(
item
.
outputs
)
{
app
.
nodeOutputs
=
item
.
outputs
;
}
app
.
loadGraphData
(
item
.
prompt
[
3
].
extra_pnginfo
.
workflow
);
},
}),
$el
(
"
button
"
,
{
textContent
:
removeAction
.
name
,
onclick
:
async
()
=>
{
await
removeAction
.
cb
();
await
this
.
update
();
},
}),
]);
}),
]),
]),
$el
(
"
div.comfy-list-actions
"
,
[
$el
(
"
button
"
,
{
textContent
:
"
Clear
"
+
this
.
#
text
,
onclick
:
async
()
=>
{
await
api
.
clearItems
(
this
.
#
type
);
await
this
.
load
();
},
}),
$el
(
"
button
"
,
{
textContent
:
"
Refresh
"
,
onclick
:
()
=>
this
.
load
()
}),
])
);
}
}
async
update
()
{
async
update
()
{
...
@@ -53,11 +125,14 @@ class ComfyList {
...
@@ -53,11 +125,14 @@ class ComfyList {
async
show
()
{
async
show
()
{
this
.
element
.
style
.
display
=
"
block
"
;
this
.
element
.
style
.
display
=
"
block
"
;
this
.
button
.
textContent
=
"
Close
"
;
await
this
.
load
();
await
this
.
load
();
}
}
hide
()
{
hide
()
{
this
.
element
.
style
.
display
=
"
none
"
;
this
.
element
.
style
.
display
=
"
none
"
;
this
.
button
.
textContent
=
"
See
"
+
this
.
#
text
;
}
}
toggle
()
{
toggle
()
{
...
@@ -75,77 +150,78 @@ export class ComfyUI {
...
@@ -75,77 +150,78 @@ export class ComfyUI {
constructor
(
app
)
{
constructor
(
app
)
{
this
.
app
=
app
;
this
.
app
=
app
;
this
.
dialog
=
new
ComfyDialog
();
this
.
dialog
=
new
ComfyDialog
();
this
.
queue
=
new
ComfyList
();
this
.
history
=
new
ComfyList
();
this
.
menuContainer
=
document
.
createElement
(
"
div
"
);
this
.
menuContainer
.
classList
.
add
(
"
comfy-menu
"
);
this
.
queueSize
=
document
.
createElement
(
"
span
"
);
this
.
menuContainer
.
append
(
this
.
queueSize
);
this
.
addAction
(
"
Queue Prompt
"
,
()
=>
{
app
.
queuePrompt
(
0
);
},
"
queue
"
);
this
.
btnContainer
=
document
.
createElement
(
"
div
"
);
this
.
queue
=
new
ComfyList
(
"
Queue
"
);
this
.
btnContainer
.
classList
.
add
(
"
comfy-menu-btns
"
);
this
.
history
=
new
ComfyList
(
"
History
"
);
this
.
menuContainer
.
append
(
this
.
btnContainer
);
this
.
addAction
(
api
.
addEventListener
(
"
status
"
,
()
=>
{
"
Queue Front
"
,
this
.
queue
.
update
();
()
=>
{
this
.
history
.
update
();
app
.
queuePrompt
(
-
1
);
});
},
"
sm
"
);
this
.
addAction
(
var
input
=
document
.
createElement
(
"
input
"
);
"
See Queue
"
,
input
.
setAttribute
(
"
type
"
,
"
file
"
);
(
btn
)
=>
{
input
.
setAttribute
(
"
accept
"
,
"
.json,image/png
"
);
btn
.
textContent
=
this
.
queue
.
toggle
()
?
"
Close
"
:
"
See Queue
"
;
input
.
style
.
display
=
"
none
"
;
},
document
.
body
.
appendChild
(
input
);
"
sm
"
);
this
.
addAction
(
input
.
addEventListener
(
"
change
"
,
function
()
{
"
See History
"
,
var
file
=
input
.
files
[
0
];
(
btn
)
=>
{
prompt_file_load
(
file
);
btn
.
textContent
=
this
.
history
.
toggle
()
?
"
Close
"
:
"
See History
"
;
});
},
"
sm
"
);
this
.
menuContainer
.
append
(
this
.
queue
.
element
);
this
.
menuContainer
.
append
(
this
.
history
.
element
);
this
.
addAction
(
"
Save
"
,
()
=>
{
this
.
menuContainer
=
$el
(
"
div.comfy-menu
"
,
{
parent
:
document
.
body
},
[
app
.
queuePrompt
(
-
1
);
$el
(
"
span
"
,
{
$
:
(
q
)
=>
(
this
.
queueSize
=
q
)
}),
});
$el
(
"
button.comfy-queue-btn
"
,
{
textContent
:
"
Queue Prompt
"
,
onclick
:
()
=>
app
.
queuePrompt
(
0
)
}),
this
.
addAction
(
"
Load
"
,
()
=>
{
$el
(
"
div.comfy-menu-btns
"
,
[
app
.
queuePrompt
(
-
1
);
$el
(
"
button
"
,
{
textContent
:
"
Queue Front
"
,
onclick
:
()
=>
app
.
queuePrompt
(
-
1
)
}),
});
$el
(
"
button
"
,
{
this
.
addAction
(
"
Clear
"
,
()
=>
{
$
:
(
b
)
=>
(
this
.
queue
.
button
=
b
),
app
.
queuePrompt
(
-
1
);
textContent
:
"
View Queue
"
,
});
onclick
:
()
=>
{
this
.
addAction
(
"
Load Default
"
,
()
=>
{
this
.
history
.
hide
();
app
.
queuePrompt
(
-
1
);
this
.
queue
.
toggle
();
});
},
}),
$el
(
"
button
"
,
{
$
:
(
b
)
=>
(
this
.
history
.
button
=
b
),
textContent
:
"
View History
"
,
onclick
:
()
=>
{
this
.
queue
.
hide
();
this
.
history
.
toggle
();
},
}),
]),
this
.
queue
.
element
,
this
.
history
.
element
,
$el
(
"
button
"
,
{
textContent
:
"
Save
"
,
onclick
:
()
=>
{
const
json
=
JSON
.
stringify
(
app
.
graph
.
serialize
());
// convert the data to a JSON string
const
blob
=
new
Blob
([
json
],
{
type
:
"
application/json
"
});
const
url
=
URL
.
createObjectURL
(
blob
);
const
a
=
$el
(
"
a
"
,
{
href
:
url
,
download
:
"
workflow.json
"
,
style
:
"
display: none
"
,
parent
:
document
.
body
,
});
a
.
click
();
setTimeout
(
function
()
{
a
.
remove
();
window
.
URL
.
revokeObjectURL
(
url
);
},
0
);
},
}),
$el
(
"
button
"
,
{
textContent
:
"
Load
"
,
onclick
:
()
=>
{}
}),
$el
(
"
button
"
,
{
textContent
:
"
Clear
"
,
onclick
:
()
=>
app
.
graph
.
clear
()
}),
$el
(
"
button
"
,
{
textContent
:
"
Load Default
"
,
onclick
:
()
=>
app
.
loadGraphData
()
}),
]);
document
.
body
.
append
(
this
.
menuContainer
);
this
.
setStatus
({
exec_info
:
{
queue_remaining
:
"
X
"
}
});
this
.
setStatus
({
exec_info
:
{
queue_remaining
:
"
X
"
}
});
}
}
addAction
(
text
,
cb
,
cls
)
{
const
btn
=
document
.
createElement
(
"
button
"
);
btn
.
classList
.
add
(
"
comfy-menu-btn-
"
+
(
cls
||
"
lg
"
));
btn
.
textContent
=
text
;
btn
.
onclick
=
()
=>
{
cb
(
btn
);
};
(
cls
===
"
sm
"
?
this
.
btnContainer
:
this
.
menuContainer
).
append
(
btn
);
}
setStatus
(
status
)
{
setStatus
(
status
)
{
this
.
queueSize
.
textContent
=
"
Queue size:
"
+
(
status
?
status
.
exec_info
.
queue_remaining
:
"
ERR
"
);
this
.
queueSize
.
textContent
=
"
Queue size:
"
+
(
status
?
status
.
exec_info
.
queue_remaining
:
"
ERR
"
);
}
}
...
...
web/style.css
View file @
a5c5c97d
...
@@ -34,6 +34,8 @@ body {
...
@@ -34,6 +34,8 @@ body {
max-height
:
80vh
;
max-height
:
80vh
;
transform
:
translate
(
-50%
,
-50%
);
transform
:
translate
(
-50%
,
-50%
);
overflow
:
hidden
;
overflow
:
hidden
;
min-width
:
60%
;
justify-content
:
center
;
}
}
.comfy-modal-content
{
.comfy-modal-content
{
...
@@ -79,21 +81,56 @@ body {
...
@@ -79,21 +81,56 @@ body {
align-items
:
center
;
align-items
:
center
;
}
}
.comfy-menu
button
{
font-size
:
20px
;
}
.comfy-menu-btns
{
.comfy-menu-btns
{
margin-bottom
:
10px
;
margin-bottom
:
10px
;
width
:
100%
;
}
}
.comfy-menu-btn
-sm
{
.comfy-menu-btn
s
button
{
font-size
:
10px
;
font-size
:
10px
;
width
:
50%
;
width
:
50%
;
}
}
.comfy-
menu-btn-lg
,
.comfy-menu-btn-
queue
{
.comfy-queue
-btn
{
font-size
:
20px
;
width
:
100%
;
}
}
.comfy-menu-btn-queue
{
.comfy-list
{
width
:
100%
;
background-color
:
rgb
(
225
,
225
,
225
);
margin-bottom
:
10px
;
}
.comfy-list-items
{
overflow-y
:
scroll
;
max-height
:
100px
;
background-color
:
#d0d0d0
;
padding
:
5px
;
}
.comfy-list
h4
{
min-width
:
160px
;
margin
:
0
;
padding
:
3px
;
font-weight
:
normal
;
}
.comfy-list-items
button
{
font-size
:
10px
;
}
.comfy-list-actions
{
margin
:
5px
;
display
:
flex
;
gap
:
5px
;
justify-content
:
center
;
}
.comfy-list-actions
button
{
font-size
:
12px
;
}
}
@media
(
prefers-color-scheme
:
dark
)
{
@media
(
prefers-color-scheme
:
dark
)
{
...
@@ -107,7 +144,7 @@ body {
...
@@ -107,7 +144,7 @@ body {
}
}
@media
only
screen
and
(
max-height
:
850px
)
{
@media
only
screen
and
(
max-height
:
850px
)
{
#
menu
{
.comfy-
menu
{
margin-top
:
-70px
;
margin-top
:
-70px
;
}
}
}
}
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