Replies: 11 comments 3 replies
-
I checked setting labels, and could bring another very minor improvement (they are currently discarded). |
Beta Was this translation helpful? Give feedback.
-
Hi, Thanks for the write up!
370914061-25630131-2f4a-45bc-80e8-9b5acaf2f1c9.mp4 |
Beta Was this translation helpful? Give feedback.
-
Oh and FYI I have a lot of unpublished code (mostly js/frontend stuff) that I plan to organize better: use a bundler, probably switch to typescript.... |
Beta Was this translation helpful? Give feedback.
-
Great! So I will work on a PR (my first one...), you can expect something by the end of this week the latest. And BTW: I'm more comfortable with TS than JS (and I surely prefer good typings), so in the future if you need some help, don't hesitate to ping me. That would be a good exercise for me to understand Comfy better. |
Beta Was this translation helpful? Give feedback.
-
Hi @melMass, |
Beta Was this translation helpful? Give feedback.
-
No pressure at all! |
Beta Was this translation helpful? Give feedback.
-
(That said it can be also tested with a workflow showing various cases we can try to break) |
Beta Was this translation helpful? Give feedback.
-
Hi @melMass , Once again, all my sincere apologies for the time I took to push this PR, but here it is at last! -> #222 The 3 improvements described above have been implemented. You may want to check the JSDoc syntax (not really used to), for the rest it should be good I think. Note 1: sorry, my prettier config may have slightly messed up with yours, so you may have to re-save the file I'm afraid... Note 2: my code currently relies on
We talked about testing, and I could propose a node you may find interesting. It's a simple string formatter (using Python
Example with the template string: I hope you'll find this PR interesting. Do not hesitate if you want me to update this PR with the regexp, or to create a new one with the string formatter. Cheers! |
Beta Was this translation helpful? Give feedback.
-
Maybe easier than a PR, here is the code for the string formatter node, as you can see it's dead simple: class FormatString:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
return {
'required': {
'format': (
'STRING',
{
'default': 'my first arg: {arg0}, second by index: {1}',
'multiline': False,
},
),
}
}
@classmethod
def VALIDATE_INPUTS(s, input_types):
for t in input_types.values():
if t not in ['STRING', 'INT', 'FLOAT', 'BOOLEAN']:
return False
return True
CATEGORY = 'ChangeMe'
RETURN_TYPES = ('STRING',)
RETURN_NAMES = ('formatted',)
FUNCTION = 'run'
def run(self, format: str, **kw):
# handle both index and name references
output = format.format(*kw.values(), **kw)
return (output,) With the following JS code, in setupDynamicConnections(nodeType, "arg", "*", { separator: "", start_index: 0,}); |
Beta Was this translation helpful? Give feedback.
-
Hi @melMass , While importing my previous nodes into my new collection (soon to be shared publicly), I came across a bug with the I found a solution to this, basically adapting a trick I used in other nodes, where I need to dynamically show / hide a multiline preview. It consists in storing the actual node size, let Unfortunately, I cannot propose a PR, as I switched to Typescript, but if you're interested, here is the code, in // replace the call to dynamicConnection with this
// keep a track of current size, and also the minimum / computed one
const oldSize = [this.size[0], this.size[1]]
const oldComputedSize = this.computeSize()
dynamicConnection(
this,
slotIndex as number,
isConnected as boolean,
`${prefix}${options.separator}`,
inputType as string,
options,
)
// reset positions of all widgets, they will be recalculated
for (const widget of this.widgets || []) {
delete widget.y
delete widget.last_y
// computedHeight is used by the multiline widgets, it must be reset to force it to take all height
delete widget.computedHeight
}
// get the new computed size, after adding / removing inputs
const newComputedSize = this.computeSize()
// recalculate the node size: preserve width, and increase / decrease height
this.setSize([
oldSize[0],
oldSize[1] + newComputedSize[1] - oldComputedSize[1],
])
return r PS: I will soon ping you when my repo is created: still need to refine some details + a massive documentation effort. But most of the job is done, and I must say I'm pretty satisfied with the result, with many interesting UI tweaks (and the dynamic outputs work well! \o/). Once again a long post, sorry! Hope everything is fine on your side, Pascal. |
Beta Was this translation helpful? Give feedback.
-
That's great, sincerely happy to help!
No CI or such on my side, I have both the TS and JS code in the repo, as I know many people still work with JS and will maybe want to be able to search / copy code from it (and the disk usage impact is negligible). For the watch / build part, here is an excerpt from my "watch": "tsc-watch -p tsconfig.json --onSuccess 'tsc-alias -p tsconfig.json -r build/replacers.js/mock.js'",
"build": "rimraf ./dist/js && tsc -p tsconfig.prod.json && tsc-alias -p tsconfig.prod.json -r build/replacers.js/mock.js", The trick is to use tsc-alias instead of the more common tsconfig-paths, because it allows having some custom path replacers, in addition to handling the aliases in /**
* Replace the paths within the '.mock' folder into the relative path expected at runtime.
* We use a RegExp to achieve this, could be another approach
*/
const re = /[^'"`]*\/\.mock\//
export default function mockReplacer({
orig,
// file,
// config,
}) {
if (re.test(orig)) {
// count the number of '..' before '.mock' folder
const nbParents = (orig.match(/\.\.\//g) || []).length
const replaced = orig.replace(re, '../'.repeat(3 + nbParents)) // 3 because of my code structure, you may have to adjust
return replaced
}
return orig
} And in the import type { ComfyApp } from '@comfyorg/comfyui-frontend-types'
export declare const app: ComfyApp That's it! No CI burden, no custom python script, no problem! And a VSCode task to launch my watch script on workspace opening makes me an happy coder :) Also, I wanted to say: it's thanks to you and the dynamic inputs trick that I discovered all this frontend part... and got totally contaminated... But I really enjoy it (even if I dislike LiteGraph)! |
Beta Was this translation helpful? Give feedback.
-
Note
This was implemented in #222
Describe the problem
Currently the dynamic inputs work well, but could be slightly improved with the following features:
_
(even empty''
)1
(I personally prefer0
, but I understand most people don't)Describe the solution you'd like
I have implemented some light modifications to your code (
setupDynamicConnections()
anddynamic_connection()
inweb/comfy_shared.js
) to handle the cases above:separator
andstart_index
argument
vsarg
)startsWith()
to filter dynamic onesAlternatives considered
No response
Additional context
Salut !
First, a big thank for your work!
Although rather new to Comfy, I got interested with dynamic inputs for my own / personal nodes, so I first discovered the cozy-comfyui repo (very nice introduction), then came across yours which proposes a more advanced solution.
And I must say I'm impressed, except a very minor issue on manual disconnection (totally acceptable), it works perfectly!
I implemented the tiny QoL improvements above for my own use: the first one (
separator
/start_index
) is pretty straightforward, the second one a bit more debatable, as not dealing with input order may confuse users a bit.No revolution here, they are very simple, but if you think they could be interesting, just tell me and I'll be happy to contribute.
Either by describing the changes in this issue, or even proposing a PR if you want.
Thanks again for sharing your work, cheers!
Beta Was this translation helpful? Give feedback.
All reactions