From 605c8db320e1531c6347f6888606fa50d8eb268b Mon Sep 17 00:00:00 2001 From: melMass Date: Sat, 2 Dec 2023 19:07:32 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=93=9D=20add=20note=20plus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit future ideas: - add a markdown mode - add a separate css tab on the edit dialog --- web/comfy_shared.js | 37 +++++++++ web/mtb_widgets.js | 2 + web/note_plus.js | 181 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 web/note_plus.js diff --git a/web/comfy_shared.js b/web/comfy_shared.js index 6be9745..60902cb 100644 --- a/web/comfy_shared.js +++ b/web/comfy_shared.js @@ -334,6 +334,43 @@ function getBrightness(rgbObj) { } //- HTML / CSS UTILS +export const loadScript = ( + FILE_URL, + async = true, + type = 'text/javascript' +) => { + return new Promise((resolve, reject) => { + try { + // Check if the script already exists + const existingScript = document.querySelector(`script[src="${FILE_URL}"]`) + if (existingScript) { + resolve({ status: true, message: 'Script already loaded' }) + return + } + + const scriptEle = document.createElement('script') + scriptEle.type = type + scriptEle.async = async + scriptEle.src = FILE_URL + + scriptEle.addEventListener('load', (ev) => { + resolve({ status: true }) + }) + + scriptEle.addEventListener('error', (ev) => { + reject({ + status: false, + message: `Failed to load the script ${FILE_URL}`, + }) + }) + + document.body.appendChild(scriptEle) + } catch (error) { + reject(error) + } + }) +} + export function defineClass(className, classStyles) { const styleSheets = document.styleSheets diff --git a/web/mtb_widgets.js b/web/mtb_widgets.js index d193e0a..8df622f 100644 --- a/web/mtb_widgets.js +++ b/web/mtb_widgets.js @@ -7,6 +7,8 @@ * */ +// TODO: Use the builtin addDOMWidget everywhere appropriate + import { app } from '../../scripts/app.js' import { api } from '../../scripts/api.js' diff --git a/web/note_plus.js b/web/note_plus.js new file mode 100644 index 0000000..aa07fb0 --- /dev/null +++ b/web/note_plus.js @@ -0,0 +1,181 @@ +import { app } from '../../scripts/app.js' +import { api } from '../../scripts/api.js' +import * as shared from './comfy_shared.js' + +class NotePlus extends LiteGraph.LGraphNode { + title = 'Note+ (mtb)' + category = 'mtb/utils' + + constructor() { + super() + + this.isVirtualNode = true + this.serialize_widgets = true + + this.editing = false + this.live = true + this.rawVal = "

Note+\n

" + + this.calculated_height = 36 + + const inner = document.createElement('div') + inner.style.margin = '0' + inner.style.padding = '0' + this.html_widget = this.addDOMWidget('HTML', 'html', inner, { + setValue: (v) => { + // update our widget preview + this.html_widget.element.innerHTML = v + // calculate height + this.calculated_height = this.html_widget.element.scrollHeight + 36 + }, + getValue: () => this.rawVal, + getMinHeight: () => this.calculated_height, // (the edit button), + }) + + // console.log(`Value of HTML: ${this.html_widget.value}`) + this.html_widget.element.innerHTML = this.html_widget.value + + //- ace based editor + this.addWidget('button', 'Edit', 'Edit', () => { + const container = document.createElement('div') + Object.assign(container.style, { + display: 'flex', + gap: '10px', + }) + + dialog.show('') + dialog.textElement.append(container) + + const value = document.createElement('div') + value.id = 'noteplus-editor' + Object.assign(value.style, { + width: '300px', + height: '200px', + backgroundColor: 'rgb(30,30,30)', + color: 'whitesmoke', + }) + + container.append(value) + + const live_edit = document.createElement('input') + live_edit.type = 'checkbox' + live_edit.checked = this.live + live_edit.onchange = () => { + this.live = live_edit.checked + } + + const live_edit_label = document.createElement('label') + live_edit_label.textContent = 'Live Edit' + live_edit_label.append(live_edit) + + value.after(live_edit_label) + + this.setupEditor() + this.editor.setValue(this.html_widget.element.innerHTML) + }) + + const dialog = new app.ui.dialog.constructor() + dialog.element.classList.add('comfy-settings') + + const closeButton = dialog.element.querySelector('button') + closeButton.textContent = 'CANCEL' + const saveButton = document.createElement('button') + saveButton.textContent = 'SAVE' + saveButton.onclick = () => { + this.updateHTML(this.editor.getValue()) + + this.editor.destroy() + this.editor.container.remove() + + dialog.close() + } + + closeButton.before(saveButton) + + shared + .loadScript( + 'https://cdn.jsdelivr.net/npm/ace-builds@1.16.0/src-min-noconflict/ace.min.js' + ) + .catch((e) => { + console.error(e) + }) + } + + setupEditor() { + this.editor = ace.edit('noteplus-editor') + this.editor.setTheme('ace/theme/dracula') + this.editor.session.setMode('ace/mode/html') + + this.editor.setShowPrintMargin(false) + this.editor.session.setUseWrapMode(true) + this.editor.renderer.setShowGutter(false) + this.editor.session.setTabSize(4) + this.editor.session.setUseSoftTabs(true) + this.editor.setFontSize(14) + this.editor.setReadOnly(false) + this.editor.setHighlightActiveLine(false) + this.editor.setShowFoldWidgets(true) + + this.editor.session.on('change', (delta) => { + // delta.start, delta.end, delta.lines, delta.action + if (this.live) { + this.updateHTML(this.editor.getValue()) + } + }) + } + + updateHTML(val) { + // if (CONTAINER_HTML.includes('${html}')) { + // console.log('found template') + // val = CONTAINER_HTML.replace('${html}', val) + // } + + this.html_widget.value = val + this.rawVal = val + + this.calculated_height = this.html_widget.element.scrollHeight + + this.setSize(this.computeSize()) + } + + // // onRemoved() { + // // console.log('Removing', this) + // // for (const w of this.widgets) { + // // console.log('Removing', w) + // // w.onRemove?.() + // // w.onRemoved?.() + // // } + // // } +} + +app.registerExtension({ + name: 'mtb.noteplus', + + setup() { + // app.ui.settings.addSetting({ + // id: "mtb.noteplus.Container", + // name: "📦 HTML container", + // type: "text", + // defaultValue: "
${html}
", + // tooltip: + // "This defines the wrapper for the noteplus html content, use '${html}' to define the location of the placeholder", + // attrs: { + // style: { + // fontFamily: "monospace", + // }, + // }, + // onChange(value) { + // if (!value) { + // CONTAINER_HTML = null; + // return; + // } + // console.log(`NOTEPLUS| value changed: ${value}`) + // CONTAINER_HTML = value + // }, + // }); + }, + + registerCustomNodes() { + LiteGraph.registerNodeType('Note Plus (mtb)', NotePlus) + }, +})