|
|
import { app } from "../../scripts/app.js"; |
|
|
import { api } from "../../scripts/api.js"; |
|
|
import { ttN_CreateDropdown, ttN_RemoveDropdown } from "./ttNdropdown.js"; |
|
|
|
|
|
|
|
|
const FULLSCREEN_WRAPPER_ID = "ttN-FullscreenWrapper"; |
|
|
const FULLSCREEN_IMAGE_ID = "ttN-FullscreenImage"; |
|
|
const IMAGE_PREVIEWS_WRAPPER_ID = "ttN-imagePreviewsWrapper"; |
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
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 = {}; |
|
|
|
|
|
|
|
|
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'); |
|
|
} |
|
|
|
|
|
|
|
|
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 (!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); |
|
|
}); |
|
|
|
|
|
|
|
|
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) { |
|
|
|
|
|
imgDiv.classList.remove('ttN-divSelected', 'ttN-divAfter'); |
|
|
imgDiv.children[0].classList.remove('ttN-imgSelected', 'ttN-imgAfter'); |
|
|
|
|
|
imgDiv.classList.add('ttN-divBefore'); |
|
|
|
|
|
} |
|
|
else if (index === TTN_FS_ImageIndex) { |
|
|
|
|
|
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) { |
|
|
|
|
|
imgDiv.classList.remove('ttN-divSelected', 'ttN-divBefore'); |
|
|
imgDiv.children[0].classList.remove('ttN-imgSelected', 'ttN-imgBefore'); |
|
|
|
|
|
imgDiv.classList.add('ttN-divAfter'); |
|
|
|
|
|
} |
|
|
}); |
|
|
|
|
|
_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]; |
|
|
|
|
|
} |
|
|
|
|
|
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); |
|
|
} |
|
|
|
|
|
|
|
|
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); |
|
|
} |
|
|
|
|
|
|
|
|
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); |
|
|
} |
|
|
|
|
|
|
|
|
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(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
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); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function _handleKeyPress_doc(e) { |
|
|
if (TTN_isFullscreen) { |
|
|
const imageList = ttN_srcDict[TTN_FullscreenNode.id] || []; |
|
|
|
|
|
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) { |
|
|
|
|
|
_scrollScaleImage(e, TTN_FULLSCREEN_IMAGE, zoomDirection); |
|
|
} |
|
|
if ((!TTN_INVERTCTRL && !e.ctrlKey) || (e.ctrlKey && TTN_INVERTCTRL) || isMouseOverPreviewWrapper) { |
|
|
|
|
|
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; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
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(); |
|
|
|
|
|
|
|
|
const offsetX = e.clientX - rect.left; |
|
|
const offsetY = e.clientY - rect.top; |
|
|
const relativeX = offsetX / rect.width; |
|
|
const relativeY = offsetY / rect.height; |
|
|
|
|
|
|
|
|
_setCurrentImageScale(image, scaleFactor, zoomDirection); |
|
|
|
|
|
const newRect = image.getBoundingClientRect(); |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
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); |