diff --git a/src/info-panel/InfoPanel.ts b/src/info-panel/InfoPanel.ts index ab40ca0..7b422e1 100644 --- a/src/info-panel/InfoPanel.ts +++ b/src/info-panel/InfoPanel.ts @@ -68,11 +68,9 @@ export class InfoPanel { this.magnifyGlass.updateMagnifiedView = (() => { originalUpdateMagnifiedView(); - // Only schedule info update if panel is enabled, glass is active, AND preview is visible - // This prevents extra work when glass preview is hidden via hover controls + // Schedule info update if panel is enabled and glass is active if (this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelEnabled"] && - this.magnifyGlass.state.active && - this.stateManager.state.isGlassPreviewVisible !== false) { + this.magnifyGlass.state.active) { this.scheduleInfoUpdate(); } }).bind(this); diff --git a/web/info-panel/InfoPanel.js b/web/info-panel/InfoPanel.js index cccc9b6..7414eb2 100644 --- a/web/info-panel/InfoPanel.js +++ b/web/info-panel/InfoPanel.js @@ -46,7 +46,7 @@ class InfoPanel { const originalUpdateMagnifiedView = this.magnifyGlass.updateMagnifiedView.bind(this.magnifyGlass); this.magnifyGlass.updateMagnifiedView = (() => { originalUpdateMagnifiedView(); - if (this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelEnabled"] && this.magnifyGlass.state.active && this.stateManager.state.isGlassPreviewVisible !== false) { + if (this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelEnabled"] && this.magnifyGlass.state.active) { this.scheduleInfoUpdate(); } }).bind(this); diff --git a/web/info-panel/InfoPanel.js.map b/web/info-panel/InfoPanel.js.map index 64d212c..f932d69 100644 --- a/web/info-panel/InfoPanel.js.map +++ b/web/info-panel/InfoPanel.js.map @@ -1 +1 @@ -{"version":3,"file":"InfoPanel.js","sources":["../../src/info-panel/InfoPanel.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - Info Panel Orchestrator (TypeScript)\n * \n * Complete Info Panel Manager extracted from magnify_info_panel.js\n * Main class that orchestrates all info panel components.\n */\n\nimport type { MagnifyGlassInstance } from '../types/comfyui';\nimport { registerPanelSettings } from '../shared/settings';\nimport { Logger } from '../shared/logger';\nimport { StateManager } from './StateManager';\nimport { UIManager } from './UIManager';\nimport { PositionManager } from './PositionManager';\nimport { EventManager } from './EventManager';\nimport { InformationGatherer } from './InformationGatherer';\n\n/**\n * Professional Info Panel Manager.\n * Orchestrates all the other components for the info panel.\n */\nexport class InfoPanel {\n magnifyGlass: MagnifyGlassInstance;\n stateManager: StateManager;\n uiManager: UIManager;\n positionManager: PositionManager;\n eventManager: EventManager;\n informationGatherer: InformationGatherer;\n\n constructor(magnifyGlass: MagnifyGlassInstance) {\n this.magnifyGlass = magnifyGlass;\n\n // Initialize Managers\n this.stateManager = new StateManager();\n this.uiManager = new UIManager(this.stateManager);\n this.informationGatherer = new InformationGatherer();\n\n // Position Manager needs the UI elements\n this.positionManager = new PositionManager(this.stateManager, this.uiManager.elements.panel!);\n\n // Event Manager needs state and UI manager\n this.eventManager = new EventManager(this.stateManager, this.uiManager.elements.panel!, this.positionManager, {\n toggleVisibility: () => {\n if (this.stateManager.state.isPanelVisible) {\n this.uiManager.hide();\n } else {\n this.uiManager.show();\n }\n },\n togglePin: () => {\n this.stateManager.togglePinning();\n this.uiManager.updatePinnedState();\n },\n updatePosition: () => this.positionManager.positionPanel()\n });\n\n this.hookIntoMagnifyGlass();\n\n // Register settings with ComfyUI\n registerPanelSettings(this.stateManager, this.uiManager, this.positionManager);\n\n Logger.info('Info Panel initialized successfully');\n }\n\n hookIntoMagnifyGlass(): void {\n // Hook into magnify glass update cycle\n const originalUpdateMagnifiedView = this.magnifyGlass.updateMagnifiedView.bind(this.magnifyGlass);\n\n this.magnifyGlass.updateMagnifiedView = (() => {\n originalUpdateMagnifiedView();\n\n // Only schedule info update if panel is enabled, glass is active, AND preview is visible\n // This prevents extra work when glass preview is hidden via hover controls\n if (this.stateManager.state.settings[\"🔍MagnifyGlass.InfoPanelEnabled\"] &&\n this.magnifyGlass.state.active &&\n this.stateManager.state.isGlassPreviewVisible !== false) {\n this.scheduleInfoUpdate();\n }\n }).bind(this);\n\n // Hook into show/hide\n const originalShow = this.magnifyGlass.ui.show.bind(this.magnifyGlass.ui);\n const originalHide = this.magnifyGlass.ui.hide.bind(this.magnifyGlass.ui);\n\n this.magnifyGlass.ui.show = (() => {\n originalShow();\n\n // CRITICAL: Only restore panel if the magnify glass is actually active\n // This prevents the panel from showing when toggle() is switching it OFF\n if (!this.magnifyGlass.state.active) {\n return;\n }\n\n if (this.stateManager.state.settings[\"🔍MagnifyGlass.InfoPanelEnabled\"]) {\n // Restore state: If it was visible before hide, make it visible now.\n // Otherwise only show controls.\n if (this.stateManager.state.wasPanelVisibleBeforeHide) {\n this.uiManager.show();\n\n // Position properly\n setTimeout(() => {\n this.positionManager.positionPanel();\n this.positionManager.positionFloatingControls(this.uiManager.elements.controls);\n }, 10);\n } else {\n // Do NOT force panel visible. Only show controls.\n const showControls = this.stateManager.state.settings[\"🔍MagnifyGlass.ShowHoveringControls\"] !== false;\n if (showControls && this.uiManager.elements.controls) {\n this.uiManager.elements.controls.style.display = 'flex';\n }\n\n // Ensure states are updated\n this.uiManager.updateControlStates();\n\n // Position controls after showing (relative to glass since panel is hidden)\n setTimeout(() => {\n this.positionManager.positionFloatingControls(this.uiManager.elements.controls);\n }, 10);\n }\n }\n }).bind(this);\n\n this.magnifyGlass.ui.hide = (() => {\n // Save state before hiding\n this.stateManager.state.wasPanelVisibleBeforeHide = this.stateManager.state.isPanelVisible;\n\n originalHide();\n this.uiManager.hide();\n\n // FORCE HIDE: Directly set panel display to none as a safety measure\n if (this.uiManager.elements.panel) {\n this.uiManager.elements.panel.style.display = 'none';\n }\n\n // Explicitly hide floating controls when glass is disabled\n if (this.uiManager.elements.controls) {\n this.uiManager.elements.controls.style.display = 'none';\n }\n }).bind(this);\n }\n\n scheduleInfoUpdate(): void {\n if (this.stateManager.state.updateScheduled) return;\n\n this.stateManager.state.updateScheduled = true;\n requestAnimationFrame(() => {\n this.updateInfo();\n this.stateManager.state.updateScheduled = false;\n });\n }\n\n // State for persistence\n private lastValidNodeInfo: any = null;\n\n updateInfo(): void {\n const settings = this.stateManager.state.settings;\n const isActive = this.magnifyGlass.state.active;\n\n // Safety: If disabled or inactive, ensure hidden and return\n if (!settings[\"🔍MagnifyGlass.InfoPanelEnabled\"] || !isActive) {\n // Hide the panel completely when the glass is inactive\n this.uiManager.hide();\n if (this.uiManager.elements.controls && this.uiManager.elements.controls.style.display !== 'none') {\n this.uiManager.elements.controls.style.display = 'none';\n }\n return;\n }\n\n // Logic for \"Hold Info\" (Freeze)\n if (this.stateManager.state.isInfoHeld) {\n // If held, we skip gathering new info and skip updating the display content.\n // But we MUST still update positioning to keep the UI responsive to movement.\n this.positionManager.positionPanel();\n this.positionManager.positionFloatingControls(this.uiManager.elements.controls);\n return;\n }\n\n let info = this.informationGatherer.gatherInformation();\n\n // PERSISTENCE LOGIC START\n if (info.hoveredNode) {\n // We have a valid node, update our cache\n this.lastValidNodeInfo = info;\n } else if (settings[\"🔍MagnifyGlass.InfoPanelPersist\"] && this.lastValidNodeInfo) {\n // No node hovered, but persistence is ON and we have a cache.\n // Merge the CACHED node info into the CURRENT info (so we keep current cursor pos/zoom but show old node)\n info = {\n ...info, // Current timestamp, cursor, zoom\n hoveredNode: this.lastValidNodeInfo.hoveredNode,\n hoveredWidget: this.lastValidNodeInfo.hoveredWidget\n };\n }\n // PERSISTENCE LOGIC END\n\n this.stateManager.setCurrentInfo(info);\n\n // Update the UI\n this.uiManager.displayInfo(info);\n\n // Send info to pop-out viewer if active\n if (this.magnifyGlass.popOutManager && this.magnifyGlass.popOutManager.isPopOutOpen()) {\n this.magnifyGlass.popOutManager.sendInfo(info as any);\n }\n\n this.positionManager.positionPanel();\n this.positionManager.positionFloatingControls(this.uiManager.elements.controls);\n\n // Handle node hover state logic if needed for internal state\n if (info.hoveredNode) {\n this.stateManager.state.isHoveringNode = true;\n this.stateManager.expandNodeSections();\n if (this.stateManager.state.lastNodeId !== info.hoveredNode.id) {\n this.stateManager.state.lastNodeId = info.hoveredNode.id;\n }\n } else {\n this.stateManager.state.isHoveringNode = false;\n // Only collapse if we are NOT persisting\n if (!settings[\"🔍MagnifyGlass.InfoPanelPersist\"]) {\n if (this.stateManager.state.lastNodeId !== null) {\n this.stateManager.state.lastNodeId = null;\n if (!this.stateManager.state.isPanelHovered) {\n this.stateManager.scheduleAutoCollapse();\n }\n }\n }\n }\n }\n\n updateSettings(): void {\n const changes = this.stateManager.updateSettings();\n this.uiManager.applyStyles();\n\n if (this.stateManager.state.settings[\"🔍MagnifyGlass.InfoPanelEnabled\"] && this.magnifyGlass.state.active) {\n this.uiManager.show();\n // Ensure position is updated after potential dimension changes\n this.positionManager.positionPanel();\n } else {\n this.uiManager.hide();\n }\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;AAoBO,MAAM,UAAU;AAAA,EAQnB,YAAY,cAAoC;AAPhD;AACA;AACA;AACA;AACA;AACA;AA6HQ;AAAA,6CAAyB;AA1H7B,SAAK,eAAe;AAGpB,SAAK,eAAe,IAAI,aAAA;AACxB,SAAK,YAAY,IAAI,UAAU,KAAK,YAAY;AAChD,SAAK,sBAAsB,IAAI,oBAAA;AAG/B,SAAK,kBAAkB,IAAI,gBAAgB,KAAK,cAAc,KAAK,UAAU,SAAS,KAAM;AAG5F,SAAK,eAAe,IAAI,aAAa,KAAK,cAAc,KAAK,UAAU,SAAS,OAAQ,KAAK,iBAAiB;AAAA,MAC1G,kBAAkB,MAAM;AACpB,YAAI,KAAK,aAAa,MAAM,gBAAgB;AACxC,eAAK,UAAU,KAAA;AAAA,QACnB,OAAO;AACH,eAAK,UAAU,KAAA;AAAA,QACnB;AAAA,MACJ;AAAA,MACA,WAAW,MAAM;AACb,aAAK,aAAa,cAAA;AAClB,aAAK,UAAU,kBAAA;AAAA,MACnB;AAAA,MACA,gBAAgB,MAAM,KAAK,gBAAgB,cAAA;AAAA,IAAc,CAC5D;AAED,SAAK,qBAAA;AAGL,0BAAsB,KAAK,cAAc,KAAK,WAAW,KAAK,eAAe;AAE7E,WAAO,KAAK,qCAAqC;AAAA,EACrD;AAAA,EAEA,uBAA6B;AAEzB,UAAM,8BAA8B,KAAK,aAAa,oBAAoB,KAAK,KAAK,YAAY;AAEhG,SAAK,aAAa,uBAAuB,MAAM;AAC3C,kCAAA;AAIA,UAAI,KAAK,aAAa,MAAM,SAAS,iCAAiC,KAClE,KAAK,aAAa,MAAM,UACxB,KAAK,aAAa,MAAM,0BAA0B,OAAO;AACzD,aAAK,mBAAA;AAAA,MACT;AAAA,IACJ,GAAG,KAAK,IAAI;AAGZ,UAAM,eAAe,KAAK,aAAa,GAAG,KAAK,KAAK,KAAK,aAAa,EAAE;AACxE,UAAM,eAAe,KAAK,aAAa,GAAG,KAAK,KAAK,KAAK,aAAa,EAAE;AAExE,SAAK,aAAa,GAAG,QAAQ,MAAM;AAC/B,mBAAA;AAIA,UAAI,CAAC,KAAK,aAAa,MAAM,QAAQ;AACjC;AAAA,MACJ;AAEA,UAAI,KAAK,aAAa,MAAM,SAAS,iCAAiC,GAAG;AAGrE,YAAI,KAAK,aAAa,MAAM,2BAA2B;AACnD,eAAK,UAAU,KAAA;AAGf,qBAAW,MAAM;AACb,iBAAK,gBAAgB,cAAA;AACrB,iBAAK,gBAAgB,yBAAyB,KAAK,UAAU,SAAS,QAAQ;AAAA,UAClF,GAAG,EAAE;AAAA,QACT,OAAO;AAEH,gBAAM,eAAe,KAAK,aAAa,MAAM,SAAS,qCAAqC,MAAM;AACjG,cAAI,gBAAgB,KAAK,UAAU,SAAS,UAAU;AAClD,iBAAK,UAAU,SAAS,SAAS,MAAM,UAAU;AAAA,UACrD;AAGA,eAAK,UAAU,oBAAA;AAGf,qBAAW,MAAM;AACb,iBAAK,gBAAgB,yBAAyB,KAAK,UAAU,SAAS,QAAQ;AAAA,UAClF,GAAG,EAAE;AAAA,QACT;AAAA,MACJ;AAAA,IACJ,GAAG,KAAK,IAAI;AAEZ,SAAK,aAAa,GAAG,QAAQ,MAAM;AAE/B,WAAK,aAAa,MAAM,4BAA4B,KAAK,aAAa,MAAM;AAE5E,mBAAA;AACA,WAAK,UAAU,KAAA;AAGf,UAAI,KAAK,UAAU,SAAS,OAAO;AAC/B,aAAK,UAAU,SAAS,MAAM,MAAM,UAAU;AAAA,MAClD;AAGA,UAAI,KAAK,UAAU,SAAS,UAAU;AAClC,aAAK,UAAU,SAAS,SAAS,MAAM,UAAU;AAAA,MACrD;AAAA,IACJ,GAAG,KAAK,IAAI;AAAA,EAChB;AAAA,EAEA,qBAA2B;AACvB,QAAI,KAAK,aAAa,MAAM,gBAAiB;AAE7C,SAAK,aAAa,MAAM,kBAAkB;AAC1C,0BAAsB,MAAM;AACxB,WAAK,WAAA;AACL,WAAK,aAAa,MAAM,kBAAkB;AAAA,IAC9C,CAAC;AAAA,EACL;AAAA,EAKA,aAAmB;AACf,UAAM,WAAW,KAAK,aAAa,MAAM;AACzC,UAAM,WAAW,KAAK,aAAa,MAAM;AAGzC,QAAI,CAAC,SAAS,iCAAiC,KAAK,CAAC,UAAU;AAE3D,WAAK,UAAU,KAAA;AACf,UAAI,KAAK,UAAU,SAAS,YAAY,KAAK,UAAU,SAAS,SAAS,MAAM,YAAY,QAAQ;AAC/F,aAAK,UAAU,SAAS,SAAS,MAAM,UAAU;AAAA,MACrD;AACA;AAAA,IACJ;AAGA,QAAI,KAAK,aAAa,MAAM,YAAY;AAGpC,WAAK,gBAAgB,cAAA;AACrB,WAAK,gBAAgB,yBAAyB,KAAK,UAAU,SAAS,QAAQ;AAC9E;AAAA,IACJ;AAEA,QAAI,OAAO,KAAK,oBAAoB,kBAAA;AAGpC,QAAI,KAAK,aAAa;AAElB,WAAK,oBAAoB;AAAA,IAC7B,WAAW,SAAS,iCAAiC,KAAK,KAAK,mBAAmB;AAG9E,aAAO;AAAA,QACH,GAAG;AAAA;AAAA,QACH,aAAa,KAAK,kBAAkB;AAAA,QACpC,eAAe,KAAK,kBAAkB;AAAA,MAAA;AAAA,IAE9C;AAGA,SAAK,aAAa,eAAe,IAAI;AAGrC,SAAK,UAAU,YAAY,IAAI;AAG/B,QAAI,KAAK,aAAa,iBAAiB,KAAK,aAAa,cAAc,gBAAgB;AACnF,WAAK,aAAa,cAAc,SAAS,IAAW;AAAA,IACxD;AAEA,SAAK,gBAAgB,cAAA;AACrB,SAAK,gBAAgB,yBAAyB,KAAK,UAAU,SAAS,QAAQ;AAG9E,QAAI,KAAK,aAAa;AAClB,WAAK,aAAa,MAAM,iBAAiB;AACzC,WAAK,aAAa,mBAAA;AAClB,UAAI,KAAK,aAAa,MAAM,eAAe,KAAK,YAAY,IAAI;AAC5D,aAAK,aAAa,MAAM,aAAa,KAAK,YAAY;AAAA,MAC1D;AAAA,IACJ,OAAO;AACH,WAAK,aAAa,MAAM,iBAAiB;AAEzC,UAAI,CAAC,SAAS,iCAAiC,GAAG;AAC9C,YAAI,KAAK,aAAa,MAAM,eAAe,MAAM;AAC7C,eAAK,aAAa,MAAM,aAAa;AACrC,cAAI,CAAC,KAAK,aAAa,MAAM,gBAAgB;AACzC,iBAAK,aAAa,qBAAA;AAAA,UACtB;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,iBAAuB;AACH,SAAK,aAAa,eAAA;AAClC,SAAK,UAAU,YAAA;AAEf,QAAI,KAAK,aAAa,MAAM,SAAS,iCAAiC,KAAK,KAAK,aAAa,MAAM,QAAQ;AACvG,WAAK,UAAU,KAAA;AAEf,WAAK,gBAAgB,cAAA;AAAA,IACzB,OAAO;AACH,WAAK,UAAU,KAAA;AAAA,IACnB;AAAA,EACJ;AACJ;"} \ No newline at end of file +{"version":3,"file":"InfoPanel.js","sources":["../../src/info-panel/InfoPanel.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - Info Panel Orchestrator (TypeScript)\n * \n * Complete Info Panel Manager extracted from magnify_info_panel.js\n * Main class that orchestrates all info panel components.\n */\n\nimport type { MagnifyGlassInstance } from '../types/comfyui';\nimport { registerPanelSettings } from '../shared/settings';\nimport { Logger } from '../shared/logger';\nimport { StateManager } from './StateManager';\nimport { UIManager } from './UIManager';\nimport { PositionManager } from './PositionManager';\nimport { EventManager } from './EventManager';\nimport { InformationGatherer } from './InformationGatherer';\n\n/**\n * Professional Info Panel Manager.\n * Orchestrates all the other components for the info panel.\n */\nexport class InfoPanel {\n magnifyGlass: MagnifyGlassInstance;\n stateManager: StateManager;\n uiManager: UIManager;\n positionManager: PositionManager;\n eventManager: EventManager;\n informationGatherer: InformationGatherer;\n\n constructor(magnifyGlass: MagnifyGlassInstance) {\n this.magnifyGlass = magnifyGlass;\n\n // Initialize Managers\n this.stateManager = new StateManager();\n this.uiManager = new UIManager(this.stateManager);\n this.informationGatherer = new InformationGatherer();\n\n // Position Manager needs the UI elements\n this.positionManager = new PositionManager(this.stateManager, this.uiManager.elements.panel!);\n\n // Event Manager needs state and UI manager\n this.eventManager = new EventManager(this.stateManager, this.uiManager.elements.panel!, this.positionManager, {\n toggleVisibility: () => {\n if (this.stateManager.state.isPanelVisible) {\n this.uiManager.hide();\n } else {\n this.uiManager.show();\n }\n },\n togglePin: () => {\n this.stateManager.togglePinning();\n this.uiManager.updatePinnedState();\n },\n updatePosition: () => this.positionManager.positionPanel()\n });\n\n this.hookIntoMagnifyGlass();\n\n // Register settings with ComfyUI\n registerPanelSettings(this.stateManager, this.uiManager, this.positionManager);\n\n Logger.info('Info Panel initialized successfully');\n }\n\n hookIntoMagnifyGlass(): void {\n // Hook into magnify glass update cycle\n const originalUpdateMagnifiedView = this.magnifyGlass.updateMagnifiedView.bind(this.magnifyGlass);\n\n this.magnifyGlass.updateMagnifiedView = (() => {\n originalUpdateMagnifiedView();\n\n // Schedule info update if panel is enabled and glass is active\n if (this.stateManager.state.settings[\"🔍MagnifyGlass.InfoPanelEnabled\"] &&\n this.magnifyGlass.state.active) {\n this.scheduleInfoUpdate();\n }\n }).bind(this);\n\n // Hook into show/hide\n const originalShow = this.magnifyGlass.ui.show.bind(this.magnifyGlass.ui);\n const originalHide = this.magnifyGlass.ui.hide.bind(this.magnifyGlass.ui);\n\n this.magnifyGlass.ui.show = (() => {\n originalShow();\n\n // CRITICAL: Only restore panel if the magnify glass is actually active\n // This prevents the panel from showing when toggle() is switching it OFF\n if (!this.magnifyGlass.state.active) {\n return;\n }\n\n if (this.stateManager.state.settings[\"🔍MagnifyGlass.InfoPanelEnabled\"]) {\n // Restore state: If it was visible before hide, make it visible now.\n // Otherwise only show controls.\n if (this.stateManager.state.wasPanelVisibleBeforeHide) {\n this.uiManager.show();\n\n // Position properly\n setTimeout(() => {\n this.positionManager.positionPanel();\n this.positionManager.positionFloatingControls(this.uiManager.elements.controls);\n }, 10);\n } else {\n // Do NOT force panel visible. Only show controls.\n const showControls = this.stateManager.state.settings[\"🔍MagnifyGlass.ShowHoveringControls\"] !== false;\n if (showControls && this.uiManager.elements.controls) {\n this.uiManager.elements.controls.style.display = 'flex';\n }\n\n // Ensure states are updated\n this.uiManager.updateControlStates();\n\n // Position controls after showing (relative to glass since panel is hidden)\n setTimeout(() => {\n this.positionManager.positionFloatingControls(this.uiManager.elements.controls);\n }, 10);\n }\n }\n }).bind(this);\n\n this.magnifyGlass.ui.hide = (() => {\n // Save state before hiding\n this.stateManager.state.wasPanelVisibleBeforeHide = this.stateManager.state.isPanelVisible;\n\n originalHide();\n this.uiManager.hide();\n\n // FORCE HIDE: Directly set panel display to none as a safety measure\n if (this.uiManager.elements.panel) {\n this.uiManager.elements.panel.style.display = 'none';\n }\n\n // Explicitly hide floating controls when glass is disabled\n if (this.uiManager.elements.controls) {\n this.uiManager.elements.controls.style.display = 'none';\n }\n }).bind(this);\n }\n\n scheduleInfoUpdate(): void {\n if (this.stateManager.state.updateScheduled) return;\n\n this.stateManager.state.updateScheduled = true;\n requestAnimationFrame(() => {\n this.updateInfo();\n this.stateManager.state.updateScheduled = false;\n });\n }\n\n // State for persistence\n private lastValidNodeInfo: any = null;\n\n updateInfo(): void {\n const settings = this.stateManager.state.settings;\n const isActive = this.magnifyGlass.state.active;\n\n // Safety: If disabled or inactive, ensure hidden and return\n if (!settings[\"🔍MagnifyGlass.InfoPanelEnabled\"] || !isActive) {\n // Hide the panel completely when the glass is inactive\n this.uiManager.hide();\n if (this.uiManager.elements.controls && this.uiManager.elements.controls.style.display !== 'none') {\n this.uiManager.elements.controls.style.display = 'none';\n }\n return;\n }\n\n // Logic for \"Hold Info\" (Freeze)\n if (this.stateManager.state.isInfoHeld) {\n // If held, we skip gathering new info and skip updating the display content.\n // But we MUST still update positioning to keep the UI responsive to movement.\n this.positionManager.positionPanel();\n this.positionManager.positionFloatingControls(this.uiManager.elements.controls);\n return;\n }\n\n let info = this.informationGatherer.gatherInformation();\n\n // PERSISTENCE LOGIC START\n if (info.hoveredNode) {\n // We have a valid node, update our cache\n this.lastValidNodeInfo = info;\n } else if (settings[\"🔍MagnifyGlass.InfoPanelPersist\"] && this.lastValidNodeInfo) {\n // No node hovered, but persistence is ON and we have a cache.\n // Merge the CACHED node info into the CURRENT info (so we keep current cursor pos/zoom but show old node)\n info = {\n ...info, // Current timestamp, cursor, zoom\n hoveredNode: this.lastValidNodeInfo.hoveredNode,\n hoveredWidget: this.lastValidNodeInfo.hoveredWidget\n };\n }\n // PERSISTENCE LOGIC END\n\n this.stateManager.setCurrentInfo(info);\n\n // Update the UI\n this.uiManager.displayInfo(info);\n\n // Send info to pop-out viewer if active\n if (this.magnifyGlass.popOutManager && this.magnifyGlass.popOutManager.isPopOutOpen()) {\n this.magnifyGlass.popOutManager.sendInfo(info as any);\n }\n\n this.positionManager.positionPanel();\n this.positionManager.positionFloatingControls(this.uiManager.elements.controls);\n\n // Handle node hover state logic if needed for internal state\n if (info.hoveredNode) {\n this.stateManager.state.isHoveringNode = true;\n this.stateManager.expandNodeSections();\n if (this.stateManager.state.lastNodeId !== info.hoveredNode.id) {\n this.stateManager.state.lastNodeId = info.hoveredNode.id;\n }\n } else {\n this.stateManager.state.isHoveringNode = false;\n // Only collapse if we are NOT persisting\n if (!settings[\"🔍MagnifyGlass.InfoPanelPersist\"]) {\n if (this.stateManager.state.lastNodeId !== null) {\n this.stateManager.state.lastNodeId = null;\n if (!this.stateManager.state.isPanelHovered) {\n this.stateManager.scheduleAutoCollapse();\n }\n }\n }\n }\n }\n\n updateSettings(): void {\n const changes = this.stateManager.updateSettings();\n this.uiManager.applyStyles();\n\n if (this.stateManager.state.settings[\"🔍MagnifyGlass.InfoPanelEnabled\"] && this.magnifyGlass.state.active) {\n this.uiManager.show();\n // Ensure position is updated after potential dimension changes\n this.positionManager.positionPanel();\n } else {\n this.uiManager.hide();\n }\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file