added add button

This commit is contained in:
Christian Bastian
2024-01-03 10:09:54 -05:00
parent 3983873591
commit 4c06ec752a
3 changed files with 96 additions and 25 deletions

View File

@@ -17,6 +17,7 @@ Currently it is still missing some features it should have.
- Search `/`subdirectories of model directories based on your file structure (for example, `/styles/clothing`).
- Include models listed in ComfyUI's `extra_model_paths.yaml`.
- Button to copy a model to the ComfyUI clipboard. (Embedding cannot be copied to the system clipboard with an http connection.)
- Button to add model to ComfyUI graph. (For small screens/low resolution.)
- Right, left and bottom toggleable sidebar modes.
- Drag model to graph to add or existing node to set model.
- Drag embedding to textarea to append.
@@ -51,10 +52,11 @@ Currently it is still missing some features it should have.
- ☐ Exclude hidden folders with a `.` prefix.
- ☐ Include a optional string to always add to searches.
- ☐ Enable optional checksum to detect if a model is already downloaded.
- ☐ Change copy icon to an add icon `✚`.
- ☐ Enable/Disable add and copy buttons.
- ☐ Allow user to drag width of sidebar or height of bottom bar and remember it.
- ☐ Hide/Show model extension.
- ☐ Optionally remove embedding extension.
- ☐ Strict model drag on node widget textbox.
### Model info window/panel (server load/send on demand)
@@ -68,3 +70,7 @@ Currently it is still missing some features it should have.
- ☐ Show preview images for videos.
- ☐ If ffmpeg or cv2 available, extract the first frame of the video and use as image preview.
- ☐ Play preview video?
### Accessibility
- ☐ Proper naming and labeling.

View File

@@ -55,10 +55,8 @@
.comfy-grid .item {
position: relative;
aspect-ratio: 2/3;
max-width: 230px;
/*width: 230px;*/
/*height: 345px;*/
width: 230px;
height: 345px;
text-align: center;
overflow: hidden;
border-radius: 8px;
@@ -70,7 +68,7 @@
object-fit: cover;
}
.comfy-grid .item div {
.comfy-grid .model-label {
background-color: #000a;
width: 100%;
height: 2.2rem;
@@ -80,7 +78,7 @@
line-height: 2.2rem;
}
.comfy-grid .item div > p {
.comfy-grid .model-label > p {
width: calc(100% - 2rem);
overflow-x: scroll;
white-space: nowrap;
@@ -89,17 +87,18 @@
margin: 0;
}
.comfy-grid .item div {
.comfy-grid .model-label {
scrollbar-width: none;
-ms-overflow-style: none;
}
.comfy-grid .item div ::-webkit-scrollbar {
.comfy-grid .model-label ::-webkit-scrollbar {
width: 0;
height: 0;
}
.comfy-grid .item .model-preview-overlay {
position: absolute;
top: 0;
left: 0;
height: 100%;
@@ -107,23 +106,29 @@
background-color: rgba(0, 0, 0, 0);
}
.comfy-grid .copy-model-button {
.comfy-grid .model-preview-top-right {
position: absolute;
display: flex;
flex-direction: column;
gap: 8px;
top: 8px;
right: 8px;
}
.comfy-grid .model-button {
opacity: 0.65;
}
.comfy-grid .copy-model-button:hover {
.comfy-grid .model-button:hover {
opacity: 1;
}
button.icon-button.copy-model-button.copy-alert-success {
.comfy-grid .model-button.copy-alert-success {
color: green;
border-color: green;
}
button.icon-button.copy-model-button.copy-alert-fail {
.comfy-grid .model-button.copy-alert-fail {
color: darkred;
border-color: darkred;
}

View File

@@ -274,15 +274,61 @@ class ModelGrid {
}, true);
});
}
static #addModel(event, modelType, path) {
if (modelType !== "embeddings") {
const nodeType = modelNodeType(modelType);
const widgetIndex = modelWidgetIndex(nodeType);
let node = LiteGraph.createNode(nodeType, null, []);
if (node) {
node.widgets[widgetIndex].value = path;
const selectedNodes = app.canvas.selected_nodes;
let isSelectedNode = false;
for (var i in selectedNodes) {
const selectedNode = selectedNodes[i];
// TODO: settings.model_add_offset
node.pos[0] = selectedNode.pos[0] + 25;
node.pos[1] = selectedNode.pos[1] + 25;
isSelectedNode = true;
break;
}
if (!isSelectedNode) {
const graphMouse = app.canvas.graph_mouse;
node.pos[0] = graphMouse[0];
node.pos[1] = graphMouse[1];
}
app.graph.add(node, {doProcessChange: true});
app.canvas.selectNode(node);
}
event.stopPropagation();
}
else if (modelType === "embeddings") {
const text = pathToEmbeddingString(path);
const selectedNodes = app.canvas.selected_nodes;
for (var i in selectedNodes) {
const selectedNode = selectedNodes[i];
const nodeType = modelNodeType(modelType);
const widgetIndex = modelWidgetIndex(nodeType);
const target = selectedNode.widgets[widgetIndex].element;
if (target.type === "textarea") {
const currentText = target.value;
const sep = currentText.length === 0 || currentText.slice(-1).match(/\s/) ? "" : " ";
target.value = currentText + sep + text;
}
}
event.stopPropagation();
}
}
static #dragAddModel(event, modelType, path) {
const target = document.elementFromPoint(event.x, event.y);
if (modelType !== "embeddings" && target.id === "graph-canvas") {
const nodeType = modelNodeType(modelType);
const widgetIndex = modelWidgetIndex(nodeType);
const pos = app.canvas.convertEventToCanvasOffset(event);
const nodeAtPos = app.graph.getNodeOnPos(pos[0], pos[1], app.canvas.visible_nodes);
//if (nodeAtPos && nodeAtPos.type === nodeType && app.canvas.processNodeWidgets(nodeAtPos, pos, event) !== nodeAtPos.widgets[widgetIndex]) {
//if (nodeAtPos && nodeAtPos.type === nodeType && app.canvas.processNodeWidgets(nodeAtPos, pos, event) !== nodeAtPos.widgets[widgetIndex]) { // TODO: settings.strict_model_drag
if (nodeAtPos && nodeAtPos.type === nodeType) {
let node = nodeAtPos;
node.widgets[widgetIndex].value = path;
@@ -319,7 +365,7 @@ class ModelGrid {
successful = true;
}
else {
console.warn("Cannot copy embedding to the system clipboard; Try dragging the element instead.");
console.warn("Cannot copy the embedding to the system clipboard; Try dragging it instead.");
}
}
else if (nodeType) {
@@ -345,11 +391,14 @@ class ModelGrid {
static generateInnerHtml(models, modelType) {
if (models.length > 0) {
// TODO: settings.show_model_add_button
// TODO: settings.show_model_copy_button
return models.map((item) => {
const uri = item.post ?? "no-post";
const imgUrl = `/model-manager/image-preview?uri=${uri}`;
const addModel = (e) => ModelGrid.#addModel(e, modelType, item.path);
const copy = (e) => ModelGrid.#copyModelToClipboard(e, modelType, item.path);
const dragAdd = (e) => ModelGrid.#dragAddModel(e, modelType, item.path);
const clickCopy = (e) => ModelGrid.#copyModelToClipboard(e, modelType, item.path);
const clickAdd = (e) => ModelGrid.#addModel(e, modelType, item.path);
return $el("div.item", {}, [
$el("img.model-preview", {
src: imgUrl,
@@ -357,17 +406,28 @@ class ModelGrid {
}),
$el("div.model-preview-overlay", {
src: imgUrl,
ondragend: (e) => addModel(e),
ondragend: (e) => dragAdd(e),
draggable: true,
}),
$el("button.icon-button.copy-model-button", {
type: "button",
textContent: "⧉︎",
onclick: (e) => copy(e),
$el("div.model-preview-top-right", {
draggable: false,
}),
},
[
$el("button.icon-button.model-button", {
type: "button",
textContent: "⧉︎",
onclick: (e) => clickCopy(e),
draggable: false,
}),
$el("button.icon-button.model-button", {
type: "button",
textContent: "✚",
onclick: (e) => clickAdd(e),
draggable: false,
}),
]),
$el("div.model-label", {
ondragend: (e) => addModel(e),
ondragend: (e) => dragAdd(e),
draggable: true,
}, [
$el("p", [item.name])