Generalize the UI messaging in rgthree.
This commit is contained in:
+118
-69
@@ -74,7 +74,18 @@ class LogSession {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export type RgthreeUiMessage = {
|
||||
id: string;
|
||||
message: string;
|
||||
type?: 'warn'|null;
|
||||
timeout?: number;
|
||||
// closeable?: boolean; // TODO
|
||||
actions?: Array<{
|
||||
label: string;
|
||||
href?: string;
|
||||
callback?: (event: MouseEvent) => void;
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A global class as 'rgthree'; exposed on wiindow. Lots can go in here.
|
||||
@@ -91,6 +102,77 @@ class Rgthree {
|
||||
monitorBadLinksAlerted = false;
|
||||
monitorLinkTimeout: number|null = null;
|
||||
|
||||
async clearAllMessages() {
|
||||
let container = document.querySelector('.rgthree-top-messages-container');
|
||||
container && (container.innerHTML = '');
|
||||
}
|
||||
|
||||
async showMessage(data: RgthreeUiMessage) {
|
||||
let container = document.querySelector('.rgthree-top-messages-container');
|
||||
if (!container) {
|
||||
container = document.createElement('div');
|
||||
container.classList.add('rgthree-top-messages-container');
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
// Hide if we exist.
|
||||
await this.hideMessage(data.id);
|
||||
|
||||
const messageContainer = document.createElement('div');
|
||||
messageContainer.setAttribute('type', data.type || 'info');
|
||||
|
||||
const message = document.createElement('span');
|
||||
message.innerText = data.message;
|
||||
messageContainer.appendChild(message);
|
||||
|
||||
for (let a = 0; a < (data.actions || []).length; a++) {
|
||||
const action = data.actions![a]!;
|
||||
if (a > 0) {
|
||||
const sep = document.createElement('span');
|
||||
sep.innerHTML = ' | ';
|
||||
messageContainer.appendChild(sep);
|
||||
}
|
||||
|
||||
const actionEl = document.createElement('a');
|
||||
actionEl.innerText = action.label;
|
||||
if (action.href) {
|
||||
actionEl.target = '_blank';
|
||||
actionEl.href = action.href;
|
||||
}
|
||||
if (action.callback) {
|
||||
actionEl.onclick = (e) => {
|
||||
return action.callback!(e);
|
||||
}
|
||||
}
|
||||
messageContainer.appendChild(actionEl);
|
||||
}
|
||||
|
||||
const messageAnimContainer = document.createElement('div');
|
||||
messageAnimContainer.setAttribute('msg-id', data.id);
|
||||
messageAnimContainer.appendChild(messageContainer);
|
||||
container.appendChild(messageAnimContainer);
|
||||
|
||||
// Add. Wait. Measure. Wait. Anim.
|
||||
await wait(64);
|
||||
messageAnimContainer.style.marginTop = `-${messageAnimContainer.offsetHeight}px`;
|
||||
await wait(64);
|
||||
messageAnimContainer.classList.add('-show');
|
||||
|
||||
if (data.timeout) {
|
||||
await wait(data.timeout);
|
||||
this.hideMessage(data.id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async hideMessage(id: string) {
|
||||
const msg = document.querySelector(`.rgthree-top-messages-container > [msg-id="${id}"]`);
|
||||
if (msg?.classList.contains('-show')) {
|
||||
msg.classList.remove('-show');
|
||||
await wait(750);
|
||||
}
|
||||
msg && msg.remove();
|
||||
}
|
||||
|
||||
constructor() {
|
||||
window.addEventListener("keydown", (e) => {
|
||||
this.ctrlKey = !!e.ctrlKey;
|
||||
@@ -128,17 +210,17 @@ class Rgthree {
|
||||
|
||||
const clean = app.clean;
|
||||
app.clean = function() {
|
||||
document.querySelector('.rgthree-bad-links-alerts-container')?.remove();
|
||||
that.clearAllMessages();
|
||||
clean && clean.call(app, ...arguments);
|
||||
};
|
||||
|
||||
const loadGraphData = app.loadGraphData;
|
||||
app.loadGraphData = function(graph: serializedLGraph) {
|
||||
if (this.monitorLinkTimeout) {
|
||||
clearTimeout(this.monitorLinkTimeout);
|
||||
this.monitorLinkTimeout = null;
|
||||
if (that.monitorLinkTimeout) {
|
||||
clearTimeout(that.monitorLinkTimeout);
|
||||
that.monitorLinkTimeout = null;
|
||||
}
|
||||
document.querySelector('.rgthree-bad-links-alerts-container')?.remove();
|
||||
that.clearAllMessages();
|
||||
// Try to make a copy to use, because ComfyUI's loadGraphData will modify it.
|
||||
let graphCopy: serializedLGraph|null;
|
||||
try {
|
||||
@@ -151,71 +233,38 @@ class Rgthree {
|
||||
const graphToUse = wasLoadingAborted ? (graphCopy || graph) : app.graph
|
||||
const fixBadLinksResult = fixBadLinks(graphToUse);
|
||||
if (fixBadLinksResult.hasBadLinks) {
|
||||
const div = document.createElement('div');
|
||||
div.classList.add('rgthree-bad-links-alerts');
|
||||
div.innerHTML = `
|
||||
<span style="font-size: 18px; margin-right: 4px; display: inline-block; line-height:1">⚠️</span>
|
||||
<span style="flex; 1 1 auto; ">
|
||||
The workflow you've loaded may have connection/linking data that could be fixed.
|
||||
</span>
|
||||
<a target="_blank"
|
||||
style="color: #fc0; margin-left: 4px; display: inline-block; line-height:1"
|
||||
href="/extensions/rgthree-comfy/html/links.html">Open fixer<a>
|
||||
<span> | </span>
|
||||
<a class="fix-in-place" target="_blank"
|
||||
style="cursor: pointer; text-decoration: underline; color: #fc0; margin-left: 4px; display: inline-block; line-height:1"
|
||||
>Fix in place<a>
|
||||
`;
|
||||
div.style.background = '#353535';
|
||||
div.style.color = '#fff';
|
||||
div.style.display = 'flex';
|
||||
div.style.flexDirection = 'row';
|
||||
div.style.alignItems = 'center';
|
||||
div.style.justifyContent = 'center';
|
||||
div.style.height = 'fit-content';
|
||||
div.style.boxShadow = '0 0 10px rgba(0,0,0,0.88)';
|
||||
div.style.padding = '6px 12px';
|
||||
div.style.borderRadius = '0 0 4px 4px';
|
||||
div.style.fontFamily = 'Arial, sans-serif';
|
||||
div.style.fontSize = '14px';
|
||||
div.style.transform = 'translateY(-100%)';
|
||||
div.style.transition = 'transform 0.5s ease-in-out';
|
||||
const container = document.createElement('div');
|
||||
container.classList.add('rgthree-bad-links-alerts-container');
|
||||
container.appendChild(div);
|
||||
container.style.position = 'fixed';
|
||||
container.style.zIndex = '9999';
|
||||
container.style.top = '0';
|
||||
container.style.left = '0';
|
||||
container.style.width = '100%';
|
||||
container.style.height = '0';
|
||||
container.style.display = 'flex';
|
||||
container.style.justifyContent = 'center';
|
||||
document.body.appendChild(container);
|
||||
|
||||
div.querySelector('.fix-in-place')?.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
if (confirm('This will attempt to fix in place. Please make sure to have a saved copy of your workflow.')) {
|
||||
const fixBadLinksResult = fixBadLinks(graphToUse, true);
|
||||
if (!fixBadLinksResult.hasBadLinks) {
|
||||
alert('Success! It\'s possible some valid links may have been affected. Please check and verify your workflow.');
|
||||
wasLoadingAborted && app.loadGraphData(fixBadLinksResult.graph);
|
||||
container.remove();
|
||||
if (rgthreeConfig['monitor_bad_links']) {
|
||||
that.monitorLinkTimeout = setTimeout(() => {
|
||||
that.monitorBadLinks();
|
||||
}, 5000);
|
||||
that.showMessage({
|
||||
id: 'bad-links',
|
||||
type: 'warn',
|
||||
message: 'The workflow you\'ve loaded may have connection/linking data that could be fixed.',
|
||||
actions: [
|
||||
{
|
||||
label: 'Open fixer',
|
||||
href: '/extensions/rgthree-comfy/html/links.html',
|
||||
},
|
||||
{
|
||||
label: 'Fix in place',
|
||||
href: '/extensions/rgthree-comfy/html/links.html',
|
||||
callback: (event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
if (confirm('This will attempt to fix in place. Please make sure to have a saved copy of your workflow.')) {
|
||||
const fixBadLinksResult = fixBadLinks(graphToUse, true);
|
||||
if (!fixBadLinksResult.hasBadLinks) {
|
||||
that.hideMessage('bad-links');
|
||||
alert('Success! It\'s possible some valid links may have been affected. Please check and verify your workflow.');
|
||||
wasLoadingAborted && app.loadGraphData(fixBadLinksResult.graph);
|
||||
if (rgthreeConfig['monitor_bad_links']) {
|
||||
that.monitorLinkTimeout = setTimeout(() => {
|
||||
that.monitorBadLinks();
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const container = document.querySelector('.rgthree-bad-links-alerts') as HTMLElement;
|
||||
container && (container.style.transform = 'translateY(0%)');
|
||||
}, 500);
|
||||
} else if (rgthreeConfig['monitor_bad_links']) {
|
||||
that.monitorLinkTimeout = setTimeout(() => {
|
||||
that.monitorBadLinks();
|
||||
|
||||
@@ -1,4 +1,82 @@
|
||||
|
||||
.rgthree-top-messages-container {
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.rgthree-top-messages-container > div {
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
padding: 4px;
|
||||
margin-top: -100px; /* re-set by JS */
|
||||
opacity: 0;
|
||||
transition: all 0.33s ease-in-out;
|
||||
z-index: 3;
|
||||
}
|
||||
.rgthree-top-messages-container > div:last-child {
|
||||
z-index: 2;
|
||||
}
|
||||
.rgthree-top-messages-container > div:not(.-show) {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.rgthree-top-messages-container > div.-show {
|
||||
opacity: 1;
|
||||
margin-top: 0px !important;
|
||||
}
|
||||
|
||||
.rgthree-top-messages-container > div.-show {
|
||||
opacity: 1;
|
||||
transform: translateY(0%);
|
||||
}
|
||||
|
||||
.rgthree-top-messages-container > div > div {
|
||||
position: relative;
|
||||
background: #353535;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: fit-content;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.88);
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.rgthree-top-messages-container [type="warn"]::before {
|
||||
content: '⚠️';
|
||||
display: inline-block;
|
||||
flex: 0 0 auto;
|
||||
font-size: 18px;
|
||||
margin-right: 4px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.rgthree-top-messages-container a {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
color: #fc0;
|
||||
margin-left: 4px;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.rgthree-top-messages-container a:hover {
|
||||
color: #fc0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Fix node selector being crazy long b/c of array types. */
|
||||
.litegraph.litesearchbox input,
|
||||
.litegraph.litesearchbox select {
|
||||
|
||||
+94
-68
@@ -59,6 +59,64 @@ class LogSession {
|
||||
}
|
||||
}
|
||||
class Rgthree {
|
||||
async clearAllMessages() {
|
||||
let container = document.querySelector('.rgthree-top-messages-container');
|
||||
container && (container.innerHTML = '');
|
||||
}
|
||||
async showMessage(data) {
|
||||
let container = document.querySelector('.rgthree-top-messages-container');
|
||||
if (!container) {
|
||||
container = document.createElement('div');
|
||||
container.classList.add('rgthree-top-messages-container');
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
await this.hideMessage(data.id);
|
||||
const messageContainer = document.createElement('div');
|
||||
messageContainer.setAttribute('type', data.type || 'info');
|
||||
const message = document.createElement('span');
|
||||
message.innerText = data.message;
|
||||
messageContainer.appendChild(message);
|
||||
for (let a = 0; a < (data.actions || []).length; a++) {
|
||||
const action = data.actions[a];
|
||||
if (a > 0) {
|
||||
const sep = document.createElement('span');
|
||||
sep.innerHTML = ' | ';
|
||||
messageContainer.appendChild(sep);
|
||||
}
|
||||
const actionEl = document.createElement('a');
|
||||
actionEl.innerText = action.label;
|
||||
if (action.href) {
|
||||
actionEl.target = '_blank';
|
||||
actionEl.href = action.href;
|
||||
}
|
||||
if (action.callback) {
|
||||
actionEl.onclick = (e) => {
|
||||
return action.callback(e);
|
||||
};
|
||||
}
|
||||
messageContainer.appendChild(actionEl);
|
||||
}
|
||||
const messageAnimContainer = document.createElement('div');
|
||||
messageAnimContainer.setAttribute('msg-id', data.id);
|
||||
messageAnimContainer.appendChild(messageContainer);
|
||||
container.appendChild(messageAnimContainer);
|
||||
await wait(64);
|
||||
messageAnimContainer.style.marginTop = `-${messageAnimContainer.offsetHeight}px`;
|
||||
await wait(64);
|
||||
messageAnimContainer.classList.add('-show');
|
||||
if (data.timeout) {
|
||||
await wait(data.timeout);
|
||||
this.hideMessage(data.id);
|
||||
}
|
||||
}
|
||||
async hideMessage(id) {
|
||||
const msg = document.querySelector(`.rgthree-top-messages-container > [msg-id="${id}"]`);
|
||||
if (msg === null || msg === void 0 ? void 0 : msg.classList.contains('-show')) {
|
||||
msg.classList.remove('-show');
|
||||
await wait(750);
|
||||
}
|
||||
msg && msg.remove();
|
||||
}
|
||||
constructor() {
|
||||
this.ctrlKey = false;
|
||||
this.altKey = false;
|
||||
@@ -98,18 +156,16 @@ class Rgthree {
|
||||
};
|
||||
const clean = app.clean;
|
||||
app.clean = function () {
|
||||
var _a;
|
||||
(_a = document.querySelector('.rgthree-bad-links-alerts-container')) === null || _a === void 0 ? void 0 : _a.remove();
|
||||
that.clearAllMessages();
|
||||
clean && clean.call(app, ...arguments);
|
||||
};
|
||||
const loadGraphData = app.loadGraphData;
|
||||
app.loadGraphData = function (graph) {
|
||||
var _a;
|
||||
if (this.monitorLinkTimeout) {
|
||||
clearTimeout(this.monitorLinkTimeout);
|
||||
this.monitorLinkTimeout = null;
|
||||
if (that.monitorLinkTimeout) {
|
||||
clearTimeout(that.monitorLinkTimeout);
|
||||
that.monitorLinkTimeout = null;
|
||||
}
|
||||
(_a = document.querySelector('.rgthree-bad-links-alerts-container')) === null || _a === void 0 ? void 0 : _a.remove();
|
||||
that.clearAllMessages();
|
||||
let graphCopy;
|
||||
try {
|
||||
graphCopy = JSON.parse(JSON.stringify(graph));
|
||||
@@ -118,73 +174,43 @@ class Rgthree {
|
||||
graphCopy = null;
|
||||
}
|
||||
setTimeout(() => {
|
||||
var _a, _b, _c;
|
||||
var _a, _b;
|
||||
const wasLoadingAborted = (_b = (_a = document.querySelector('.comfy-modal-content')) === null || _a === void 0 ? void 0 : _a.textContent) === null || _b === void 0 ? void 0 : _b.includes('Loading aborted due');
|
||||
const graphToUse = wasLoadingAborted ? (graphCopy || graph) : app.graph;
|
||||
const fixBadLinksResult = fixBadLinks(graphToUse);
|
||||
if (fixBadLinksResult.hasBadLinks) {
|
||||
const div = document.createElement('div');
|
||||
div.classList.add('rgthree-bad-links-alerts');
|
||||
div.innerHTML = `
|
||||
<span style="font-size: 18px; margin-right: 4px; display: inline-block; line-height:1">⚠️</span>
|
||||
<span style="flex; 1 1 auto; ">
|
||||
The workflow you've loaded may have connection/linking data that could be fixed.
|
||||
</span>
|
||||
<a target="_blank"
|
||||
style="color: #fc0; margin-left: 4px; display: inline-block; line-height:1"
|
||||
href="/extensions/rgthree-comfy/html/links.html">Open fixer<a>
|
||||
<span> | </span>
|
||||
<a class="fix-in-place" target="_blank"
|
||||
style="cursor: pointer; text-decoration: underline; color: #fc0; margin-left: 4px; display: inline-block; line-height:1"
|
||||
>Fix in place<a>
|
||||
`;
|
||||
div.style.background = '#353535';
|
||||
div.style.color = '#fff';
|
||||
div.style.display = 'flex';
|
||||
div.style.flexDirection = 'row';
|
||||
div.style.alignItems = 'center';
|
||||
div.style.justifyContent = 'center';
|
||||
div.style.height = 'fit-content';
|
||||
div.style.boxShadow = '0 0 10px rgba(0,0,0,0.88)';
|
||||
div.style.padding = '6px 12px';
|
||||
div.style.borderRadius = '0 0 4px 4px';
|
||||
div.style.fontFamily = 'Arial, sans-serif';
|
||||
div.style.fontSize = '14px';
|
||||
div.style.transform = 'translateY(-100%)';
|
||||
div.style.transition = 'transform 0.5s ease-in-out';
|
||||
const container = document.createElement('div');
|
||||
container.classList.add('rgthree-bad-links-alerts-container');
|
||||
container.appendChild(div);
|
||||
container.style.position = 'fixed';
|
||||
container.style.zIndex = '9999';
|
||||
container.style.top = '0';
|
||||
container.style.left = '0';
|
||||
container.style.width = '100%';
|
||||
container.style.height = '0';
|
||||
container.style.display = 'flex';
|
||||
container.style.justifyContent = 'center';
|
||||
document.body.appendChild(container);
|
||||
(_c = div.querySelector('.fix-in-place')) === null || _c === void 0 ? void 0 : _c.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
if (confirm('This will attempt to fix in place. Please make sure to have a saved copy of your workflow.')) {
|
||||
const fixBadLinksResult = fixBadLinks(graphToUse, true);
|
||||
if (!fixBadLinksResult.hasBadLinks) {
|
||||
alert('Success! It\'s possible some valid links may have been affected. Please check and verify your workflow.');
|
||||
wasLoadingAborted && app.loadGraphData(fixBadLinksResult.graph);
|
||||
container.remove();
|
||||
if (rgthreeConfig['monitor_bad_links']) {
|
||||
that.monitorLinkTimeout = setTimeout(() => {
|
||||
that.monitorBadLinks();
|
||||
}, 5000);
|
||||
that.showMessage({
|
||||
id: 'bad-links',
|
||||
type: 'warn',
|
||||
message: 'The workflow you\'ve loaded may have connection/linking data that could be fixed.',
|
||||
actions: [
|
||||
{
|
||||
label: 'Open fixer',
|
||||
href: '/extensions/rgthree-comfy/html/links.html',
|
||||
},
|
||||
{
|
||||
label: 'Fix in place',
|
||||
href: '/extensions/rgthree-comfy/html/links.html',
|
||||
callback: (event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
if (confirm('This will attempt to fix in place. Please make sure to have a saved copy of your workflow.')) {
|
||||
const fixBadLinksResult = fixBadLinks(graphToUse, true);
|
||||
if (!fixBadLinksResult.hasBadLinks) {
|
||||
that.hideMessage('bad-links');
|
||||
alert('Success! It\'s possible some valid links may have been affected. Please check and verify your workflow.');
|
||||
wasLoadingAborted && app.loadGraphData(fixBadLinksResult.graph);
|
||||
if (rgthreeConfig['monitor_bad_links']) {
|
||||
that.monitorLinkTimeout = setTimeout(() => {
|
||||
that.monitorBadLinks();
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
});
|
||||
setTimeout(() => {
|
||||
const container = document.querySelector('.rgthree-bad-links-alerts');
|
||||
container && (container.style.transform = 'translateY(0%)');
|
||||
}, 500);
|
||||
}
|
||||
else if (rgthreeConfig['monitor_bad_links']) {
|
||||
that.monitorLinkTimeout = setTimeout(() => {
|
||||
|
||||
Reference in New Issue
Block a user