3v324v23's picture
lfs
1e3b872
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js";
import { ttN_CreateDropdown, ttN_RemoveDropdown } from "./ttNdropdown.js";
//GLOBAL CONSTANTS
const FULLSCREEN_WRAPPER_ID = "ttN-FullscreenWrapper";
const FULLSCREEN_IMAGE_ID = "ttN-FullscreenImage";
const IMAGE_PREVIEWS_WRAPPER_ID = "ttN-imagePreviewsWrapper";
//GLOBAL OPTS
let TTN_AUTOHIDE = JSON.parse(localStorage.getItem('Comfy.Settings.ttN.FullscreenAutohideToggle')) ?? true;
let TTN_INVERTCTRL = JSON.parse(localStorage.getItem('Comfy.Settings.ttN.FullscreenInvertCtrl')) ?? false;
let TTN_SLIDESHOWMODE = true;
//GLOBAL ELEMENTS
const TTN_LITEGRAPH = document.getElementsByClassName("litegraph")[0];
const TTN_COMFYMENU = document.getElementsByClassName("comfy-menu")[0];
const TTN_COMFYHAMBURGER = document.getElementsByClassName("comfy-menu-hamburger")[0];
let TTN_FULLSCREEN_WRAPPER;
let TTN_FULLSCREEN_IMAGE = new Image();
let TTN_PREVIEWS_WRAPPER;
//GLOBAL VARS
let TTN_isFullscreen = false;
let TTN_isDraggingImage = false;
let TTN_offsetX, TTN_offsetY;
let TTN_FS_ImageIndex = -1;
let TTN_FullscreenNode = null;
let TTN_ImageScale = 1;
let TTN_COMPARE1_INDEX;
let TTN_COMPARE2_INDEX;
let TTN_CompareFromImage = null;
let TTN_CompareToImage = null;
let TTN_Comparing = false;
let hideUI_Timeout;
let ttN_srcDict = {};
let ttN_imageElementsDict = {};
//COMFY SPECIFIC
loadSrcDict()
function _stealComfyMenu() {
if (TTN_FULLSCREEN_WRAPPER && TTN_COMFYMENU && TTN_COMFYHAMBURGER) {
TTN_FULLSCREEN_WRAPPER.append(TTN_COMFYMENU)
TTN_FULLSCREEN_WRAPPER.append(TTN_COMFYHAMBURGER)
}
}
function _replaceComfyMenu() {
TTN_LITEGRAPH.append(TTN_COMFYMENU)
TTN_LITEGRAPH.append(TTN_COMFYHAMBURGER)
}
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;
}
export function _setDefaultFullscreenNode() {
let selectedNode = _getSelectedNode();
if (selectedNode) {
sessionStorage.setItem('Comfy.Settings.ttN.default_fullscreen_node', JSON.stringify(selectedNode.id));
} else {
sessionStorage.removeItem('Comfy.Settings.ttN.default_fullscreen_node');
}
}
function clearSrcDict() {
ttN_srcDict = {};
sessionStorage.removeItem('ttN_srcDict');
}
//get the src list
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 _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_FS_ImageIndex === imgDivList.length - 1) {
TTN_FULLSCREEN_IMAGE.src = latentPreview
}
}
function clearCompareImages() {
if (!TTN_Comparing) return;
TTN_CompareToImage?.classList.remove('ttN-compare-to')
TTN_CompareFromImage?.classList.remove('ttN-compare-from')
TTN_CompareFromImage = null
TTN_CompareToImage = null
TTN_Comparing = false
}
function addPreviewImageDropdown(imgElement) {
let suggestions = ['Load Prompt from Image', 'Select for Compare']
imgElement.addEventListener('contextmenu', (e) => {
e.preventDefault();
if (TTN_CompareFromImage && !suggestions.includes('Compare With Selected')) {
suggestions.push('Compare With Selected')
} else if (!TTN_CompareFromImage && suggestions.includes('Compare With Selected')) {
suggestions.splice(suggestions.indexOf('Compare With Selected'), 1)
}
if (TTN_Comparing && !suggestions.includes('Clear Compare')) {
suggestions.push('Clear Compare')
} else if (!TTN_Comparing && suggestions.includes('Clear Compare')) {
suggestions.splice(suggestions.indexOf('Clear Compare'), 1)
}
const manualOffset = ['80%', '70%'];
ttN_CreateDropdown(imgElement, suggestions, async (s) => {
if (s === 'Load Prompt from Image') {
imgElement.classList.add('ttN-loadToGraph')
app.handleFile(await (await fetch(imgElement.src)).blob())
setTimeout(() => {
imgElement.classList.remove('ttN-loadToGraph')
}, 350)
}
if (s === 'Delete Image') {
console.log("Delete Image")
}
if (s === 'Select for Compare') {
if (TTN_CompareFromImage) {
TTN_CompareFromImage.classList.remove('ttN-compare-from')
}
imgElement.classList.add('ttN-compare-from')
TTN_CompareFromImage = imgElement
TTN_COMPARE1_INDEX = imgElement.index
}
if (s === 'Compare With Selected') {
if (!TTN_CompareFromImage) {
return;
}
if (TTN_CompareToImage) {
TTN_CompareToImage.classList.remove('ttN-compare-to')
}
imgElement.classList.add('ttN-compare-to')
TTN_CompareToImage = imgElement
TTN_COMPARE2_INDEX = imgElement.index
TTN_Comparing = true
_setCurrentImageIndex(TTN_COMPARE2_INDEX)
}
if (s === 'Clear Compare') {
clearCompareImages()
}
}, false, manualOffset, TTN_FULLSCREEN_WRAPPER);
});
}
function _createImageDivFromSrc(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.index = index;
imgElement.classList.add('ttN-img');
imgWrapper.appendChild(imgElement);
imgElement.addEventListener('click', () => {
_setCurrentImageIndex(index);
});
// right click
addPreviewImageDropdown(imgElement);
ttN_imageElementsDict[imgSrc] = imgWrapper;
}
return ttN_imageElementsDict[imgSrc];
}
function updateImageElements(indexOverride = null) {
if (!TTN_isFullscreen) return;
const srcList = ttN_srcDict[TTN_FullscreenNode.id] || null;
if (!srcList) return;
if (!TTN_FULLSCREEN_WRAPPER) return
const imgDivList = srcList.map((src, index) => _createImageDivFromSrc(src, index));
TTN_FS_ImageIndex = indexOverride || TTN_FS_ImageIndex
if ((TTN_FS_ImageIndex > imgDivList.length - 1) || (TTN_FS_ImageIndex === -1)) {
TTN_FS_ImageIndex = imgDivList.length - 1
}
if (TTN_FS_ImageIndex < -1) TTN_FS_ImageIndex = 0
TTN_FULLSCREEN_IMAGE.src = imgDivList[TTN_FS_ImageIndex].children[0].src;
if (!TTN_PREVIEWS_WRAPPER) return
if (TTN_SLIDESHOWMODE) {
TTN_FULLSCREEN_WRAPPER.classList.add('ttN-slideshow')
_handleLatentPreview(imgDivList);
} else {
TTN_FULLSCREEN_WRAPPER.classList.remove('ttN-slideshow')
}
if (TTN_FS_ImageIndex > imgDivList.length - 1) TTN_FS_ImageIndex = imgDivList.length - 1;
if (TTN_FS_ImageIndex < 0) TTN_FS_ImageIndex = 0;
imgDivList.forEach((imgDiv, index) => {
if (TTN_PREVIEWS_WRAPPER.children[index] != imgDiv) TTN_PREVIEWS_WRAPPER.appendChild(imgDiv);
const orderValue = index - TTN_FS_ImageIndex;
imgDiv.style.order = orderValue;
if (index < TTN_FS_ImageIndex) {
// 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_FS_ImageIndex) {
// 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_FS_ImageIndex) {
// 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(TTN_PREVIEWS_WRAPPER, TTN_FS_ImageIndex, imgDivList);
}
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_SLIDESHOWMODE) {
updateImageElements(index);
}
}
}
saveSrcDict();
updateImageElements();
};
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 removeDictEntry(node_id, index) {
delete ttN_srcDict[node_id][index];
//TODO
}
function _appendFullscreenMenuButtons() {
const ttN_hr = document.createElement('hr');
ttN_hr.style.margin = '20px 0px';
ttN_hr.style.width = '100%';
ttN_hr.classList.add('ttN-hr');
if (TTN_COMFYMENU) {
TTN_COMFYMENU.appendChild(ttN_hr);
}
// Toggle hover auto-hide button
const toggleHoverButton = document.createElement('button');
toggleHoverButton.innerHTML = 'Toggle Hover Auto-hide';
toggleHoverButton.classList.add('ttN-toggle-hover-button');
if (TTN_AUTOHIDE == true) {
toggleHoverButton.classList.add('ttN-true');
}
toggleHoverButton.addEventListener('click', function() {
if (TTN_AUTOHIDE == true) {
localStorage.setItem('Comfy.Settings.ttN.FullscreenAutohideToggle', 'false');
TTN_AUTOHIDE = false;
toggleHoverButton.classList.remove('ttN-true');
__reset_hideUI_Timeout();
} else {
localStorage.setItem('Comfy.Settings.ttN.FullscreenAutohideToggle', 'true');
TTN_AUTOHIDE = true;
toggleHoverButton.classList.add('ttN-true');
__reset_hideUI_Timeout();
}
});
if (TTN_COMFYMENU) {
TTN_COMFYMENU.appendChild(toggleHoverButton);
}
// Toggle slideshow mode button
const toggleSlideshowButton = document.createElement('button');
toggleSlideshowButton.innerHTML = 'Toggle Slideshow Mode';
toggleSlideshowButton.classList.add('ttN-slideshow-button');
if (TTN_SLIDESHOWMODE) {
toggleSlideshowButton.classList.add('ttN-true');
}
toggleSlideshowButton.addEventListener('click', function() {
TTN_SLIDESHOWMODE = !TTN_SLIDESHOWMODE;
if (TTN_SLIDESHOWMODE) {
toggleSlideshowButton.classList.add('ttN-true');
TTN_FULLSCREEN_WRAPPER.classList.add('ttN-slideshow')
} else {
toggleSlideshowButton.classList.remove('ttN-true');
TTN_FULLSCREEN_WRAPPER.classList.remove('ttN-slideshow')
}
});
if (TTN_COMFYMENU) {
TTN_COMFYMENU.appendChild(toggleSlideshowButton);
}
// Invert Ctrl button
const invertCtrlButton = document.createElement('button');
invertCtrlButton.classList.add('ttN-invert-ctrl-button');
if (TTN_INVERTCTRL == true) {
invertCtrlButton.classList.add('ttN-true');
invertCtrlButton.innerHTML = 'Ctrl+Wheel: Scroll Images';
} else {
invertCtrlButton.classList.remove('ttN-true');
invertCtrlButton.innerHTML = 'Ctrl+Wheel: Zoom';
}
invertCtrlButton.addEventListener('click', function() {
if (TTN_INVERTCTRL == true) {
localStorage.setItem('Comfy.Settings.ttN.FullscreenInvertCtrl', 'false')
invertCtrlButton.classList.remove('ttN-true');
TTN_INVERTCTRL = false
invertCtrlButton.innerHTML = 'Ctrl+Wheel: Zoom';
} else {
localStorage.setItem('Comfy.Settings.ttN.FullscreenInvertCtrl', 'true')
invertCtrlButton.classList.add('ttN-true');
TTN_INVERTCTRL = true
invertCtrlButton.innerHTML = 'Ctrl+Wheel: Scroll Images';
}
});
if (TTN_COMFYMENU) {
TTN_COMFYMENU.appendChild(invertCtrlButton);
}
}
function _removeFullscreenMenuButtons() {
const ttN_hr = document.querySelector('.ttN-hr');
if (ttN_hr) {
ttN_hr.remove();
}
const toggleHoverButton = document.querySelector('.ttN-toggle-hover-button');
if (toggleHoverButton) {
toggleHoverButton.remove();
}
const toggleSlideshowButton = document.querySelector('.ttN-slideshow-button');
if (toggleSlideshowButton) {
toggleSlideshowButton.remove();
}
const invertCtrlButton = document.querySelector('.ttN-invert-ctrl-button');
if (invertCtrlButton) {
invertCtrlButton.remove();
}
}
//EVENT LISTENERS
function enable_document_listeners(toggle=true) {
document.removeEventListener("keydown", _handleKeyPress_doc, true);
if (toggle==true) {
document.addEventListener("keydown", _handleKeyPress_doc, true);
}
}
function enable_api_listeners(toggle=true) {
api.removeEventListener("status", _handleExecutedEvent);
api.removeEventListener("progress", _handleExecutedEvent);
api.removeEventListener("execution_cached", _handleExecutedEvent);
api.removeEventListener("reconnecting", _handleReconnectingEvent);
if (toggle==true) {
api.addEventListener("status", _handleExecutedEvent);
api.addEventListener("progress", _handleExecutedEvent);
api.addEventListener("execution_cached", _handleExecutedEvent);
api.addEventListener("reconnecting", _handleReconnectingEvent);
}
}
function enable_wrapper_listeners(toggle=true) {
TTN_FULLSCREEN_WRAPPER.removeEventListener("wheel", _handleMouse);
TTN_FULLSCREEN_WRAPPER.removeEventListener('mousemove', _handleMouse);
TTN_FULLSCREEN_WRAPPER.removeEventListener('mousedown', _handleMouse);
TTN_FULLSCREEN_WRAPPER.removeEventListener('mouseup', _handleMouse);
TTN_FULLSCREEN_WRAPPER.removeEventListener('click', _handleMouse);
TTN_FULLSCREEN_WRAPPER.removeEventListener('dblclick', _handleMouse);
if (toggle==true) {
TTN_FULLSCREEN_WRAPPER.addEventListener("wheel", _handleMouse);
TTN_FULLSCREEN_WRAPPER.addEventListener('mousemove', _handleMouse);
TTN_FULLSCREEN_WRAPPER.addEventListener('mousedown', _handleMouse);
TTN_FULLSCREEN_WRAPPER.addEventListener('mouseup', _handleMouse);
TTN_FULLSCREEN_WRAPPER.addEventListener('click', _handleMouse);
TTN_FULLSCREEN_WRAPPER.addEventListener('dblclick', _handleMouse);
}
}
//EVENT HANDLERS
function _handleKeyPress_doc(e) {
if (TTN_isFullscreen) {
const imageList = ttN_srcDict[TTN_FullscreenNode.id] || []; //TODO: ADD IMAGE LIST
switch (e.code) {
case 'ArrowLeft':
e.preventDefault();
if (TTN_Comparing) {
_setCurrentImageIndex(Math.min(TTN_COMPARE1_INDEX, TTN_COMPARE2_INDEX))
break;
}
if (e.ctrlKey) {
_setCurrentImageIndex(0);
break;
}
if (e.shiftKey) {
_setCurrentImageIndex(5, "-");
if (TTN_FS_ImageIndex < 0) _setCurrentImageIndex(0);
break;
}
if (TTN_FS_ImageIndex == 0) {
_setCurrentImageIndex(0);
} else {
_setCurrentImageIndex(1, "-");
}
__reset_hideUI_Timeout();
break;
case 'ArrowRight':
e.preventDefault();
if (TTN_Comparing) {
_setCurrentImageIndex(Math.max(TTN_COMPARE1_INDEX, TTN_COMPARE2_INDEX))
break;
}
if (e.ctrlKey) {
_setCurrentImageIndex(-1);
break;
}
if (e.shiftKey) {
_setCurrentImageIndex(5, "+");
if (TTN_FS_ImageIndex > imageList.length - 1) _setCurrentImageIndex(-1);
break;
}
_setCurrentImageIndex(1, "+");
if (TTN_FS_ImageIndex > imageList.length - 1) _setCurrentImageIndex(-1);
__reset_hideUI_Timeout();
break;
case 'ArrowUp':
e.preventDefault();
__toggleUI();
break;
case 'ArrowDown':
e.preventDefault();
TTN_SLIDESHOWMODE = !TTN_SLIDESHOWMODE;
if (TTN_SLIDESHOWMODE) {
__hideUI();
_setCurrentImageIndex(-1);
} else {
__showUI();
}
break;
case 'Escape':
case 'F11':
e.preventDefault();
closeFullscreenApp();
return;
}
updateImageElements();
_applyTranslation(TTN_PREVIEWS_WRAPPER, TTN_FS_ImageIndex, imageList);
return;
};
if ((e.code === 'F11' && e.shiftKey) && !e.ctrlKey) {
let selected_node = _getSelectedNode();
if (selected_node) {
openFullscreenApp(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) {
TTN_SLIDESHOWMODE = true
openFullscreenApp(defaultNode);
return
}
}
}
if ((e.code === 'ArrowDown' && e.shiftKey) && !e.ctrlKey) {
setDefaultNode();
}
return
}
function _handleExecutedEvent(e) {
setTimeout(updateImageTLDE, 500);
setTimeout(updateImageTLDE, 1000);
}
function _handleReconnectingEvent(e) {
clearSrcDict();
sessionStorage.removeItem('Comfy.Settings.ttN.default_fullscreen_node');
ttN_imageElementsDict = {};
}
function _handleWheelEvent(e) {
const isMouseOverPreviewWrapper = _isMouseOverElement(TTN_PREVIEWS_WRAPPER, e.clientX, e.clientY);
const invertMenuScrolling = localStorage.getItem('Comfy.Settings.Comfy.InvertMenuScrolling') === "true";
const deltaYSign = e.deltaY > 0 ? 1 : -1;
const zoomDirection = invertMenuScrolling ? deltaYSign === -1 ? "+" : "-" : deltaYSign === 1 ? "+" : "-";
const scrollDirection = invertMenuScrolling ? deltaYSign === -1 ? "-" : "+" : deltaYSign === 1 ? "-" : "+";
e.preventDefault();
if (((TTN_INVERTCTRL && !e.ctrlKey) || (e.ctrlKey && !TTN_INVERTCTRL)) && !isMouseOverPreviewWrapper) {
// SCALE IMAGE
_scrollScaleImage(e, TTN_FULLSCREEN_IMAGE, zoomDirection);
}
if ((!TTN_INVERTCTRL && !e.ctrlKey) || (e.ctrlKey && TTN_INVERTCTRL) || isMouseOverPreviewWrapper) {
//SCROLL PREVIEWS
if (scrollDirection === "-" && TTN_FS_ImageIndex <= 0) return;
if (TTN_Comparing && scrollDirection === "-") {
_setCurrentImageIndex(Math.min(TTN_COMPARE1_INDEX, TTN_COMPARE2_INDEX))
} else if (TTN_Comparing && scrollDirection === "+") {
_setCurrentImageIndex(Math.max(TTN_COMPARE1_INDEX, TTN_COMPARE2_INDEX))
} else {
_setCurrentImageIndex(1, scrollDirection);
}
if (TTN_FS_ImageIndex < 0) _setCurrentImageIndex(0);
}
const imageList = ttN_srcDict[TTN_FullscreenNode.id] || [];
_applyTranslation(TTN_PREVIEWS_WRAPPER, TTN_FS_ImageIndex, imageList);
}
function _handleMouse(e) {
const isMouseOverPreviewWrapper = _isMouseOverElement(TTN_PREVIEWS_WRAPPER, e.clientX, e.clientY);
const isMouseOverMenu = _isMouseOverElement(TTN_COMFYMENU, e.clientX, e.clientY) || _isMouseOverElement(TTN_COMFYHAMBURGER, e.clientX, e.clientY);
const isMouseOverImage = _isMouseOverElement(TTN_FULLSCREEN_IMAGE, e.clientX, e.clientY);
switch (e.type) {
case "wheel":
_handleWheelEvent(e);
break;
case "mousedown":
if (!isMouseOverMenu && !isMouseOverPreviewWrapper) {
e.preventDefault();
TTN_isDraggingImage = true
TTN_offsetX = TTN_FULLSCREEN_IMAGE.offsetLeft - e.clientX;
TTN_offsetY = TTN_FULLSCREEN_IMAGE.offsetTop - e.clientY;
}
break;
case "mouseup":
TTN_isDraggingImage = false
break;
case "click":
if (!isMouseOverMenu && !isMouseOverPreviewWrapper && TTN_SLIDESHOWMODE) {
__hideUI();
}
break;
case "dblclick":
if (!isMouseOverMenu && !isMouseOverPreviewWrapper) {
e.preventDefault();
e.stopPropagation();
TTN_FULLSCREEN_IMAGE.style.left = "";
TTN_FULLSCREEN_IMAGE.style.top = "";
_setCurrentImageScale(TTN_FULLSCREEN_IMAGE, 1);
}
break;
case "mousemove":
if (TTN_SLIDESHOWMODE) {
if (isMouseOverPreviewWrapper || isMouseOverMenu) {
__showUI();
__reset_hideUI_Timeout(7000);
}
}
if (TTN_isDraggingImage) {
TTN_FULLSCREEN_IMAGE.style.left = (e.clientX + TTN_offsetX) + 'px';
TTN_FULLSCREEN_IMAGE.style.top = (e.clientY + TTN_offsetY) + 'px';
}
break;
}
}
//UI FUNCTIONS
function createElement(tagName, attributes = {}, parentElement = document.body) {
if (attributes.id && document.getElementById(attributes.id)) {
return document.getElementById(attributes.id);
}
const element = document.createElement(tagName);
Object.entries(attributes).forEach(([key, value]) => {
element.setAttribute(key, value);
});
parentElement.appendChild(element);
return element;
}
function _createFullscreenBody() {
TTN_FULLSCREEN_WRAPPER = createElement("div", { id: FULLSCREEN_WRAPPER_ID, class: 'ttN-slideshow' });
TTN_FULLSCREEN_WRAPPER.onfullscreenchange = function (event) {
if (!document.fullscreenElement) {
closeFullscreenApp();
}
};
TTN_PREVIEWS_WRAPPER = createElement("div", { id: IMAGE_PREVIEWS_WRAPPER_ID }, TTN_FULLSCREEN_WRAPPER);
TTN_FULLSCREEN_IMAGE.src = _findFullImageSRC(TTN_FullscreenNode) || _findLatentPreviewImageSRC(TTN_FullscreenNode) || '';
TTN_FULLSCREEN_IMAGE.id = FULLSCREEN_IMAGE_ID;
TTN_FULLSCREEN_WRAPPER.appendChild(TTN_FULLSCREEN_IMAGE);
}
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();
}
}
export function openFullscreenApp(node) {
if (TTN_isFullscreen) return
TTN_FullscreenNode = node;
_createFullscreenBody();
enable_wrapper_listeners();
_stealComfyMenu();
_appendFullscreenMenuButtons();
__hideUI();
TTN_FULLSCREEN_IMAGE.style.left = "";
TTN_FULLSCREEN_IMAGE.style.top = "";
_setCurrentImageScale(TTN_FULLSCREEN_IMAGE, 1);
TTN_FS_ImageIndex = -1;
clearCompareImages();
_initiateFullscreen(TTN_FULLSCREEN_WRAPPER);
TTN_isFullscreen = true;
updateImageTLDE();
}
function closeFullscreenApp() {
if (!TTN_isFullscreen) return
__showUI();
clearTimeout(hideUI_Timeout);
_replaceComfyMenu();
_removeFullscreenMenuButtons();
enable_wrapper_listeners(false);
document.body.removeChild(TTN_FULLSCREEN_WRAPPER);
TTN_isFullscreen = false;
}
function _scrollScaleImage(e, image, zoomDirection, partner=null) {
let scaleFactor = 0.14;
if (TTN_ImageScale > 1) scaleFactor = scaleFactor * 2
if (TTN_ImageScale > 3) scaleFactor = scaleFactor * 2
if (TTN_ImageScale > 5) scaleFactor = scaleFactor * 2
if (TTN_ImageScale > 7) scaleFactor = scaleFactor * 2
if (TTN_ImageScale < 0.14) scaleFactor = scaleFactor / 2
const rect = image.getBoundingClientRect();
// Step 1: Get the Mouse's Position Relative to the Image
const offsetX = e.clientX - rect.left;
const offsetY = e.clientY - rect.top;
const relativeX = offsetX / rect.width;
const relativeY = offsetY / rect.height;
// Step 2: Zoom
_setCurrentImageScale(image, scaleFactor, zoomDirection);
const newRect = image.getBoundingClientRect();
// Step 3: Adjust the Image's Position
const newX = e.clientX - relativeX * newRect.width;
const newY = e.clientY - relativeY * newRect.height;
image.style.left = (image.offsetLeft + newX - newRect.left) + 'px';
image.style.top = (image.offsetTop + newY - newRect.top) + 'px';
}
function _setCurrentImageScale(image, s, symbol=null) {
switch (symbol) {
case "+":
s = TTN_ImageScale + s;
break;
case "-":
s = TTN_ImageScale - s;
break;
}
if (s < 0.01) s = 0.01
if (s > 9) s = 9
// round s to 2 decimal places
s = Math.round(s * 100) / 100
TTN_ImageScale = s
image.style.transform = "scale(" + TTN_ImageScale + ")";
}
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 _isMouseOverElement(element, mouseX, mouseY) {
if (!element) return false;
const rect = element.getBoundingClientRect();
return (
mouseX >= rect.left &&
mouseX <= rect.right &&
mouseY >= rect.top &&
mouseY <= rect.bottom
);
}
function __hideUI() {
if (TTN_COMFYMENU) TTN_COMFYMENU.classList.add('hidden')
if (TTN_COMFYHAMBURGER) TTN_COMFYHAMBURGER.classList.add('hidden');
if (TTN_PREVIEWS_WRAPPER) TTN_PREVIEWS_WRAPPER.classList.add('hidden');
ttN_RemoveDropdown();
}
function __showUI() {
if(TTN_COMFYMENU) TTN_COMFYMENU.classList.remove('hidden')
if (TTN_COMFYHAMBURGER) TTN_COMFYHAMBURGER.classList.remove('hidden');
if (TTN_PREVIEWS_WRAPPER) TTN_PREVIEWS_WRAPPER.classList.remove('hidden');
__reset_hideUI_Timeout();
}
function __toggleUI() {
if (TTN_COMFYMENU) TTN_COMFYMENU.classList.toggle('hidden')
if (TTN_COMFYHAMBURGER) TTN_COMFYHAMBURGER.classList.toggle('hidden');
if (TTN_PREVIEWS_WRAPPER) TTN_PREVIEWS_WRAPPER.classList.toggle('hidden');
__reset_hideUI_Timeout();
}
function __reset_hideUI_Timeout(timeout=3700) {
clearTimeout(hideUI_Timeout);
hideUI_Timeout = setTimeout(() => {
if (TTN_SLIDESHOWMODE && TTN_AUTOHIDE) {
__hideUI();
}
}, timeout);
}
function _setCurrentImageIndex(i, symbol=null) {
switch (symbol) {
case null:
TTN_FS_ImageIndex = i;
break
case "+":
TTN_FS_ImageIndex += i;
break
case "-":
TTN_FS_ImageIndex -= i;
break
}
updateImageElements();
}
enable_document_listeners();
enable_api_listeners();
var styleElement = document.createElement("style");
const cssCode = `
.hidden {
transition: opacity 0.5s, visibility 0.5s, transform 0.2s ease!important;
opacity: 0!important;
visibility: hidden!important;
}
#ttN-FullscreenWrapper {
display: flex;
justify-content: center;
align-items: end;
background-color: #1f1f1f;
}
#ttN-FullscreenImage {
height: inherit;
position: absolute;
}
#ttN-Compare1Image, #ttN-Compare2Image {
object-fit: contain;
}
#ttN-imagePreviewsWrapper {
display: flex;
position: absolute;
width: max-content;
z-index: 10;
height: 14vh;
left: 50vw;
opacity: 1;
visibility: visible;
transition: transform 0.2s, visibility 0.2s ease;
}
#ttN-CompareWrapper {
display: flex;
position: absolute;
width: 100vw;
height: 100vh;
z-index: 1;
}
#ttN-Compare1, #ttN-Compare2 {
width: 50vw;
height: 100vh;
display: flex;
justify-content: center;
}
.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: 10;
}
.ttN-imgSelected {
height: 200px!important;
z-index: 10;
transition: 0.1s;
}
.ttN-slideshow {
background: black!important;
}
.ttN-true {
color: green!important;
}
.ttN-compare-from {
border: 7px solid cyan;
}
.ttN-compare-to {
border: 7px solid red;
}
.ttN-loadToGraph {
height: 0px!important;
transition: 0.2s ease-in-out;
}
`;
styleElement.innerHTML = cssCode
document.head.appendChild(styleElement);