added add button
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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])
|
||||
|
||||
Reference in New Issue
Block a user