RPComfy / ComfyUI /web /extensions /tinyterraNodes /ttNfullscreen.js
Metaphysix2's picture
Upload folder using huggingface_hub
3e5f61c
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
const FULLSCREEN_WRAPPER_ID = "ttN-FullscreenWrapper";
const FULLSCREEN_IMAGE_ID = "ttN-FullscreenImage";
const IMAGE_PREVIEWS_WRAPPER_ID = "ttN-imagePreviewsWrapper";
let ttN_isFullscreen = false;
let ttN_FullscreenImage = new Image();
let ttN_FullscreenImageIndex = 0;
let ttN_FullscreenNode = null;
let ttN_Slideshow = true;
let ttN_srcDict = {};
let ttN_imageElementsDict = {};
loadSrcDict()
const ARROW_KEYS = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
function saveSrcDict() {
sessionStorage.setItem('ttN_srcDict', JSON.stringify(ttN_srcDict));
}
function loadSrcDict() {
const savedData = sessionStorage.getItem('ttN_srcDict');
if (savedData) {
ttN_srcDict = JSON.parse(savedData);
}
}
function clearSrcDict() {
ttN_srcDict = {};
sessionStorage.removeItem('ttN_srcDict');
}
function _getSelectedNode() {
const graphcanvas = LGraphCanvas.active_canvas;
if (graphcanvas.selected_nodes && Object.keys(graphcanvas.selected_nodes).length === 1) {
return Object.values(graphcanvas.selected_nodes)[0];
}
return null;
}
function _findFullImageSRC(node) {
if (node.imgs) {
let img = node.imgs.find(imgElement => imgElement.src.includes("filename"));
return img ? img.src : null;
}
return null;
}
function _findLatentPreviewImageSRC(node) {
if (!node.imgs) return null;
if (node.imageIndex !== null && node.imageIndex < node.imgs.length) {
return node.imgs[node.imageIndex].src;
} else if (node.overIndex !== null && node.overIndex < node.imgs.length) {
return node.imgs[node.overIndex].src;
}
return null;
}
function _initiateFullscreen(Element) {
if (Element.requestFullscreen) {
return Element.requestFullscreen();
} else if (Element.mozRequestFullScreen) {
return Element.mozRequestFullScreen();
} else if (Element.webkitRequestFullscreen) {
return Element.webkitRequestFullscreen();
} else if (Element.msRequestFullscreen) {
return Element.msRequestFullscreen();
}
}
function _applyTranslation(Element, Index, List) {
let translationConst = (Index / (List.length - 1)) * 100;
translationConst = translationConst - (0.5 / (List.length - 1)) * 100
if (Index === 0) { translationConst = 0; }
Element.style.transform = 'translateX(-' + translationConst + '%)';
}
function _handleArrowKeys(e) {
e.stopPropagation();
const FullscreenWrapper = document.getElementById(FULLSCREEN_WRAPPER_ID);
const imagePreviewsWrapper = document.getElementById(IMAGE_PREVIEWS_WRAPPER_ID);
const imageList = ttN_srcDict[ttN_FullscreenNode.id] || [];
const comfyMenu = document.getElementsByClassName("comfy-menu")[0]
const litegraph = document.getElementsByClassName("litegraph")[0]
switch (e.code) {
case 'ArrowLeft':
if (e.ctrlKey) {
ttN_FullscreenImageIndex = 0;
break;
}
if (e.shiftKey) {
ttN_FullscreenImageIndex -= 5;
if (ttN_FullscreenImageIndex < 0) ttN_FullscreenImageIndex = 0
break;
}
ttN_FullscreenImageIndex -= 1;
if (ttN_FullscreenImageIndex < 0) ttN_FullscreenImageIndex = 0
break;
case 'ArrowRight':
if (e.ctrlKey) {
ttN_FullscreenImageIndex = imageList.length - 1;
break;
}
if (e.shiftKey) {
ttN_FullscreenImageIndex += 5;
if (ttN_FullscreenImageIndex > imageList.length - 1) ttN_FullscreenImageIndex = imageList.length - 1
break;
}
ttN_FullscreenImageIndex += 1;
if (ttN_FullscreenImageIndex > imageList.length - 1) ttN_FullscreenImageIndex = imageList.length - 1
break;
case 'ArrowUp':
if (imagePreviewsWrapper) {
if (imagePreviewsWrapper.style.display === 'none') {
FullscreenWrapper.append(comfyMenu)
imagePreviewsWrapper.style.display = 'flex'
} else {
litegraph.append(comfyMenu)
imagePreviewsWrapper.style.display = 'none'
}
}
break;
case 'ArrowDown':
ttN_Slideshow = !ttN_Slideshow;
if (ttN_Slideshow) {
ttN_FullscreenImageIndex = -1;
imagePreviewsWrapper.style.display = 'none'
litegraph.append(comfyMenu)
} else {
imagePreviewsWrapper.style.display = 'flex'
FullscreenWrapper.append(comfyMenu)
}
break;
}
_applyTranslation(imagePreviewsWrapper, ttN_FullscreenImageIndex, imageList);
updateImageElements()
}
function _handleWheelEvent(e) {
e.stopPropagation();
var InvertMenuScrolling = localStorage.getItem('Comfy.Settings.Comfy.InvertMenuScrolling')
console.log("InvertMenuScrolling", InvertMenuScrolling)
if (InvertMenuScrolling === "true") {
console.log('yes')
if (e.deltaY > 0) {
// Scrolling down
ttN_FullscreenImageIndex += 1;
} else if (e.deltaY < 0) {
// Scrolling up
ttN_FullscreenImageIndex -= 1;
if (ttN_FullscreenImageIndex < 0) ttN_FullscreenImageIndex = 0;
}
} else {
console.log('no')
if (e.deltaY < 0) {
// Scrolling down
ttN_FullscreenImageIndex += 1;
} else if (e.deltaY > 0) {
// Scrolling up
ttN_FullscreenImageIndex -= 1;
if (ttN_FullscreenImageIndex < 0) ttN_FullscreenImageIndex = 0;
}
}
updateImageElements()
}
function _handleEscapeKey(e) {
e.stopPropagation();
LGraphCanvas.prototype.ttNcloseFullscreen();
}
function _handleExecutedEvent(event) {
setTimeout(updateImageTLDE, 500);
}
function _handleReconnectingEvent(e) {
clearSrcDict();
sessionStorage.removeItem('Comfy.Settings.ttN.default_fullscreen_node');
ttN_imageElementsDict = {};
}
function _triggerFullscreen(node) {
updateImageTLDE();
ttN_FullscreenImageIndex = -1;
LGraphCanvas.prototype.ttNcreateFullscreen(node);
ttN_FullscreenNode = node;
}
function ttNfullscreenEventListener(e) {
if (!ttN_isFullscreen) {
if ((e.code === 'ArrowUp' && e.shiftKey) && !e.ctrlKey) {
e.stopPropagation();
let selected_node = _getSelectedNode();
if (selected_node) {
_triggerFullscreen(selected_node);
return
}
let defaultNodeID = JSON.parse(sessionStorage.getItem('Comfy.Settings.ttN.default_fullscreen_node'));
if (defaultNodeID) {
let defaultNode = app.graph._nodes_by_id[defaultNodeID];
if (defaultNode) {
_triggerFullscreen(defaultNode);
return
}
}
}
return;
}
e.stopPropagation();
updateImageTLDE();
const imagePreviewsWrapper = document.getElementById(IMAGE_PREVIEWS_WRAPPER_ID);
const imageList = ttN_srcDict[ttN_FullscreenNode.id] || [];
switch (e.type) {
case 'wheel':
_handleWheelEvent(e);
_applyTranslation(imagePreviewsWrapper, ttN_FullscreenImageIndex, imageList);
break;
case 'keydown':
if (ARROW_KEYS.includes(e.code)) {
_handleArrowKeys(e);
_applyTranslation(imagePreviewsWrapper, ttN_FullscreenImageIndex, imageList);
} else if (e.code === 'Escape') {
_handleEscapeKey(e);
_applyTranslation(imagePreviewsWrapper, ttN_FullscreenImageIndex, imageList);
}
break;
}
}
function updateImageTLDE() {
for (let node of app.graph._nodes) {
if (!node.imgs) continue
let imgSrc = _findFullImageSRC(node);
if (!imgSrc) continue;
_removeLatentPreviewImageSRC(node, imgSrc)
ttN_srcDict[node.id] = ttN_srcDict[node.id] || [];
let index = ttN_srcDict[node.id].length;
if (!ttN_srcDict[node.id].includes((index, imgSrc))) {
ttN_srcDict[node.id].push((index, imgSrc));
if (ttN_Slideshow) {
updateImageElements(index);
}
}
}
saveSrcDict();
updateImageElements();
};
function _getImageDivFromSrc(imgSrc, index) {
// If image element doesn't exist, create it
if (!ttN_imageElementsDict[imgSrc]) {
const imgWrapper = document.createElement('div');
imgWrapper.classList.add('ttN-imgWrapper');
const imgElement = document.createElement('img');
imgElement.src = imgSrc;
imgElement.classList.add('ttN-img');
imgWrapper.appendChild(imgElement);
imgElement.addEventListener('click', () => {
ttN_FullscreenImageIndex = index;
updateImageElements(index);
});
ttN_imageElementsDict[imgSrc] = imgWrapper;
}
return ttN_imageElementsDict[imgSrc];
}
function _removeLatentPreviewImageSRC(node, imgSrc) {
let latentPreviewSrc = _findLatentPreviewImageSRC(node);
if (imgSrc && latentPreviewSrc) {
for (let i in node.imgs) {
if(!node.imgs[i].src.includes("filename")) {
node.imgs.splice(i, 1);
}
}
}
}
function _handleLatentPreview(imgDivList) {
let latentPreview = _findLatentPreviewImageSRC(ttN_FullscreenNode);
if (latentPreview && !latentPreview.includes("filename") && ttN_FullscreenImageIndex === imgDivList.length - 1) {
ttN_FullscreenImage.src = latentPreview
}
}
function updateImageElements(indexOverride = null) {
if (!ttN_isFullscreen) return;
const srcList = ttN_srcDict[ttN_FullscreenNode.id] || null;
if (!srcList) return;
const fullscreenWrapper = document.getElementById(FULLSCREEN_WRAPPER_ID);
if (!fullscreenWrapper) return
const imgDivList = srcList.map((src, index) => _getImageDivFromSrc(src, index));
ttN_FullscreenImageIndex = indexOverride || ttN_FullscreenImageIndex
if ((ttN_FullscreenImageIndex > imgDivList.length - 1) || (ttN_FullscreenImageIndex === -1)) {
ttN_FullscreenImageIndex = imgDivList.length - 1
}
if (ttN_FullscreenImageIndex < -1) ttN_FullscreenImageIndex = 0
ttN_FullscreenImage.src = imgDivList[ttN_FullscreenImageIndex].children[0].src;
const previewsWrapper = document.getElementById(IMAGE_PREVIEWS_WRAPPER_ID);
if (!previewsWrapper) return
if (ttN_Slideshow) {
fullscreenWrapper.classList.add('ttN-slideshow')
_handleLatentPreview(imgDivList);
} else {
fullscreenWrapper.classList.remove('ttN-slideshow')
}
if (ttN_FullscreenImageIndex > imgDivList.length - 1) ttN_FullscreenImageIndex = imgDivList.length - 1;
if (ttN_FullscreenImageIndex < 0) ttN_FullscreenImageIndex = 0;
imgDivList.forEach((imgDiv, index) => {
if (previewsWrapper.children[index] != imgDiv) previewsWrapper.appendChild(imgDiv);
const orderValue = index - ttN_FullscreenImageIndex;
imgDiv.style.order = orderValue;
if (index < ttN_FullscreenImageIndex) {
// For images before the selected image
imgDiv.classList.remove('ttN-divSelected', 'ttN-divAfter');
imgDiv.children[0].classList.remove('ttN-imgSelected', 'ttN-imgAfter');
imgDiv.classList.add('ttN-divBefore');
//imgDiv.children[0].classList.add('ttN-imgBefore');
}
else if (index === ttN_FullscreenImageIndex) {
// For the selected image
imgDiv.classList.remove('ttN-divBefore', 'ttN-divAfter');
imgDiv.children[0].classList.remove('ttN-imgBefore', 'ttN-imgAfter');
imgDiv.classList.add('ttN-divSelected');
imgDiv.children[0].classList.add('ttN-imgSelected');
}
else if (index > ttN_FullscreenImageIndex) {
// For images after the selected image
imgDiv.classList.remove('ttN-divSelected', 'ttN-divBefore');
imgDiv.children[0].classList.remove('ttN-imgSelected', 'ttN-imgBefore');
imgDiv.classList.add('ttN-divAfter');
//imgDiv.children[0].classList.add('ttN-imgAfter');
}
});
_applyTranslation(previewsWrapper, ttN_FullscreenImageIndex, imgDivList);
}
api.addEventListener("status", _handleExecutedEvent);
api.addEventListener("progress", _handleExecutedEvent);
api.addEventListener("execution_cached", _handleExecutedEvent);
api.addEventListener("reconnecting", _handleReconnectingEvent);
app.registerExtension({
name: "comfy.ttN.fullscreen",
init() {
document.addEventListener("keydown", ttNfullscreenEventListener, true);
},
setup() {
LGraphCanvas.prototype.ttNcreateFullscreen = function (node) {
if (!node || ttN_isFullscreen) return;
document.addEventListener("wheel", ttNfullscreenEventListener, true);
const fullscreenWrapper = document.createElement('div');
fullscreenWrapper.id = FULLSCREEN_WRAPPER_ID;
fullscreenWrapper.classList.add('ttN-slideshow');
document.body.appendChild(fullscreenWrapper);
const fullscreenImage = new Image();
fullscreenImage.src = _findFullImageSRC(node) || _findLatentPreviewImageSRC(node) || '';
fullscreenImage.id = FULLSCREEN_IMAGE_ID;
fullscreenWrapper.appendChild(fullscreenImage);
const previewsWrapper = document.createElement('div');
previewsWrapper.id = IMAGE_PREVIEWS_WRAPPER_ID;
previewsWrapper.style.display = 'none';
fullscreenWrapper.appendChild(previewsWrapper);
_initiateFullscreen(fullscreenWrapper).then(() => {
ttN_isFullscreen = true;
ttN_FullscreenImage = fullscreenImage;
updateImageElements();
}).catch(err => {
console.error("Error attempting to enable full-screen mode:", err.message, err.name);
});
fullscreenWrapper.onfullscreenchange = function (event) {
if (!document.fullscreenElement) {
LGraphCanvas.prototype.ttNcloseFullscreen();
}
};
}
LGraphCanvas.prototype.ttNcloseFullscreen = function () {
if (!ttN_isFullscreen) return;
const comfyMenu = document.getElementsByClassName("comfy-menu")[0]
const litegraph = document.getElementsByClassName("litegraph")[0]
litegraph.append(comfyMenu);
const fullscreenWrapper = document.getElementById(FULLSCREEN_WRAPPER_ID);
document.body.removeChild(fullscreenWrapper);
document.removeEventListener("wheel", ttNfullscreenEventListener, true);
ttN_isFullscreen = false;
}
const getNodeMenuOptions = LGraphCanvas.prototype.getNodeMenuOptions;
LGraphCanvas.prototype.getNodeMenuOptions = function (node) {
const options = getNodeMenuOptions.apply(this, arguments);
node.setDirtyCanvas(true, true);
options.splice(options.length - 1, 0,
{
content: "Fullscreen (ttN)",
callback: () => { LGraphCanvas.prototype.ttNcreateFullscreen(node) }
},
{
content: "Set Default Fullscreen Node (ttN)",
callback: function () {
let selectedNode = _getSelectedNode();
if (selectedNode) {
sessionStorage.setItem('Comfy.Settings.ttN.default_fullscreen_node', JSON.stringify(selectedNode.id));
}
}
},
{
content: "Clear Default Fullscreen Node (ttN)",
callback: function () {
sessionStorage.removeItem('Comfy.Settings.ttN.default_fullscreen_node');
}
},
null
);
return options;
};
}
});
var styleElement = document.createElement("style");
const cssCode = `
#ttN-FullscreenWrapper {
display: flex;
justify-content: center;
align-items: end;
background-color: #1f1f1f;
}
#ttN-FullscreenImage {
height: inherit;
position: absolute;
}
#ttN-imagePreviewsWrapper {
position: absolute;
width: max-content;
z-index: 1;
height: 14vh;
left: 50vw;
transition: transform 0.2s ease;
}
.ttN-imgWrapper {
position: sticky;
transition: transform 0.2s ease;
align-self: end;
}
.ttN-img {
height: 121px;
margin: 7px;
cursor: pointer;
display: block;
border: 3px solid rgba(255,255,255);
box-shadow: 0px 0px 0px 10px;
transition: all 0.4s ease;
}
.ttN-img:hover {
transform: scale(1.1);
z-index: 1;
}
.ttN-imgSelected {
height: 200px!important;
z-index: 1;
transition: 0.1s;
}
.ttN-slideshow {
background: black!important;
}
`;
styleElement.innerHTML = cssCode
document.head.appendChild(styleElement);