Merge branch 'pythongosssss:main' into main

This commit is contained in:
mijuku233
2024-01-04 13:07:29 +08:00
committed by GitHub
20 changed files with 216 additions and 54 deletions
+24 -2
View File
@@ -312,7 +312,7 @@ app.registerExtension({
};
TextAreaAutoComplete.globalSeparator = localStorage.getItem(id + ".AutoSeparate") ?? ", ";
app.ui.settings.addSetting({
const enabledSetting = app.ui.settings.addSetting({
id,
name: "🐍 Text Autocomplete",
defaultValue: true,
@@ -356,7 +356,6 @@ app.registerExtension({
},
[
$el("input", {
id: id.replaceAll(".", "-"),
type: "checkbox",
checked: !!TextAreaAutoComplete.globalSeparator,
onchange: (event) => {
@@ -367,6 +366,26 @@ app.registerExtension({
}),
]
),
$el(
"label",
{
textContent: "Replace _ with space ",
style: {
display: "block",
},
},
[
$el("input", {
type: "checkbox",
checked: !!TextAreaAutoComplete.replacer,
onchange: (event) => {
const checked = !!event.target.checked;
TextAreaAutoComplete.replacer = checked ? (v) => v.replaceAll("_", " ") : undefined;
localStorage.setItem(id + ".ReplaceUnderscore", checked);
},
}),
]
),
$el("button", {
textContent: "Manage Custom Words",
onclick: () => {
@@ -383,6 +402,9 @@ app.registerExtension({
]);
},
});
TextAreaAutoComplete.enabled = enabledSetting.value;
TextAreaAutoComplete.replacer = localStorage.getItem(id + ".ReplaceUnderscore") === "true" ? (v) => v.replaceAll("_", " ") : undefined;
},
beforeRegisterNodeDef(_, def) {
// Process each input to see if there is a custom word list for
+5 -4
View File
@@ -27,10 +27,11 @@ app.registerExtension({
left: 0;
top: 0;
transform: translate(-100%, 0);
width: 256px;
height: 256px;
background-size: cover;
background-position: center;
width: 384px;
height: 384px;
background-size: contain;
background-position: top right;
background-repeat: no-repeat;
filter: brightness(65%);
}
`,
+13 -14
View File
@@ -175,8 +175,9 @@ const CHAR_CODE_ZERO = "0".charCodeAt(0);
const CHAR_CODE_NINE = "9".charCodeAt(0);
class TextAreaCaretHelper {
constructor(el) {
constructor(el, getScale) {
this.el = el;
this.getScale = getScale;
}
#calculateElementOffset() {
@@ -253,11 +254,12 @@ class TextAreaCaretHelper {
}
getCursorOffset() {
const scale = this.getScale();
const elOffset = this.#calculateElementOffset();
const elScroll = this.#getElScroll();
const cursorPosition = this.#getCursorPosition();
const lineHeight = this.#getLineHeightPx();
const top = elOffset.top - elScroll.top + cursorPosition.top + lineHeight;
const top = elOffset.top - (elScroll.top * scale) + (cursorPosition.top + lineHeight) * scale;
const left = elOffset.left - elScroll.left + cursorPosition.left;
const clientTop = this.el.getBoundingClientRect().top;
if (this.el.dir !== "rtl") {
@@ -289,8 +291,7 @@ class TextAreaCaretHelper {
const startPos = this.el.selectionStart;
const endPos = this.el.selectionEnd;
this.el.value =
this.el.value.substring(0, startPos + offset) + value + this.el.value.substring(endPos, this.el.value.length);
this.el.value = this.el.value.substring(0, startPos + offset) + value + this.el.value.substring(endPos, this.el.value.length);
this.el.selectionEnd = this.el.selectionStart = startPos + value.length + offset + (finalOffset ?? 0);
} else {
this.el.value += value;
@@ -313,6 +314,7 @@ class TextAreaCaretHelper {
export class TextAreaAutoComplete {
static globalSeparator = "";
static enabled = true;
static replacer = undefined;
/** @type {Record<string, Record<string, AutoCompleteEntry>>} */
static groups = {};
@@ -341,7 +343,7 @@ export class TextAreaAutoComplete {
*/
constructor(el, words = null, separator = null) {
this.el = el;
this.helper = new TextAreaCaretHelper(el);
this.helper = new TextAreaCaretHelper(el, () => app.canvas.ds.scale);
this.dropdown = $el("div.pysssss-autocomplete");
this.overrideWords = words;
this.overrideSeparator = separator;
@@ -481,10 +483,7 @@ export class TextAreaAutoComplete {
);
const top = priorityMatches.length * 0.2;
return priorityMatches
.slice(0, top)
.concat(prefixMatches, priorityMatches.slice(top), includesMatches)
.slice(0, 20);
return priorityMatches.slice(0, top).concat(prefixMatches, priorityMatches.slice(top), includesMatches).slice(0, 20);
}
#update() {
@@ -567,11 +566,11 @@ export class TextAreaAutoComplete {
{
onclick: () => {
this.el.focus();
this.helper.insertAtCursor(
(wordInfo.value ?? wordInfo.text) + this.separator,
-before.length,
wordInfo.caretOffset
);
let value = wordInfo.value ?? wordInfo.text;
if(TextAreaAutoComplete.replacer) {
value = TextAreaAutoComplete.replacer(value);
}
this.helper.insertAtCursor(value + this.separator, -before.length, wordInfo.caretOffset);
setTimeout(() => {
this.#update();
}, 150);
+31 -1
View File
@@ -80,6 +80,12 @@ export class Lightbox {
}
async update(shift) {
if (shift < 0 && this.index <= 0) {
return;
}
if (shift > 0 && this.index >= this.images.length - 1) {
return;
}
this.index += shift;
this.prev.style.visibility = this.index ? "unset" : "hidden";
@@ -91,7 +97,11 @@ export class Lightbox {
this.el.style.opacity = 1;
this.img.style.opacity = 0;
this.spinner.style.display = "inline-block";
await loadImage(img);
try {
await loadImage(img);
} catch (err) {
console.error('failed to load image', img, err);
}
this.spinner.style.display = "none";
this.link.href = img;
this.img.src = img;
@@ -100,3 +110,23 @@ export class Lightbox {
}
export const lightbox = new Lightbox();
addEventListener('keydown', (event) => {
if (lightbox.el.style.display === 'none') {
return;
}
const { key } = event;
switch (key) {
case 'ArrowLeft':
case 'a':
lightbox.update(-1);
break;
case 'ArrowRight':
case 'd':
lightbox.update(1);
break;
case 'Escape':
lightbox.close();
break;
}
});
+1 -1
View File
@@ -410,7 +410,7 @@ app.registerExtension({
api.addEventListener("executed", ({ detail }) => {
if (visible && detail?.output?.images) {
for (const src of detail.output.images) {
const href = `/view?filename=${encodeURIComponent(src.filename)}&type=${
const href = `./view?filename=${encodeURIComponent(src.filename)}&type=${
src.type
}&subfolder=${encodeURIComponent(src.subfolder)}&t=${+new Date()}`;
+2
View File
@@ -234,6 +234,8 @@ const infoHandler = {
CheckpointLoader: "checkpoints",
CheckpointLoaderSimple: "checkpoints",
"CheckpointLoader|pysssss": "checkpoints",
"Efficient Loader": "checkpoints",
"Eff. Loader SDXL": "checkpoints",
};
app.registerExtension({
+12 -1
View File
@@ -15,7 +15,18 @@ app.registerExtension({
return;
}
}
const url = new URL(`assets/notify.mp3`, import.meta.url);
let file = this.widgets[2].value;
if (!file) {
file = "notify.mp3";
}
if (!file.startsWith("http")) {
if (!file.includes("/")) {
file = "assets/" + file;
}
file = new URL(file, import.meta.url)
}
const url = new URL(file);
const audio = new Audio(url);
audio.volume = this.widgets[1].value;
audio.play();
+1 -1
View File
@@ -154,7 +154,7 @@ app.registerExtension({
v = this.widgets_values[0];
}
let config = [link.type, {}];
if (input.widget) {
if (input.widget?.config) {
config = input.widget.config;
}
const { widget } = ComfyWidgets[widgetType](this, "value", config, app);
+6 -4
View File
@@ -49,11 +49,13 @@ const ext = {
api.addEventListener("executed", ({ detail }) => {
if (!enabled) return;
const images = detail?.output?.images;
if (!images) return;
if (!images || !images.length) return;
const format = app.getPreviewFormatParam();
const src = `/view?filename=${encodeURIComponent(images[0].filename)}&type=${
images[0].type
}&subfolder=${encodeURIComponent(images[0].subfolder)}&t=${+new Date()}${format}`;
const src = [
`./view?filename=${encodeURIComponent(images[0].filename)}`,
`type=${images[0].type}`,
`subfolder=${encodeURIComponent(images[0].subfolder)}`,
`t=${+new Date()}${format}`,].join('&');
show(src, detail.node);
});
+8 -8
View File
@@ -2,23 +2,23 @@ import { app } from "../../../scripts/app.js";
import { ComfyWidgets } from "../../../scripts/widgets.js";
// Displays input text on a node
app.registerExtension({
name: "pysssss.ShowText",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === "ShowText|pysssss") {
function populate(text) {
if (this.widgets) {
const pos = this.widgets.findIndex((w) => w.name === "text");
if (pos !== -1) {
for (let i = pos; i < this.widgets.length; i++) {
this.widgets[i].onRemove?.();
}
this.widgets.length = pos;
for (let i = 1; i < this.widgets.length; i++) {
this.widgets[i].onRemove?.();
}
this.widgets.length = 1;
}
for (const list of text) {
const v = [...text];
if (!v[0]) {
v.shift();
}
for (const list of v) {
const w = ComfyWidgets["STRING"](this, "text", ["STRING", { multiline: true }], app).widget;
w.inputEl.readOnly = true;
w.inputEl.style.opacity = 0.6;
+1 -1
View File
@@ -386,7 +386,7 @@ class SvgWorkflowImage extends WorkflowImage {
return;
} else if (file && (file.type === "image/jpeg" || file.name?.endsWith(".jpg") || file.name?.endsWith(".jpeg"))) {
if (
await new Promise((r) => {
await new Promise((resolve) => {
try {
// This shouldnt go in here but it's easier than refactoring handleFile
const reader = new FileReader();
+3
View File
@@ -81,6 +81,9 @@ async function saveWorkflow(name, workflow, overwrite) {
class PysssssWorkflows {
async load() {
this.workflows = await getWorkflows();
if(this.workflows.length) {
this.workflows.sort();
}
this.loadMenu.style.display = this.workflows.length ? "flex" : "none";
}