diff --git a/src/magnify-glass/ConfigManager.ts b/src/magnify-glass/ConfigManager.ts index 0c2fb50..e556d97 100644 --- a/src/magnify-glass/ConfigManager.ts +++ b/src/magnify-glass/ConfigManager.ts @@ -121,7 +121,7 @@ export class ConfigManager { this.toggleGlassPreviewKey = DEFAULT_GLASS_SETTINGS["🔍MagnifyGlass.GlassPreviewToggleHotkey"]; this.showCursorPreview = DEFAULT_GLASS_SETTINGS["🔍MagnifyGlass.ShowCursorPreview"]; this.forceDirectCaptureKey = DEFAULT_GLASS_SETTINGS["🔍MagnifyGlass.ForceDirectCaptureKey"]; - this.forceDirectCapture = false; // Runtime flag, not persisted + this.forceDirectCapture = DEFAULT_GLASS_SETTINGS["🔍MagnifyGlass.ForceDirectCapture"]; // Initialize from default // Alignment adjustment parameters - managed separately this.offsetX = 0; diff --git a/src/magnify-glass/EventHandler.ts b/src/magnify-glass/EventHandler.ts index 870de3d..4d0ead0 100644 --- a/src/magnify-glass/EventHandler.ts +++ b/src/magnify-glass/EventHandler.ts @@ -156,9 +156,22 @@ export class EventHandler { // Force Direct Capture Toggle Key if (e.key.toLowerCase() === config.forceDirectCaptureKey && (!config.altRequired || e.altKey)) { - config.forceDirectCapture = !config.forceDirectCapture; - this.magnifyGlass.debugger.log(`Force Direct Capture: ${config.forceDirectCapture ? 'ON' : 'OFF'}`); - this.magnifyGlass.updateMagnifiedView(); + // Toggle via settings to sync with UI + const currentVal = !!config.forceDirectCapture; + // @ts-ignore + const app = window.app || (window.scripts && window.scripts.app); + if (app && app.ui && app.ui.settings) { + app.ui.settings.setSettingValue('🔍MagnifyGlass.ForceDirectCapture', !currentVal); + // The setting onChange handler will update config.forceDirectCapture and view + } else { + // Fallback if app settings not available + config.forceDirectCapture = !currentVal; + if ((window as any).comfyUIMagnifyGlass) { + (window as any).comfyUIMagnifyGlass.updateMagnifiedView(); + } + } + + Logger.info(`Force Direct Capture toggled: ${!currentVal}`); e.preventDefault(); } diff --git a/src/shared/settings/defaults.ts b/src/shared/settings/defaults.ts index 7f18e6f..6ef79d1 100644 --- a/src/shared/settings/defaults.ts +++ b/src/shared/settings/defaults.ts @@ -37,6 +37,7 @@ export const DEFAULT_GLASS_SETTINGS: GlassSettings = { "🔍MagnifyGlass.ToggleFollowCursorKey": "h", "🔍MagnifyGlass.ShowCursorPreview": false, "🔍MagnifyGlass.ForceDirectCaptureKey": "d", + "🔍MagnifyGlass.ForceDirectCapture": false, }; /** diff --git a/src/shared/settings/glassSettings.ts b/src/shared/settings/glassSettings.ts index 088eb4c..20bb9b1 100644 --- a/src/shared/settings/glassSettings.ts +++ b/src/shared/settings/glassSettings.ts @@ -288,6 +288,25 @@ export function registerGlassSettings(magnifyGlass: any): void { } } }); + + app.ui.settings.addSetting({ + id: "🔍MagnifyGlass.ForceDirectCapture", + name: "⚡ Magnify Glass: Force Direct Capture", + type: "combo", + options: [{ value: true, text: "Yes" }, { value: false, text: "No" }], + defaultValue: settings["🔍MagnifyGlass.ForceDirectCapture"] ?? false, + tooltip: "Force usage of Direct Capture mode even at low zoom levels.", + onChange: (value: any) => { + if (magnifyGlass?.config) { + // Update runtime flag + magnifyGlass.config.forceDirectCapture = !!value; + if (magnifyGlass.state.active) { + magnifyGlass.updateMagnifiedView(); + } + } + } + }); + app.ui.settings.addSetting({ id: "🔍MagnifyGlass.Action.ResetPosition", name: "🔄 Magnify Glass: Reset Position", @@ -334,7 +353,9 @@ export function registerGlassSettings(magnifyGlass: any): void { app.ui.settings.setSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h'); app.ui.settings.setSettingValue('🔍MagnifyGlass.AltRequired', false); app.ui.settings.setSettingValue('🔍MagnifyGlass.OffsetStep', 5); + app.ui.settings.setSettingValue('🔍MagnifyGlass.OffsetStep', 5); app.ui.settings.setSettingValue('🔍MagnifyGlass.ShowCursorPreview', false); + app.ui.settings.setSettingValue('🔍MagnifyGlass.ForceDirectCapture', false); // Panel Defaults diff --git a/src/sidebar/SidebarSettings.ts b/src/sidebar/SidebarSettings.ts index 3c22fff..d8d7214 100644 --- a/src/sidebar/SidebarSettings.ts +++ b/src/sidebar/SidebarSettings.ts @@ -406,6 +406,12 @@ export function renderSettingsPanel(container: HTMLElement): void { `When enabled, glass stays visible. Toggle with ${activationKey}` )); + glassSection.body.appendChild(createToggle('Force Direct Capture', + getSettingValue('🔍MagnifyGlass.ForceDirectCapture', false), + (checked) => setSettingValue('🔍MagnifyGlass.ForceDirectCapture', checked), + `Force Direct Capture mode (accurate, pixel-perfect). Hotkey: ${getSettingValue('🔍MagnifyGlass.ForceDirectCaptureKey', 'd').toUpperCase()}` + )); + glassSection.body.appendChild(createToggle('Show Mini Cursor', getSettingValue('🔍MagnifyGlass.ShowCursorPreview', false), (checked) => setSettingValue('🔍MagnifyGlass.ShowCursorPreview', checked), diff --git a/web/magnify-glass/ConfigManager.js b/web/magnify-glass/ConfigManager.js index 50290e5..049df98 100644 --- a/web/magnify-glass/ConfigManager.js +++ b/web/magnify-glass/ConfigManager.js @@ -85,7 +85,7 @@ class ConfigManager { this.toggleGlassPreviewKey = DEFAULT_GLASS_SETTINGS["🔍MagnifyGlass.GlassPreviewToggleHotkey"]; this.showCursorPreview = DEFAULT_GLASS_SETTINGS["🔍MagnifyGlass.ShowCursorPreview"]; this.forceDirectCaptureKey = DEFAULT_GLASS_SETTINGS["🔍MagnifyGlass.ForceDirectCaptureKey"]; - this.forceDirectCapture = false; + this.forceDirectCapture = DEFAULT_GLASS_SETTINGS["🔍MagnifyGlass.ForceDirectCapture"]; this.offsetX = 0; this.offsetY = 0; } diff --git a/web/magnify-glass/ConfigManager.js.map b/web/magnify-glass/ConfigManager.js.map index 72c49c4..5714c2e 100644 --- a/web/magnify-glass/ConfigManager.js.map +++ b/web/magnify-glass/ConfigManager.js.map @@ -1 +1 @@ -{"version":3,"file":"ConfigManager.js","sources":["../../src/magnify-glass/ConfigManager.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - ConfigManager (TypeScript)\n * \n * Manages configuration and settings for the magnifying glass.\n */\n\nimport { getSettingValue } from '../shared/utils';\nimport { STORAGE_KEYS } from '../shared/constants';\nimport type { GlassPosition, GlassShape, TextureFilter } from '../shared/constants';\n\n// Default settings (we'll import these properly later)\nconst DEFAULT_GLASS_SETTINGS = {\n \"🔍MagnifyGlass.ZoomFactor\": 300,\n \"🔍MagnifyGlass.GlassSize\": 300,\n \"🔍MagnifyGlass.BorderColor\": \"#6b7280\",\n \"🔍MagnifyGlass.BorderWidth\": 1,\n \"🔍MagnifyGlass.ActivationKey\": \"x\",\n \"🔍MagnifyGlass.AltRequired\": false,\n \"🔍MagnifyGlass.FollowCursor\": false,\n \"🔍MagnifyGlass.OffsetStep\": 5,\n \"🔍MagnifyGlass.GlassPosition\": \"Top-Right\" as GlassPosition,\n \"🔍MagnifyGlass.ResetKey\": \"o\",\n \"🔍MagnifyGlass.GlassShape\": \"Rounded Square\" as GlassShape,\n \"🔍MagnifyGlass.BorderEnabled\": true,\n \"🔍MagnifyGlass.TextureFiltering\": \"Linear\" as TextureFilter,\n \"🔍MagnifyGlass.AlwaysActiveMode\": true,\n \"🔍MagnifyGlass.ToggleFollowCursorKey\": \"h\",\n \"🔍MagnifyGlass.GlassPreviewToggleHotkey\": \"g\",\n \"🔍MagnifyGlass.ShowCursorPreview\": false,\n \"🔍MagnifyGlass.ForceDirectCaptureKey\": \"d\",\n};\n\n/**\n * Configuration manager class.\n * Reads settings from ComfyUI and manages persistent offsets.\n */\nexport class ConfigManager {\n /** Zoom factor (1.0 = 100%, 3.0 = 300%) */\n zoomFactor: number;\n\n /** Glass size in pixels */\n glassSize: number;\n\n /** Border color (CSS color string) */\n borderColor: string;\n\n /** Border width in pixels */\n borderWidth: number;\n\n /** Activation key (lowercase) */\n activationKey: string;\n\n /** Whether Alt key is required for activation */\n altRequired: boolean;\n\n /** Whether glass follows cursor */\n followCursor: boolean;\n\n\n\n /** Offset step for arrow key adjustments */\n offsetStep: number;\n\n /** Glass position relative to cursor */\n glassPosition: string;\n\n /** Reset key (lowercase) */\n resetKey: string;\n\n /** Glass shape */\n glassShape: string;\n\n /** Whether border is enabled */\n borderEnabled: boolean;\n\n /** Texture filtering mode */\n textureFiltering: string;\n\n /** Always active mode */\n alwaysActiveMode: boolean;\n\n /** Toggle follow cursor key */\n toggleFollowCursorKey: string;\n\n /** Glass preview toggle key */\n toggleGlassPreviewKey: string;\n\n /** Show cursor preview in glass */\n showCursorPreview: boolean;\n\n /** Force Direct Capture key */\n forceDirectCaptureKey: string;\n\n /** Runtime flag: Force Direct Capture mode (not persisted) */\n forceDirectCapture: boolean;\n\n /** Manual offset X in graph units */\n offsetX: number;\n\n /** Manual offset Y in graph units */\n offsetY: number;\n\n constructor() {\n // Initialize properties with defaults\n this.zoomFactor = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ZoomFactor\"] / 100;\n this.glassSize = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.GlassSize\"];\n this.borderColor = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.BorderColor\"];\n this.borderWidth = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.BorderWidth\"];\n this.activationKey = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ActivationKey\"];\n this.altRequired = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.AltRequired\"];\n this.followCursor = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.FollowCursor\"];\n\n this.offsetStep = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.OffsetStep\"];\n this.glassPosition = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.GlassPosition\"];\n this.resetKey = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ResetKey\"];\n this.glassShape = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.GlassShape\"];\n this.borderEnabled = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.BorderEnabled\"];\n this.textureFiltering = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.TextureFiltering\"];\n this.alwaysActiveMode = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.AlwaysActiveMode\"];\n this.toggleFollowCursorKey = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ToggleFollowCursorKey\"];\n this.toggleGlassPreviewKey = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.GlassPreviewToggleHotkey\"];\n this.showCursorPreview = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ShowCursorPreview\"];\n this.forceDirectCaptureKey = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ForceDirectCaptureKey\"];\n this.forceDirectCapture = false; // Runtime flag, not persisted\n\n // Alignment adjustment parameters - managed separately\n this.offsetX = 0;\n this.offsetY = 0;\n }\n\n /**\n * Load settings from ComfyUI settings system.\n */\n loadSettings(): void {\n this.zoomFactor = getSettingValue(\"🔍MagnifyGlass.ZoomFactor\", this.zoomFactor * 100) / 100;\n this.glassSize = getSettingValue(\"🔍MagnifyGlass.GlassSize\", this.glassSize);\n this.borderColor = getSettingValue(\"🔍MagnifyGlass.BorderColor\", this.borderColor);\n this.borderWidth = getSettingValue(\"🔍MagnifyGlass.BorderWidth\", this.borderWidth);\n this.activationKey = getSettingValue(\"🔍MagnifyGlass.ActivationKey\", this.activationKey);\n this.altRequired = getSettingValue(\"🔍MagnifyGlass.AltRequired\", this.altRequired);\n this.followCursor = getSettingValue(\"🔍MagnifyGlass.FollowCursor\", this.followCursor);\n\n this.offsetStep = getSettingValue(\"🔍MagnifyGlass.OffsetStep\", this.offsetStep);\n this.glassPosition = getSettingValue(\"🔍MagnifyGlass.GlassPosition\", this.glassPosition);\n this.resetKey = getSettingValue(\"🔍MagnifyGlass.ResetKey\", this.resetKey);\n this.glassShape = getSettingValue(\"🔍MagnifyGlass.GlassShape\", this.glassShape);\n this.borderEnabled = getSettingValue(\"🔍MagnifyGlass.BorderEnabled\", this.borderEnabled);\n this.textureFiltering = getSettingValue(\"🔍MagnifyGlass.TextureFiltering\", this.textureFiltering);\n this.alwaysActiveMode = getSettingValue(\"🔍MagnifyGlass.AlwaysActiveMode\", this.alwaysActiveMode);\n this.toggleFollowCursorKey = getSettingValue(\"🔍MagnifyGlass.ToggleFollowCursorKey\", this.toggleFollowCursorKey);\n this.showCursorPreview = getSettingValue(\"🔍MagnifyGlass.ShowCursorPreview\", this.showCursorPreview);\n this.forceDirectCaptureKey = getSettingValue(\"🔍MagnifyGlass.ForceDirectCaptureKey\", this.forceDirectCaptureKey);\n this.toggleGlassPreviewKey = getSettingValue(\"🔍MagnifyGlass.GlassPreviewToggleHotkey\", this.toggleGlassPreviewKey);\n }\n\n /**\n * Load saved offsets from localStorage.\n */\n loadSavedOffsets(): void {\n try {\n const savedOffsetX = localStorage.getItem(STORAGE_KEYS.OFFSET_X);\n const savedOffsetY = localStorage.getItem(STORAGE_KEYS.OFFSET_Y);\n\n if (savedOffsetX !== null) {\n this.offsetX = parseInt(savedOffsetX, 10);\n } else {\n this.offsetX = 0;\n }\n\n if (savedOffsetY !== null) {\n this.offsetY = parseInt(savedOffsetY, 10);\n } else {\n this.offsetY = 0;\n }\n } catch (e) {\n console.error(\"ComfyUI Magnifying Glass ERROR: Error loading saved offsets:\", e);\n this.offsetX = 0;\n this.offsetY = 0;\n }\n }\n\n /**\n * Save current offsets to localStorage.\n */\n saveOffsets(): void {\n try {\n localStorage.setItem(STORAGE_KEYS.OFFSET_X, this.offsetX.toString());\n localStorage.setItem(STORAGE_KEYS.OFFSET_Y, this.offsetY.toString());\n } catch (e) {\n console.error(\"ComfyUI Magnifying Glass ERROR: Error saving offsets:\", e);\n }\n }\n\n /**\n * Reset offsets to default (zero).\n */\n resetOffsets(): void {\n this.offsetX = 0;\n this.offsetY = 0;\n this.saveOffsets();\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"ConfigManager.js","sources":["../../src/magnify-glass/ConfigManager.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - ConfigManager (TypeScript)\n * \n * Manages configuration and settings for the magnifying glass.\n */\n\nimport { getSettingValue } from '../shared/utils';\nimport { STORAGE_KEYS } from '../shared/constants';\nimport type { GlassPosition, GlassShape, TextureFilter } from '../shared/constants';\n\n// Default settings (we'll import these properly later)\nconst DEFAULT_GLASS_SETTINGS = {\n \"🔍MagnifyGlass.ZoomFactor\": 300,\n \"🔍MagnifyGlass.GlassSize\": 300,\n \"🔍MagnifyGlass.BorderColor\": \"#6b7280\",\n \"🔍MagnifyGlass.BorderWidth\": 1,\n \"🔍MagnifyGlass.ActivationKey\": \"x\",\n \"🔍MagnifyGlass.AltRequired\": false,\n \"🔍MagnifyGlass.FollowCursor\": false,\n \"🔍MagnifyGlass.OffsetStep\": 5,\n \"🔍MagnifyGlass.GlassPosition\": \"Top-Right\" as GlassPosition,\n \"🔍MagnifyGlass.ResetKey\": \"o\",\n \"🔍MagnifyGlass.GlassShape\": \"Rounded Square\" as GlassShape,\n \"🔍MagnifyGlass.BorderEnabled\": true,\n \"🔍MagnifyGlass.TextureFiltering\": \"Linear\" as TextureFilter,\n \"🔍MagnifyGlass.AlwaysActiveMode\": true,\n \"🔍MagnifyGlass.ToggleFollowCursorKey\": \"h\",\n \"🔍MagnifyGlass.GlassPreviewToggleHotkey\": \"g\",\n \"🔍MagnifyGlass.ShowCursorPreview\": false,\n \"🔍MagnifyGlass.ForceDirectCaptureKey\": \"d\",\n};\n\n/**\n * Configuration manager class.\n * Reads settings from ComfyUI and manages persistent offsets.\n */\nexport class ConfigManager {\n /** Zoom factor (1.0 = 100%, 3.0 = 300%) */\n zoomFactor: number;\n\n /** Glass size in pixels */\n glassSize: number;\n\n /** Border color (CSS color string) */\n borderColor: string;\n\n /** Border width in pixels */\n borderWidth: number;\n\n /** Activation key (lowercase) */\n activationKey: string;\n\n /** Whether Alt key is required for activation */\n altRequired: boolean;\n\n /** Whether glass follows cursor */\n followCursor: boolean;\n\n\n\n /** Offset step for arrow key adjustments */\n offsetStep: number;\n\n /** Glass position relative to cursor */\n glassPosition: string;\n\n /** Reset key (lowercase) */\n resetKey: string;\n\n /** Glass shape */\n glassShape: string;\n\n /** Whether border is enabled */\n borderEnabled: boolean;\n\n /** Texture filtering mode */\n textureFiltering: string;\n\n /** Always active mode */\n alwaysActiveMode: boolean;\n\n /** Toggle follow cursor key */\n toggleFollowCursorKey: string;\n\n /** Glass preview toggle key */\n toggleGlassPreviewKey: string;\n\n /** Show cursor preview in glass */\n showCursorPreview: boolean;\n\n /** Force Direct Capture key */\n forceDirectCaptureKey: string;\n\n /** Runtime flag: Force Direct Capture mode (not persisted) */\n forceDirectCapture: boolean;\n\n /** Manual offset X in graph units */\n offsetX: number;\n\n /** Manual offset Y in graph units */\n offsetY: number;\n\n constructor() {\n // Initialize properties with defaults\n this.zoomFactor = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ZoomFactor\"] / 100;\n this.glassSize = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.GlassSize\"];\n this.borderColor = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.BorderColor\"];\n this.borderWidth = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.BorderWidth\"];\n this.activationKey = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ActivationKey\"];\n this.altRequired = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.AltRequired\"];\n this.followCursor = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.FollowCursor\"];\n\n this.offsetStep = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.OffsetStep\"];\n this.glassPosition = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.GlassPosition\"];\n this.resetKey = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ResetKey\"];\n this.glassShape = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.GlassShape\"];\n this.borderEnabled = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.BorderEnabled\"];\n this.textureFiltering = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.TextureFiltering\"];\n this.alwaysActiveMode = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.AlwaysActiveMode\"];\n this.toggleFollowCursorKey = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ToggleFollowCursorKey\"];\n this.toggleGlassPreviewKey = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.GlassPreviewToggleHotkey\"];\n this.showCursorPreview = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ShowCursorPreview\"];\n this.forceDirectCaptureKey = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ForceDirectCaptureKey\"];\n this.forceDirectCapture = DEFAULT_GLASS_SETTINGS[\"🔍MagnifyGlass.ForceDirectCapture\"]; // Initialize from default\n\n // Alignment adjustment parameters - managed separately\n this.offsetX = 0;\n this.offsetY = 0;\n }\n\n /**\n * Load settings from ComfyUI settings system.\n */\n loadSettings(): void {\n this.zoomFactor = getSettingValue(\"🔍MagnifyGlass.ZoomFactor\", this.zoomFactor * 100) / 100;\n this.glassSize = getSettingValue(\"🔍MagnifyGlass.GlassSize\", this.glassSize);\n this.borderColor = getSettingValue(\"🔍MagnifyGlass.BorderColor\", this.borderColor);\n this.borderWidth = getSettingValue(\"🔍MagnifyGlass.BorderWidth\", this.borderWidth);\n this.activationKey = getSettingValue(\"🔍MagnifyGlass.ActivationKey\", this.activationKey);\n this.altRequired = getSettingValue(\"🔍MagnifyGlass.AltRequired\", this.altRequired);\n this.followCursor = getSettingValue(\"🔍MagnifyGlass.FollowCursor\", this.followCursor);\n\n this.offsetStep = getSettingValue(\"🔍MagnifyGlass.OffsetStep\", this.offsetStep);\n this.glassPosition = getSettingValue(\"🔍MagnifyGlass.GlassPosition\", this.glassPosition);\n this.resetKey = getSettingValue(\"🔍MagnifyGlass.ResetKey\", this.resetKey);\n this.glassShape = getSettingValue(\"🔍MagnifyGlass.GlassShape\", this.glassShape);\n this.borderEnabled = getSettingValue(\"🔍MagnifyGlass.BorderEnabled\", this.borderEnabled);\n this.textureFiltering = getSettingValue(\"🔍MagnifyGlass.TextureFiltering\", this.textureFiltering);\n this.alwaysActiveMode = getSettingValue(\"🔍MagnifyGlass.AlwaysActiveMode\", this.alwaysActiveMode);\n this.toggleFollowCursorKey = getSettingValue(\"🔍MagnifyGlass.ToggleFollowCursorKey\", this.toggleFollowCursorKey);\n this.showCursorPreview = getSettingValue(\"🔍MagnifyGlass.ShowCursorPreview\", this.showCursorPreview);\n this.forceDirectCaptureKey = getSettingValue(\"🔍MagnifyGlass.ForceDirectCaptureKey\", this.forceDirectCaptureKey);\n this.toggleGlassPreviewKey = getSettingValue(\"🔍MagnifyGlass.GlassPreviewToggleHotkey\", this.toggleGlassPreviewKey);\n }\n\n /**\n * Load saved offsets from localStorage.\n */\n loadSavedOffsets(): void {\n try {\n const savedOffsetX = localStorage.getItem(STORAGE_KEYS.OFFSET_X);\n const savedOffsetY = localStorage.getItem(STORAGE_KEYS.OFFSET_Y);\n\n if (savedOffsetX !== null) {\n this.offsetX = parseInt(savedOffsetX, 10);\n } else {\n this.offsetX = 0;\n }\n\n if (savedOffsetY !== null) {\n this.offsetY = parseInt(savedOffsetY, 10);\n } else {\n this.offsetY = 0;\n }\n } catch (e) {\n console.error(\"ComfyUI Magnifying Glass ERROR: Error loading saved offsets:\", e);\n this.offsetX = 0;\n this.offsetY = 0;\n }\n }\n\n /**\n * Save current offsets to localStorage.\n */\n saveOffsets(): void {\n try {\n localStorage.setItem(STORAGE_KEYS.OFFSET_X, this.offsetX.toString());\n localStorage.setItem(STORAGE_KEYS.OFFSET_Y, this.offsetY.toString());\n } catch (e) {\n console.error(\"ComfyUI Magnifying Glass ERROR: Error saving offsets:\", e);\n }\n }\n\n /**\n * Reset offsets to default (zero).\n */\n resetOffsets(): void {\n this.offsetX = 0;\n this.offsetY = 0;\n this.saveOffsets();\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/web/magnify-glass/EventHandler.js b/web/magnify-glass/EventHandler.js index 4b255d9..81e3cb1 100644 --- a/web/magnify-glass/EventHandler.js +++ b/web/magnify-glass/EventHandler.js @@ -118,9 +118,17 @@ class EventHandler { this.magnifyGlass.updateMagnifiedView(); } if (e.key.toLowerCase() === config.forceDirectCaptureKey && (!config.altRequired || e.altKey)) { - config.forceDirectCapture = !config.forceDirectCapture; - this.magnifyGlass.debugger.log(`Force Direct Capture: ${config.forceDirectCapture ? "ON" : "OFF"}`); - this.magnifyGlass.updateMagnifiedView(); + const currentVal = !!config.forceDirectCapture; + const app = window.app || window.scripts && window.scripts.app; + if (app && app.ui && app.ui.settings) { + app.ui.settings.setSettingValue("🔍MagnifyGlass.ForceDirectCapture", !currentVal); + } else { + config.forceDirectCapture = !currentVal; + if (window.comfyUIMagnifyGlass) { + window.comfyUIMagnifyGlass.updateMagnifiedView(); + } + } + Logger.info(`Force Direct Capture toggled: ${!currentVal}`); e.preventDefault(); } if (e.shiftKey && e.key.toLowerCase() === "p") { diff --git a/web/magnify-glass/EventHandler.js.map b/web/magnify-glass/EventHandler.js.map index d617ac4..954ae5a 100644 --- a/web/magnify-glass/EventHandler.js.map +++ b/web/magnify-glass/EventHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"EventHandler.js","sources":["../../src/magnify-glass/EventHandler.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - EventHandler (TypeScript)\n * \n * Handles keyboard and mouse events for the magnifying glass.\n */\n\nimport { isUserTyping } from '../shared/utils';\nimport { Logger } from '../shared/logger';\nimport { DEFAULT_PADDING, DEFAULT_GLASS_Y_OFFSET } from '../shared/constants';\nimport type { MagnifyGlass } from './MagnifyGlass';\n\n/**\n * Event Handler class.\n * Manages all keyboard and mouse event handling for the magnifier.\n */\nexport class EventHandler {\n magnifyGlass: MagnifyGlass;\n\n constructor(magnifyGlass: MagnifyGlass) {\n this.magnifyGlass = magnifyGlass;\n\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleKeyUp = this.handleKeyUp.bind(this);\n this.handleMouseMove = this.handleMouseMove.bind(this);\n this.handleResize = this.handleResize.bind(this);\n }\n\n /**\n * Attach all event listeners.\n */\n attachListeners(): void {\n document.addEventListener(\"keydown\", this.handleKeyDown);\n document.addEventListener(\"keyup\", this.handleKeyUp);\n document.addEventListener(\"mousemove\", this.handleMouseMove);\n window.addEventListener(\"resize\", this.handleResize);\n }\n\n /**\n * Detach all event listeners.\n */\n detachListeners(): void {\n document.removeEventListener(\"keydown\", this.handleKeyDown);\n document.removeEventListener(\"keyup\", this.handleKeyUp);\n document.removeEventListener(\"mousemove\", this.handleMouseMove);\n window.removeEventListener(\"resize\", this.handleResize);\n }\n\n /**\n * Handle window resize events.\n */\n handleResize(): void {\n if (this.magnifyGlass && this.magnifyGlass.ui) {\n this.magnifyGlass.ui.updateResponsivePosition();\n // Also update panel position if it exists\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel && infoPanel.positionManager) {\n // Determine if we should move it\n infoPanel.positionManager.positionPanel();\n }\n }\n }\n\n /**\n * Handle keydown events.\n */\n handleKeyDown(e: KeyboardEvent): void {\n const config = this.magnifyGlass.config;\n const state = this.magnifyGlass.state;\n\n // Don't handle hotkeys if user is typing in an input field\n if (isUserTyping()) {\n return;\n }\n\n // Magnifier activation\n Logger.debug(`KeyDown: ${e.key} (config: ${config.activationKey}, active: ${state.active})`);\n if (e.key.toLowerCase() === config.activationKey &&\n (!config.altRequired || e.altKey)) {\n Logger.debug('Activation key matched!');\n if (config.alwaysActiveMode) {\n this.magnifyGlass.toggle();\n } else {\n if (!state.active) {\n this.magnifyGlass.toggle();\n }\n }\n }\n\n // Manual offset adjustment keys (only when magnifier is active)\n if (state.active) {\n let offsetChanged = false;\n const stepSize = config.offsetStep;\n\n if (e.key === \"ArrowUp\") {\n config.offsetY -= stepSize;\n offsetChanged = true;\n e.preventDefault();\n } else if (e.key === \"ArrowDown\") {\n config.offsetY += stepSize;\n offsetChanged = true;\n e.preventDefault();\n } else if (e.key === \"ArrowLeft\") {\n config.offsetX -= stepSize;\n offsetChanged = true;\n e.preventDefault();\n } else if (e.key === \"ArrowRight\") {\n config.offsetX += stepSize;\n offsetChanged = true;\n e.preventDefault();\n } else if (e.key.toLowerCase() === config.resetKey.toLowerCase() &&\n (!config.altRequired || e.altKey)) {\n this.magnifyGlass.resetOffsets();\n offsetChanged = true;\n e.preventDefault();\n }\n\n // Toggle Follow Cursor Key\n if (e.key.toLowerCase() === config.toggleFollowCursorKey &&\n (!config.altRequired || e.altKey)) {\n config.followCursor = !config.followCursor;\n this.magnifyGlass.debugger.log(`Follow Cursor Toggled: ${config.followCursor ? 'ON' : 'OFF'}`);\n if (state.active && config.followCursor) {\n this.magnifyGlass.ui.positionGlass(\n this.magnifyGlass.lastKnownMousePosition.x,\n this.magnifyGlass.lastKnownMousePosition.y\n );\n }\n e.preventDefault();\n }\n\n // Toggle Glass Preview Key (G) - mimics the hover controls button\n if (e.key.toLowerCase() === config.toggleGlassPreviewKey &&\n (!config.altRequired || e.altKey)) {\n // Find and click the toggle-glass button in the info panel hover controls\n const toggleGlassBtn = document.querySelector('[data-action=\"toggle-glass\"]') as HTMLElement;\n if (toggleGlassBtn) {\n toggleGlassBtn.click();\n this.magnifyGlass.debugger.log(`Glass Preview Toggled (via button)`);\n } else {\n // Fallback: toggle via UI directly if button not found\n const glassDiv = this.magnifyGlass.ui.glassDiv;\n if (glassDiv) {\n const isVisible = glassDiv.style.display !== 'none' && glassDiv.style.opacity !== '0';\n this.magnifyGlass.ui.setPreviewVisibility(!isVisible);\n this.magnifyGlass.debugger.log(`Glass Preview Toggled (fallback): ${!isVisible ? 'ON' : 'OFF'}`);\n }\n }\n e.preventDefault();\n }\n\n if (offsetChanged) {\n config.saveOffsets();\n this.magnifyGlass.updateMagnifiedView();\n }\n\n // Force Direct Capture Toggle Key\n if (e.key.toLowerCase() === config.forceDirectCaptureKey &&\n (!config.altRequired || e.altKey)) {\n config.forceDirectCapture = !config.forceDirectCapture;\n this.magnifyGlass.debugger.log(`Force Direct Capture: ${config.forceDirectCapture ? 'ON' : 'OFF'}`);\n this.magnifyGlass.updateMagnifiedView();\n e.preventDefault();\n }\n\n // Pop-out tab toggle (Shift+P)\n if (e.shiftKey && e.key.toLowerCase() === 'p') {\n this.magnifyGlass.popOutManager.toggle();\n e.preventDefault();\n }\n }\n }\n\n /**\n * Handle keyup events.\n */\n handleKeyUp(e: KeyboardEvent): void {\n const config = this.magnifyGlass.config;\n const state = this.magnifyGlass.state;\n\n if (!config.alwaysActiveMode &&\n (e.key.toLowerCase() === config.activationKey ||\n (config.altRequired && e.key === \"Alt\"))) {\n\n let shouldDeactivate = false;\n if (config.altRequired) {\n if (e.key === \"Alt\" || e.key.toLowerCase() === config.activationKey) {\n shouldDeactivate = true;\n }\n } else {\n if (e.key.toLowerCase() === config.activationKey) {\n shouldDeactivate = true;\n }\n }\n\n if (state.active && shouldDeactivate) {\n state.active = false;\n this.magnifyGlass.ui.hide();\n }\n }\n }\n\n /**\n * Handle mousemove events.\n */\n handleMouseMove(e: MouseEvent): void {\n // Always track mouse position\n this.magnifyGlass.lastKnownMousePosition.x = e.clientX;\n this.magnifyGlass.lastKnownMousePosition.y = e.clientY;\n\n if (!this.magnifyGlass.state.active || !this.magnifyGlass.litegraphCanvas) return;\n\n const rect = this.magnifyGlass.litegraphCanvas.getBoundingClientRect();\n const cssMouseXOnCanvas = e.clientX - rect.left;\n const cssMouseYOnCanvas = e.clientY - rect.top;\n\n // Check if the cursor is over the canvas element\n if (cssMouseXOnCanvas >= 0 && cssMouseXOnCanvas <= rect.width &&\n cssMouseYOnCanvas >= 0 && cssMouseYOnCanvas <= rect.height) {\n\n const canvasElement = this.magnifyGlass.litegraphCanvas;\n const scaleX = rect.width > 0 ? canvasElement.width / rect.width : 1;\n const scaleY = rect.height > 0 ? canvasElement.height / rect.height : 1;\n\n const pixelX = cssMouseXOnCanvas * scaleX;\n const pixelY = cssMouseYOnCanvas * scaleY;\n\n this.magnifyGlass.state.x = pixelX;\n this.magnifyGlass.state.y = pixelY;\n\n this.magnifyGlass.ui.positionGlass(e.clientX, e.clientY);\n this.magnifyGlass.updateMagnifiedView();\n }\n }\n\n /**\n * Update the initial position when magnifier is activated.\n */\n updateInitialPosition(): void {\n if (!this.magnifyGlass.litegraphCanvas) return;\n\n const rect = this.magnifyGlass.litegraphCanvas.getBoundingClientRect();\n const clientX = this.magnifyGlass.lastKnownMousePosition.x;\n const clientY = this.magnifyGlass.lastKnownMousePosition.y;\n\n const isOverCanvas = clientX >= rect.left && clientX <= rect.right &&\n clientY >= rect.top && clientY <= rect.bottom;\n\n if (this.magnifyGlass.config.alwaysActiveMode || isOverCanvas) {\n const cssMouseXOnCanvas = clientX - rect.left;\n const cssMouseYOnCanvas = clientY - rect.top;\n\n const canvasElement = this.magnifyGlass.litegraphCanvas;\n const scaleX = rect.width > 0 ? canvasElement.width / rect.width : 1;\n const scaleY = rect.height > 0 ? canvasElement.height / rect.height : 1;\n\n const pixelX = cssMouseXOnCanvas * scaleX;\n const pixelY = cssMouseYOnCanvas * scaleY;\n\n this.magnifyGlass.state.x = pixelX;\n this.magnifyGlass.state.y = pixelY;\n\n const glassSize = this.magnifyGlass.config.glassSize;\n\n if (!this.magnifyGlass.state.wasActivatedBefore && this.magnifyGlass.ui.glassDiv) {\n // First activation - position at top right of the window (Anchored)\n // Using style.right ensures it stays on the right even if window resizes before first usage\n this.magnifyGlass.ui.glassDiv.style.right = `${DEFAULT_PADDING}px`;\n this.magnifyGlass.ui.glassDiv.style.top = `${DEFAULT_GLASS_Y_OFFSET}px`;\n this.magnifyGlass.ui.glassDiv.style.left = 'auto'; // Ensure left is unset\n this.magnifyGlass.state.wasActivatedBefore = true;\n } else {\n this.magnifyGlass.ui.positionGlass(clientX, clientY);\n }\n\n this.magnifyGlass.updateMagnifiedView();\n }\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"EventHandler.js","sources":["../../src/magnify-glass/EventHandler.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - EventHandler (TypeScript)\n * \n * Handles keyboard and mouse events for the magnifying glass.\n */\n\nimport { isUserTyping } from '../shared/utils';\nimport { Logger } from '../shared/logger';\nimport { DEFAULT_PADDING, DEFAULT_GLASS_Y_OFFSET } from '../shared/constants';\nimport type { MagnifyGlass } from './MagnifyGlass';\n\n/**\n * Event Handler class.\n * Manages all keyboard and mouse event handling for the magnifier.\n */\nexport class EventHandler {\n magnifyGlass: MagnifyGlass;\n\n constructor(magnifyGlass: MagnifyGlass) {\n this.magnifyGlass = magnifyGlass;\n\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleKeyUp = this.handleKeyUp.bind(this);\n this.handleMouseMove = this.handleMouseMove.bind(this);\n this.handleResize = this.handleResize.bind(this);\n }\n\n /**\n * Attach all event listeners.\n */\n attachListeners(): void {\n document.addEventListener(\"keydown\", this.handleKeyDown);\n document.addEventListener(\"keyup\", this.handleKeyUp);\n document.addEventListener(\"mousemove\", this.handleMouseMove);\n window.addEventListener(\"resize\", this.handleResize);\n }\n\n /**\n * Detach all event listeners.\n */\n detachListeners(): void {\n document.removeEventListener(\"keydown\", this.handleKeyDown);\n document.removeEventListener(\"keyup\", this.handleKeyUp);\n document.removeEventListener(\"mousemove\", this.handleMouseMove);\n window.removeEventListener(\"resize\", this.handleResize);\n }\n\n /**\n * Handle window resize events.\n */\n handleResize(): void {\n if (this.magnifyGlass && this.magnifyGlass.ui) {\n this.magnifyGlass.ui.updateResponsivePosition();\n // Also update panel position if it exists\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel && infoPanel.positionManager) {\n // Determine if we should move it\n infoPanel.positionManager.positionPanel();\n }\n }\n }\n\n /**\n * Handle keydown events.\n */\n handleKeyDown(e: KeyboardEvent): void {\n const config = this.magnifyGlass.config;\n const state = this.magnifyGlass.state;\n\n // Don't handle hotkeys if user is typing in an input field\n if (isUserTyping()) {\n return;\n }\n\n // Magnifier activation\n Logger.debug(`KeyDown: ${e.key} (config: ${config.activationKey}, active: ${state.active})`);\n if (e.key.toLowerCase() === config.activationKey &&\n (!config.altRequired || e.altKey)) {\n Logger.debug('Activation key matched!');\n if (config.alwaysActiveMode) {\n this.magnifyGlass.toggle();\n } else {\n if (!state.active) {\n this.magnifyGlass.toggle();\n }\n }\n }\n\n // Manual offset adjustment keys (only when magnifier is active)\n if (state.active) {\n let offsetChanged = false;\n const stepSize = config.offsetStep;\n\n if (e.key === \"ArrowUp\") {\n config.offsetY -= stepSize;\n offsetChanged = true;\n e.preventDefault();\n } else if (e.key === \"ArrowDown\") {\n config.offsetY += stepSize;\n offsetChanged = true;\n e.preventDefault();\n } else if (e.key === \"ArrowLeft\") {\n config.offsetX -= stepSize;\n offsetChanged = true;\n e.preventDefault();\n } else if (e.key === \"ArrowRight\") {\n config.offsetX += stepSize;\n offsetChanged = true;\n e.preventDefault();\n } else if (e.key.toLowerCase() === config.resetKey.toLowerCase() &&\n (!config.altRequired || e.altKey)) {\n this.magnifyGlass.resetOffsets();\n offsetChanged = true;\n e.preventDefault();\n }\n\n // Toggle Follow Cursor Key\n if (e.key.toLowerCase() === config.toggleFollowCursorKey &&\n (!config.altRequired || e.altKey)) {\n config.followCursor = !config.followCursor;\n this.magnifyGlass.debugger.log(`Follow Cursor Toggled: ${config.followCursor ? 'ON' : 'OFF'}`);\n if (state.active && config.followCursor) {\n this.magnifyGlass.ui.positionGlass(\n this.magnifyGlass.lastKnownMousePosition.x,\n this.magnifyGlass.lastKnownMousePosition.y\n );\n }\n e.preventDefault();\n }\n\n // Toggle Glass Preview Key (G) - mimics the hover controls button\n if (e.key.toLowerCase() === config.toggleGlassPreviewKey &&\n (!config.altRequired || e.altKey)) {\n // Find and click the toggle-glass button in the info panel hover controls\n const toggleGlassBtn = document.querySelector('[data-action=\"toggle-glass\"]') as HTMLElement;\n if (toggleGlassBtn) {\n toggleGlassBtn.click();\n this.magnifyGlass.debugger.log(`Glass Preview Toggled (via button)`);\n } else {\n // Fallback: toggle via UI directly if button not found\n const glassDiv = this.magnifyGlass.ui.glassDiv;\n if (glassDiv) {\n const isVisible = glassDiv.style.display !== 'none' && glassDiv.style.opacity !== '0';\n this.magnifyGlass.ui.setPreviewVisibility(!isVisible);\n this.magnifyGlass.debugger.log(`Glass Preview Toggled (fallback): ${!isVisible ? 'ON' : 'OFF'}`);\n }\n }\n e.preventDefault();\n }\n\n if (offsetChanged) {\n config.saveOffsets();\n this.magnifyGlass.updateMagnifiedView();\n }\n\n // Force Direct Capture Toggle Key\n if (e.key.toLowerCase() === config.forceDirectCaptureKey &&\n (!config.altRequired || e.altKey)) {\n // Toggle via settings to sync with UI\n const currentVal = !!config.forceDirectCapture;\n // @ts-ignore\n const app = window.app || (window.scripts && window.scripts.app);\n if (app && app.ui && app.ui.settings) {\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ForceDirectCapture', !currentVal);\n // The setting onChange handler will update config.forceDirectCapture and view\n } else {\n // Fallback if app settings not available\n config.forceDirectCapture = !currentVal;\n if ((window as any).comfyUIMagnifyGlass) {\n (window as any).comfyUIMagnifyGlass.updateMagnifiedView();\n }\n }\n\n Logger.info(`Force Direct Capture toggled: ${!currentVal}`);\n e.preventDefault();\n }\n\n // Pop-out tab toggle (Shift+P)\n if (e.shiftKey && e.key.toLowerCase() === 'p') {\n this.magnifyGlass.popOutManager.toggle();\n e.preventDefault();\n }\n }\n }\n\n /**\n * Handle keyup events.\n */\n handleKeyUp(e: KeyboardEvent): void {\n const config = this.magnifyGlass.config;\n const state = this.magnifyGlass.state;\n\n if (!config.alwaysActiveMode &&\n (e.key.toLowerCase() === config.activationKey ||\n (config.altRequired && e.key === \"Alt\"))) {\n\n let shouldDeactivate = false;\n if (config.altRequired) {\n if (e.key === \"Alt\" || e.key.toLowerCase() === config.activationKey) {\n shouldDeactivate = true;\n }\n } else {\n if (e.key.toLowerCase() === config.activationKey) {\n shouldDeactivate = true;\n }\n }\n\n if (state.active && shouldDeactivate) {\n state.active = false;\n this.magnifyGlass.ui.hide();\n }\n }\n }\n\n /**\n * Handle mousemove events.\n */\n handleMouseMove(e: MouseEvent): void {\n // Always track mouse position\n this.magnifyGlass.lastKnownMousePosition.x = e.clientX;\n this.magnifyGlass.lastKnownMousePosition.y = e.clientY;\n\n if (!this.magnifyGlass.state.active || !this.magnifyGlass.litegraphCanvas) return;\n\n const rect = this.magnifyGlass.litegraphCanvas.getBoundingClientRect();\n const cssMouseXOnCanvas = e.clientX - rect.left;\n const cssMouseYOnCanvas = e.clientY - rect.top;\n\n // Check if the cursor is over the canvas element\n if (cssMouseXOnCanvas >= 0 && cssMouseXOnCanvas <= rect.width &&\n cssMouseYOnCanvas >= 0 && cssMouseYOnCanvas <= rect.height) {\n\n const canvasElement = this.magnifyGlass.litegraphCanvas;\n const scaleX = rect.width > 0 ? canvasElement.width / rect.width : 1;\n const scaleY = rect.height > 0 ? canvasElement.height / rect.height : 1;\n\n const pixelX = cssMouseXOnCanvas * scaleX;\n const pixelY = cssMouseYOnCanvas * scaleY;\n\n this.magnifyGlass.state.x = pixelX;\n this.magnifyGlass.state.y = pixelY;\n\n this.magnifyGlass.ui.positionGlass(e.clientX, e.clientY);\n this.magnifyGlass.updateMagnifiedView();\n }\n }\n\n /**\n * Update the initial position when magnifier is activated.\n */\n updateInitialPosition(): void {\n if (!this.magnifyGlass.litegraphCanvas) return;\n\n const rect = this.magnifyGlass.litegraphCanvas.getBoundingClientRect();\n const clientX = this.magnifyGlass.lastKnownMousePosition.x;\n const clientY = this.magnifyGlass.lastKnownMousePosition.y;\n\n const isOverCanvas = clientX >= rect.left && clientX <= rect.right &&\n clientY >= rect.top && clientY <= rect.bottom;\n\n if (this.magnifyGlass.config.alwaysActiveMode || isOverCanvas) {\n const cssMouseXOnCanvas = clientX - rect.left;\n const cssMouseYOnCanvas = clientY - rect.top;\n\n const canvasElement = this.magnifyGlass.litegraphCanvas;\n const scaleX = rect.width > 0 ? canvasElement.width / rect.width : 1;\n const scaleY = rect.height > 0 ? canvasElement.height / rect.height : 1;\n\n const pixelX = cssMouseXOnCanvas * scaleX;\n const pixelY = cssMouseYOnCanvas * scaleY;\n\n this.magnifyGlass.state.x = pixelX;\n this.magnifyGlass.state.y = pixelY;\n\n const glassSize = this.magnifyGlass.config.glassSize;\n\n if (!this.magnifyGlass.state.wasActivatedBefore && this.magnifyGlass.ui.glassDiv) {\n // First activation - position at top right of the window (Anchored)\n // Using style.right ensures it stays on the right even if window resizes before first usage\n this.magnifyGlass.ui.glassDiv.style.right = `${DEFAULT_PADDING}px`;\n this.magnifyGlass.ui.glassDiv.style.top = `${DEFAULT_GLASS_Y_OFFSET}px`;\n this.magnifyGlass.ui.glassDiv.style.left = 'auto'; // Ensure left is unset\n this.magnifyGlass.state.wasActivatedBefore = true;\n } else {\n this.magnifyGlass.ui.positionGlass(clientX, clientY);\n }\n\n this.magnifyGlass.updateMagnifiedView();\n }\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/web/shared/settings/defaults.js b/web/shared/settings/defaults.js index 15fa94e..43c5f39 100644 --- a/web/shared/settings/defaults.js +++ b/web/shared/settings/defaults.js @@ -15,7 +15,8 @@ const DEFAULT_GLASS_SETTINGS = { "🔍MagnifyGlass.TextureFiltering": "Linear", "🔍MagnifyGlass.AlwaysActiveMode": true, "🔍MagnifyGlass.ToggleFollowCursorKey": "h", - "🔍MagnifyGlass.ShowCursorPreview": false + "🔍MagnifyGlass.ShowCursorPreview": false, + "🔍MagnifyGlass.ForceDirectCapture": false }; const DEFAULT_PANEL_SETTINGS = { "🔍MagnifyGlass.InfoPanelEnabled": true, diff --git a/web/shared/settings/defaults.js.map b/web/shared/settings/defaults.js.map index 519ca04..62e298c 100644 --- a/web/shared/settings/defaults.js.map +++ b/web/shared/settings/defaults.js.map @@ -1 +1 @@ -{"version":3,"file":"defaults.js","sources":["../../../src/shared/settings/defaults.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - Default Settings Values\n * \n * Default values for all magnify glass and info panel settings.\n */\n\nimport {\n DEFAULT_GLASS_SIZE,\n DEFAULT_ZOOM_FACTOR,\n DEFAULT_BORDER_WIDTH,\n DEFAULT_BORDER_COLOR,\n DEFAULT_OFFSET_STEP,\n DEFAULT_PANEL_WIDTH,\n DEFAULT_PANEL_MAX_HEIGHT,\n DEFAULT_PANEL_OPACITY\n} from '../constants';\nimport type { GlassSettings, PanelSettings } from './types';\n\n/**\n * Default settings for the magnify glass component.\n */\nexport const DEFAULT_GLASS_SETTINGS: GlassSettings = {\n \"🔍MagnifyGlass.ZoomFactor\": DEFAULT_ZOOM_FACTOR,\n \"🔍MagnifyGlass.GlassSize\": DEFAULT_GLASS_SIZE,\n \"🔍MagnifyGlass.BorderColor\": DEFAULT_BORDER_COLOR,\n \"🔍MagnifyGlass.BorderWidth\": DEFAULT_BORDER_WIDTH,\n \"🔍MagnifyGlass.ActivationKey\": \"x\",\n \"🔍MagnifyGlass.AltRequired\": false,\n \"🔍MagnifyGlass.FollowCursor\": false,\n \"🔍MagnifyGlass.OffsetStep\": DEFAULT_OFFSET_STEP,\n \"🔍MagnifyGlass.GlassPosition\": \"Top-Right\",\n \"🔍MagnifyGlass.ResetKey\": \"o\",\n \"🔍MagnifyGlass.GlassShape\": \"Rounded Square\",\n \"🔍MagnifyGlass.BorderEnabled\": true,\n \"🔍MagnifyGlass.TextureFiltering\": \"Linear\",\n \"🔍MagnifyGlass.AlwaysActiveMode\": true,\n \"🔍MagnifyGlass.ToggleFollowCursorKey\": \"h\",\n \"🔍MagnifyGlass.ShowCursorPreview\": false,\n \"🔍MagnifyGlass.ForceDirectCaptureKey\": \"d\",\n};\n\n/**\n * Default settings for the info panel component.\n */\nexport const DEFAULT_PANEL_SETTINGS: PanelSettings = {\n \"🔍MagnifyGlass.InfoPanelEnabled\": true,\n \"🔍MagnifyGlass.InfoPanelPosition\": \"Bottom\",\n \"🔍MagnifyGlass.InfoPanelWidth\": DEFAULT_PANEL_WIDTH,\n \"🔍MagnifyGlass.InfoPanelOpacity\": DEFAULT_PANEL_OPACITY,\n \"🔍MagnifyGlass.InfoPanelMaxHeight\": DEFAULT_PANEL_MAX_HEIGHT,\n \"🔍MagnifyGlass.InfoPanelAnimations\": false,\n \"🔍MagnifyGlass.ShowInspectorTab\": false,\n \"🔍MagnifyGlass.ToggleHotkey\": \"i\",\n \"🔍MagnifyGlass.GlassPreviewToggleHotkey\": \"g\",\n \"🔍MagnifyGlass.PinPanelHotkey\": \"u\",\n \"🔍MagnifyGlass.ShowHoveringControls\": true,\n \"🔍MagnifyGlass.ControlsPosition\": \"left\",\n \"🔍MagnifyGlass.InfoPanelTextColor\": \"#6b7280\",\n \"🔍MagnifyGlass.InfoPanelAccentColor\": \"#3b82f6\",\n \"🔍MagnifyGlass.InfoPanelFontSize\": 14,\n \"🔍MagnifyGlass.InfoPanelFontFamily\": \"System Default\",\n \"🔍MagnifyGlass.InfoPanelPersist\": false,\n};\n"],"names":[],"mappings":";AAqBO,MAAM,yBAAwC;AAAA,EACjD,6BAA6B;AAAA,EAC7B,4BAA4B;AAAA,EAC5B,8BAA8B;AAAA,EAC9B,8BAA8B;AAAA,EAC9B,gCAAgC;AAAA,EAChC,8BAA8B;AAAA,EAC9B,+BAA+B;AAAA,EAC/B,6BAA6B;AAAA,EAC7B,gCAAgC;AAAA,EAChC,2BAA2B;AAAA,EAC3B,6BAA6B;AAAA,EAC7B,gCAAgC;AAAA,EAChC,mCAAmC;AAAA,EACnC,mCAAmC;AAAA,EACnC,wCAAwC;AAAA,EACxC,oCAAoC;AAExC;AAKO,MAAM,yBAAwC;AAAA,EACjD,mCAAmC;AAAA,EACnC,oCAAoC;AAAA,EACpC,iCAAiC;AAAA,EACjC,mCAAmC;AAAA,EACnC,qCAAqC;AAAA,EACrC,sCAAsC;AAAA,EACtC,mCAAmC;AAAA,EACnC,+BAA+B;AAAA,EAC/B,2CAA2C;AAAA,EAC3C,iCAAiC;AAAA,EACjC,uCAAuC;AAAA,EACvC,mCAAmC;AAAA,EACnC,qCAAqC;AAAA,EACrC,uCAAuC;AAAA,EACvC,oCAAoC;AAAA,EACpC,sCAAsC;AAAA,EACtC,mCAAmC;AACvC;"} \ No newline at end of file +{"version":3,"file":"defaults.js","sources":["../../../src/shared/settings/defaults.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - Default Settings Values\n * \n * Default values for all magnify glass and info panel settings.\n */\n\nimport {\n DEFAULT_GLASS_SIZE,\n DEFAULT_ZOOM_FACTOR,\n DEFAULT_BORDER_WIDTH,\n DEFAULT_BORDER_COLOR,\n DEFAULT_OFFSET_STEP,\n DEFAULT_PANEL_WIDTH,\n DEFAULT_PANEL_MAX_HEIGHT,\n DEFAULT_PANEL_OPACITY\n} from '../constants';\nimport type { GlassSettings, PanelSettings } from './types';\n\n/**\n * Default settings for the magnify glass component.\n */\nexport const DEFAULT_GLASS_SETTINGS: GlassSettings = {\n \"🔍MagnifyGlass.ZoomFactor\": DEFAULT_ZOOM_FACTOR,\n \"🔍MagnifyGlass.GlassSize\": DEFAULT_GLASS_SIZE,\n \"🔍MagnifyGlass.BorderColor\": DEFAULT_BORDER_COLOR,\n \"🔍MagnifyGlass.BorderWidth\": DEFAULT_BORDER_WIDTH,\n \"🔍MagnifyGlass.ActivationKey\": \"x\",\n \"🔍MagnifyGlass.AltRequired\": false,\n \"🔍MagnifyGlass.FollowCursor\": false,\n \"🔍MagnifyGlass.OffsetStep\": DEFAULT_OFFSET_STEP,\n \"🔍MagnifyGlass.GlassPosition\": \"Top-Right\",\n \"🔍MagnifyGlass.ResetKey\": \"o\",\n \"🔍MagnifyGlass.GlassShape\": \"Rounded Square\",\n \"🔍MagnifyGlass.BorderEnabled\": true,\n \"🔍MagnifyGlass.TextureFiltering\": \"Linear\",\n \"🔍MagnifyGlass.AlwaysActiveMode\": true,\n \"🔍MagnifyGlass.ToggleFollowCursorKey\": \"h\",\n \"🔍MagnifyGlass.ShowCursorPreview\": false,\n \"🔍MagnifyGlass.ForceDirectCaptureKey\": \"d\",\n \"🔍MagnifyGlass.ForceDirectCapture\": false,\n};\n\n/**\n * Default settings for the info panel component.\n */\nexport const DEFAULT_PANEL_SETTINGS: PanelSettings = {\n \"🔍MagnifyGlass.InfoPanelEnabled\": true,\n \"🔍MagnifyGlass.InfoPanelPosition\": \"Bottom\",\n \"🔍MagnifyGlass.InfoPanelWidth\": DEFAULT_PANEL_WIDTH,\n \"🔍MagnifyGlass.InfoPanelOpacity\": DEFAULT_PANEL_OPACITY,\n \"🔍MagnifyGlass.InfoPanelMaxHeight\": DEFAULT_PANEL_MAX_HEIGHT,\n \"🔍MagnifyGlass.InfoPanelAnimations\": false,\n \"🔍MagnifyGlass.ShowInspectorTab\": false,\n \"🔍MagnifyGlass.ToggleHotkey\": \"i\",\n \"🔍MagnifyGlass.GlassPreviewToggleHotkey\": \"g\",\n \"🔍MagnifyGlass.PinPanelHotkey\": \"u\",\n \"🔍MagnifyGlass.ShowHoveringControls\": true,\n \"🔍MagnifyGlass.ControlsPosition\": \"left\",\n \"🔍MagnifyGlass.InfoPanelTextColor\": \"#6b7280\",\n \"🔍MagnifyGlass.InfoPanelAccentColor\": \"#3b82f6\",\n \"🔍MagnifyGlass.InfoPanelFontSize\": 14,\n \"🔍MagnifyGlass.InfoPanelFontFamily\": \"System Default\",\n \"🔍MagnifyGlass.InfoPanelPersist\": false,\n};\n"],"names":[],"mappings":";AAqBO,MAAM,yBAAwC;AAAA,EACjD,6BAA6B;AAAA,EAC7B,4BAA4B;AAAA,EAC5B,8BAA8B;AAAA,EAC9B,8BAA8B;AAAA,EAC9B,gCAAgC;AAAA,EAChC,8BAA8B;AAAA,EAC9B,+BAA+B;AAAA,EAC/B,6BAA6B;AAAA,EAC7B,gCAAgC;AAAA,EAChC,2BAA2B;AAAA,EAC3B,6BAA6B;AAAA,EAC7B,gCAAgC;AAAA,EAChC,mCAAmC;AAAA,EACnC,mCAAmC;AAAA,EACnC,wCAAwC;AAAA,EACxC,oCAAoC;AAAA,EAEpC,qCAAqC;AACzC;AAKO,MAAM,yBAAwC;AAAA,EACjD,mCAAmC;AAAA,EACnC,oCAAoC;AAAA,EACpC,iCAAiC;AAAA,EACjC,mCAAmC;AAAA,EACnC,qCAAqC;AAAA,EACrC,sCAAsC;AAAA,EACtC,mCAAmC;AAAA,EACnC,+BAA+B;AAAA,EAC/B,2CAA2C;AAAA,EAC3C,iCAAiC;AAAA,EACjC,uCAAuC;AAAA,EACvC,mCAAmC;AAAA,EACnC,qCAAqC;AAAA,EACrC,uCAAuC;AAAA,EACvC,oCAAoC;AAAA,EACpC,sCAAsC;AAAA,EACtC,mCAAmC;AACvC;"} \ No newline at end of file diff --git a/web/shared/settings/glassSettings.js b/web/shared/settings/glassSettings.js index 81cbbc9..a6039ce 100644 --- a/web/shared/settings/glassSettings.js +++ b/web/shared/settings/glassSettings.js @@ -252,6 +252,22 @@ function registerGlassSettings(magnifyGlass) { } } }); + app.ui.settings.addSetting({ + id: "🔍MagnifyGlass.ForceDirectCapture", + name: "⚡ Magnify Glass: Force Direct Capture", + type: "combo", + options: [{ value: true, text: "Yes" }, { value: false, text: "No" }], + defaultValue: settings["🔍MagnifyGlass.ForceDirectCapture"], + tooltip: "Force usage of Direct Capture mode even at low zoom levels.", + onChange: (value) => { + if (magnifyGlass == null ? void 0 : magnifyGlass.config) { + magnifyGlass.config.forceDirectCapture = !!value; + if (magnifyGlass.state.active) { + magnifyGlass.updateMagnifiedView(); + } + } + } + }); app.ui.settings.addSetting({ id: "🔍MagnifyGlass.Action.ResetPosition", name: "🔄 Magnify Glass: Reset Position", @@ -296,7 +312,9 @@ function registerGlassSettings(magnifyGlass) { app.ui.settings.setSettingValue("🔍MagnifyGlass.ToggleFollowCursorKey", "h"); app.ui.settings.setSettingValue("🔍MagnifyGlass.AltRequired", false); app.ui.settings.setSettingValue("🔍MagnifyGlass.OffsetStep", 5); + app.ui.settings.setSettingValue("🔍MagnifyGlass.OffsetStep", 5); app.ui.settings.setSettingValue("🔍MagnifyGlass.ShowCursorPreview", false); + app.ui.settings.setSettingValue("🔍MagnifyGlass.ForceDirectCapture", false); app.ui.settings.setSettingValue("🔍MagnifyGlass.InfoPanelEnabled", true); app.ui.settings.setSettingValue("🔍MagnifyGlass.InfoPanelPosition", "Bottom"); app.ui.settings.setSettingValue("🔍MagnifyGlass.InfoPanelWidth", 300); diff --git a/web/shared/settings/glassSettings.js.map b/web/shared/settings/glassSettings.js.map index 11f68e4..6672a72 100644 --- a/web/shared/settings/glassSettings.js.map +++ b/web/shared/settings/glassSettings.js.map @@ -1 +1 @@ -{"version":3,"file":"glassSettings.js","sources":["../../../src/shared/settings/glassSettings.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - Glass Settings Registration\n * \n * Registers all magnify glass settings with ComfyUI.\n */\n\n// @ts-ignore\nimport { app } from \"/scripts/app.js\";\nimport {\n GLASS_POSITIONS,\n GLASS_SHAPES,\n ACTIVATION_KEYS,\n RESET_KEYS,\n TOGGLE_FOLLOW_KEYS\n} from '../constants';\nimport { DEFAULT_GLASS_SETTINGS } from './defaults';\n\n/**\n * Register all magnify glass settings with ComfyUI.\n * @param magnifyGlass - The MagnifyGlass instance\n */\nexport function registerGlassSettings(magnifyGlass: any): void {\n const settings = DEFAULT_GLASS_SETTINGS;\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ZoomFactor\",\n name: \"🔍 Magnify Glass: Zoom Factor (%)\",\n type: \"slider\",\n defaultValue: settings[\"🔍MagnifyGlass.ZoomFactor\"],\n min: 100,\n max: 1000,\n step: 25,\n tooltip: \"Magnification level as a percentage (e.g., 300 = 3x zoom, 150 = 1.5x zoom).\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.zoomFactor = typeof value === 'number' ? value / 100 : parseFloat(value) / 100;\n if (magnifyGlass.state.active) {\n magnifyGlass.updateMagnifiedView();\n }\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.GlassSize\",\n name: \"🔍 Magnify Glass: Size (px)\",\n type: \"slider\",\n defaultValue: settings[\"🔍MagnifyGlass.GlassSize\"],\n min: 50,\n max: 100,\n step: 10,\n tooltip: \"Diameter of the magnifying glass circle in pixels.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.glassSize = parseInt(String(value), 10);\n magnifyGlass.applyUiChanges();\n if (magnifyGlass.state.active) {\n magnifyGlass.updateMagnifiedView();\n }\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.BorderWidth\",\n name: \"🔍 Magnify Glass: Border Width (px)\",\n type: \"slider\",\n defaultValue: settings[\"🔍MagnifyGlass.BorderWidth\"],\n min: 0,\n max: 10,\n step: 0.1,\n tooltip: \"Width of the border around the magnifying glass.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.borderWidth = parseFloat(String(value));\n magnifyGlass.applyUiChanges();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.BorderColor\",\n name: \"🎨 Magnify Glass: Border Color\",\n type: \"color\",\n defaultValue: settings[\"🔍MagnifyGlass.BorderColor\"],\n tooltip: \"Color of the border around the magnifying glass.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n const strValue = String(value);\n const normalizedColor = strValue && !strValue.startsWith('#') ? `#${strValue}` : strValue;\n magnifyGlass.config.borderColor = normalizedColor;\n if (strValue !== normalizedColor) {\n try {\n app.ui.settings.setSettingValue(\"🔍MagnifyGlass.BorderColor\", normalizedColor);\n } catch (e) {\n console.warn('Failed to save normalized border color:', e);\n }\n }\n magnifyGlass.applyUiChanges();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ActivationKey\",\n name: \"⌨️ Magnify Glass: Activation Key\",\n type: \"combo\",\n options: ACTIVATION_KEYS.map(k => ({ value: k, text: k })),\n defaultValue: settings[\"🔍MagnifyGlass.ActivationKey\"],\n tooltip: \"The key to activate the magnifier.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.activationKey = String(value).toLowerCase();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.AltRequired\",\n name: \"⌨️ Magnify Glass: Require Alt/Option Key\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.AltRequired\"],\n tooltip: \"If Yes, Alt (Windows/Linux) or Option (Mac) must be held for activation.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.altRequired = !!value;\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.FollowCursor\",\n name: \"🖱️ Magnify Glass: Follow Cursor Position\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.FollowCursor\"],\n tooltip: \"If Yes, the magnifier window moves with the cursor.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.followCursor = !!value;\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.OffsetStep\",\n name: \"⌨️ Magnify Glass: Offset Adjust Step\",\n type: \"slider\",\n defaultValue: settings[\"🔍MagnifyGlass.OffsetStep\"],\n min: 1,\n max: 50,\n step: 1,\n tooltip: \"How many graph units the view shifts when pressing arrow keys.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.offsetStep = parseInt(String(value), 10);\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ResetKey\",\n name: \"⌨️ Magnify Glass: Reset Offset Key\",\n type: \"combo\",\n options: RESET_KEYS.map(k => ({ value: k, text: k })),\n defaultValue: settings[\"🔍MagnifyGlass.ResetKey\"],\n tooltip: \"The key to reset the magnify glass offset to default.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.resetKey = String(value).toLowerCase();\n }\n }\n });\n\n\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.GlassPosition\",\n name: \"🖱️ Magnify Glass: Glass Position\",\n type: \"combo\",\n options: GLASS_POSITIONS.map(p => ({ value: p, text: p === \"Bottom\" ? \"Bottom (Default)\" : p })),\n defaultValue: settings[\"🔍MagnifyGlass.GlassPosition\"],\n tooltip: \"Position of the magnifying glass relative to the cursor.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.glassPosition = String(value);\n if (magnifyGlass.state.active && !magnifyGlass.config.followCursor) {\n const { x, y } = magnifyGlass.lastKnownMousePosition;\n magnifyGlass.ui.positionGlass(x, y);\n }\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.GlassShape\",\n name: \"🖼️ Magnify Glass: Shape\",\n type: \"combo\",\n options: GLASS_SHAPES.map(s => ({ value: s, text: s })),\n defaultValue: settings[\"🔍MagnifyGlass.GlassShape\"],\n tooltip: \"Shape of the magnifying glass.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.glassShape = String(value);\n magnifyGlass.applyUiChanges();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.BorderEnabled\",\n name: \"🖼️ Magnify Glass: Show Border\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.BorderEnabled\"],\n tooltip: \"Enable or disable the border around the magnifying glass.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.borderEnabled = !!value;\n magnifyGlass.applyUiChanges();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.TextureFiltering\",\n name: \"🖼️ Magnify Glass: Texture Filtering\",\n type: \"combo\",\n options: [\n { value: \"Linear\", text: \"Linear (Smooth)\" },\n { value: \"Nearest\", text: \"Nearest (Pixelated)\" }\n ],\n defaultValue: settings[\"🔍MagnifyGlass.TextureFiltering\"],\n tooltip: \"Controls how the magnified image is scaled.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config && magnifyGlass.renderer) {\n magnifyGlass.config.textureFiltering = String(value);\n magnifyGlass.renderer.updateTextureFiltering(value);\n if (magnifyGlass.state.active) {\n magnifyGlass.updateMagnifiedView();\n }\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.AlwaysActiveMode\",\n name: \"🔒 Magnify Glass: Always Active Mode\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.AlwaysActiveMode\"],\n tooltip: \"If Yes, activating the magnifier keeps it on until activated again.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.alwaysActiveMode = !!value;\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ToggleFollowCursorKey\",\n name: \"🔑 Magnify Glass: Toggle Follow Key\",\n type: \"combo\",\n options: TOGGLE_FOLLOW_KEYS.map(k => ({ value: k, text: k })),\n defaultValue: settings[\"🔍MagnifyGlass.ToggleFollowCursorKey\"],\n tooltip: \"The key to toggle the 'Follow Cursor' behavior.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.toggleFollowCursorKey = String(value).toLowerCase();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ShowCursorPreview\",\n name: \"🖱️ Magnify Glass: Show Cursor Preview\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.ShowCursorPreview\"] ?? false,\n tooltip: \"Show a mini cursor in the glass preview to indicate the cursor position.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.showCursorPreview = !!value;\n if (magnifyGlass.state.active) {\n magnifyGlass.updateMagnifiedView();\n }\n }\n }\n });\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.Action.ResetPosition\",\n name: \"🔄 Magnify Glass: Reset Position\",\n type: \"boolean\",\n defaultValue: false,\n tooltip: \"Toggle to reset the glass position and disable follow cursor.\",\n onChange: (value: any) => {\n if (value) {\n if (magnifyGlass?.resetOffsets) {\n magnifyGlass.resetOffsets();\n }\n // Reset the toggle back to false\n setTimeout(() => {\n try {\n app.ui.settings.setSettingValue(\"🔍MagnifyGlass.Action.ResetPosition\", false);\n } catch (e) { /* ignore */ }\n }, 500);\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.Action.ResetAll\",\n name: \"⚠️ Magnify Glass: Reset ALL Settings\",\n type: \"boolean\",\n defaultValue: false,\n tooltip: \"Toggle to reset ALL settings to defaults.\",\n onChange: (value: any) => {\n if (value) {\n if (confirm(\"Reset ALL Magnify Glass settings?\")) {\n // Glass Defaults\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ZoomFactor', 300);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.GlassSize', 300);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.GlassShape', 'Rounded Square');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.GlassPosition', 'Top-Right');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.TextureFiltering', 'Linear');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.BorderWidth', 1);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.BorderColor', '#6b7280');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.BorderEnabled', true);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.FollowCursor', false);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.AlwaysActiveMode', true);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ActivationKey', 'x');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ResetKey', 'o');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.AltRequired', false);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.OffsetStep', 5);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ShowCursorPreview', false);\n\n\n // Panel Defaults\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelEnabled', true);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelPosition', 'Bottom');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelWidth', 300);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', 300);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelOpacity', 100);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelTextColor', '#6b7280');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', '#3b82f6');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelAnimations', false);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ShowHoveringControls', true);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ControlsPosition', 'left');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u');\n\n // Also force position reset\n if (magnifyGlass?.resetOffsets) {\n magnifyGlass.resetOffsets();\n }\n }\n\n // Reset the toggle back to false\n setTimeout(() => {\n try {\n app.ui.settings.setSettingValue(\"🔍MagnifyGlass.Action.ResetAll\", false);\n } catch (e) { /* ignore */ }\n }, 500);\n }\n }\n });\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"glassSettings.js","sources":["../../../src/shared/settings/glassSettings.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - Glass Settings Registration\n * \n * Registers all magnify glass settings with ComfyUI.\n */\n\n// @ts-ignore\nimport { app } from \"/scripts/app.js\";\nimport {\n GLASS_POSITIONS,\n GLASS_SHAPES,\n ACTIVATION_KEYS,\n RESET_KEYS,\n TOGGLE_FOLLOW_KEYS\n} from '../constants';\nimport { DEFAULT_GLASS_SETTINGS } from './defaults';\n\n/**\n * Register all magnify glass settings with ComfyUI.\n * @param magnifyGlass - The MagnifyGlass instance\n */\nexport function registerGlassSettings(magnifyGlass: any): void {\n const settings = DEFAULT_GLASS_SETTINGS;\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ZoomFactor\",\n name: \"🔍 Magnify Glass: Zoom Factor (%)\",\n type: \"slider\",\n defaultValue: settings[\"🔍MagnifyGlass.ZoomFactor\"],\n min: 100,\n max: 1000,\n step: 25,\n tooltip: \"Magnification level as a percentage (e.g., 300 = 3x zoom, 150 = 1.5x zoom).\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.zoomFactor = typeof value === 'number' ? value / 100 : parseFloat(value) / 100;\n if (magnifyGlass.state.active) {\n magnifyGlass.updateMagnifiedView();\n }\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.GlassSize\",\n name: \"🔍 Magnify Glass: Size (px)\",\n type: \"slider\",\n defaultValue: settings[\"🔍MagnifyGlass.GlassSize\"],\n min: 50,\n max: 100,\n step: 10,\n tooltip: \"Diameter of the magnifying glass circle in pixels.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.glassSize = parseInt(String(value), 10);\n magnifyGlass.applyUiChanges();\n if (magnifyGlass.state.active) {\n magnifyGlass.updateMagnifiedView();\n }\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.BorderWidth\",\n name: \"🔍 Magnify Glass: Border Width (px)\",\n type: \"slider\",\n defaultValue: settings[\"🔍MagnifyGlass.BorderWidth\"],\n min: 0,\n max: 10,\n step: 0.1,\n tooltip: \"Width of the border around the magnifying glass.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.borderWidth = parseFloat(String(value));\n magnifyGlass.applyUiChanges();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.BorderColor\",\n name: \"🎨 Magnify Glass: Border Color\",\n type: \"color\",\n defaultValue: settings[\"🔍MagnifyGlass.BorderColor\"],\n tooltip: \"Color of the border around the magnifying glass.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n const strValue = String(value);\n const normalizedColor = strValue && !strValue.startsWith('#') ? `#${strValue}` : strValue;\n magnifyGlass.config.borderColor = normalizedColor;\n if (strValue !== normalizedColor) {\n try {\n app.ui.settings.setSettingValue(\"🔍MagnifyGlass.BorderColor\", normalizedColor);\n } catch (e) {\n console.warn('Failed to save normalized border color:', e);\n }\n }\n magnifyGlass.applyUiChanges();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ActivationKey\",\n name: \"⌨️ Magnify Glass: Activation Key\",\n type: \"combo\",\n options: ACTIVATION_KEYS.map(k => ({ value: k, text: k })),\n defaultValue: settings[\"🔍MagnifyGlass.ActivationKey\"],\n tooltip: \"The key to activate the magnifier.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.activationKey = String(value).toLowerCase();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.AltRequired\",\n name: \"⌨️ Magnify Glass: Require Alt/Option Key\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.AltRequired\"],\n tooltip: \"If Yes, Alt (Windows/Linux) or Option (Mac) must be held for activation.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.altRequired = !!value;\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.FollowCursor\",\n name: \"🖱️ Magnify Glass: Follow Cursor Position\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.FollowCursor\"],\n tooltip: \"If Yes, the magnifier window moves with the cursor.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.followCursor = !!value;\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.OffsetStep\",\n name: \"⌨️ Magnify Glass: Offset Adjust Step\",\n type: \"slider\",\n defaultValue: settings[\"🔍MagnifyGlass.OffsetStep\"],\n min: 1,\n max: 50,\n step: 1,\n tooltip: \"How many graph units the view shifts when pressing arrow keys.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.offsetStep = parseInt(String(value), 10);\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ResetKey\",\n name: \"⌨️ Magnify Glass: Reset Offset Key\",\n type: \"combo\",\n options: RESET_KEYS.map(k => ({ value: k, text: k })),\n defaultValue: settings[\"🔍MagnifyGlass.ResetKey\"],\n tooltip: \"The key to reset the magnify glass offset to default.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.resetKey = String(value).toLowerCase();\n }\n }\n });\n\n\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.GlassPosition\",\n name: \"🖱️ Magnify Glass: Glass Position\",\n type: \"combo\",\n options: GLASS_POSITIONS.map(p => ({ value: p, text: p === \"Bottom\" ? \"Bottom (Default)\" : p })),\n defaultValue: settings[\"🔍MagnifyGlass.GlassPosition\"],\n tooltip: \"Position of the magnifying glass relative to the cursor.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.glassPosition = String(value);\n if (magnifyGlass.state.active && !magnifyGlass.config.followCursor) {\n const { x, y } = magnifyGlass.lastKnownMousePosition;\n magnifyGlass.ui.positionGlass(x, y);\n }\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.GlassShape\",\n name: \"🖼️ Magnify Glass: Shape\",\n type: \"combo\",\n options: GLASS_SHAPES.map(s => ({ value: s, text: s })),\n defaultValue: settings[\"🔍MagnifyGlass.GlassShape\"],\n tooltip: \"Shape of the magnifying glass.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.glassShape = String(value);\n magnifyGlass.applyUiChanges();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.BorderEnabled\",\n name: \"🖼️ Magnify Glass: Show Border\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.BorderEnabled\"],\n tooltip: \"Enable or disable the border around the magnifying glass.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.borderEnabled = !!value;\n magnifyGlass.applyUiChanges();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.TextureFiltering\",\n name: \"🖼️ Magnify Glass: Texture Filtering\",\n type: \"combo\",\n options: [\n { value: \"Linear\", text: \"Linear (Smooth)\" },\n { value: \"Nearest\", text: \"Nearest (Pixelated)\" }\n ],\n defaultValue: settings[\"🔍MagnifyGlass.TextureFiltering\"],\n tooltip: \"Controls how the magnified image is scaled.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config && magnifyGlass.renderer) {\n magnifyGlass.config.textureFiltering = String(value);\n magnifyGlass.renderer.updateTextureFiltering(value);\n if (magnifyGlass.state.active) {\n magnifyGlass.updateMagnifiedView();\n }\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.AlwaysActiveMode\",\n name: \"🔒 Magnify Glass: Always Active Mode\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.AlwaysActiveMode\"],\n tooltip: \"If Yes, activating the magnifier keeps it on until activated again.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.alwaysActiveMode = !!value;\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ToggleFollowCursorKey\",\n name: \"🔑 Magnify Glass: Toggle Follow Key\",\n type: \"combo\",\n options: TOGGLE_FOLLOW_KEYS.map(k => ({ value: k, text: k })),\n defaultValue: settings[\"🔍MagnifyGlass.ToggleFollowCursorKey\"],\n tooltip: \"The key to toggle the 'Follow Cursor' behavior.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.toggleFollowCursorKey = String(value).toLowerCase();\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ShowCursorPreview\",\n name: \"🖱️ Magnify Glass: Show Cursor Preview\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.ShowCursorPreview\"] ?? false,\n tooltip: \"Show a mini cursor in the glass preview to indicate the cursor position.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n magnifyGlass.config.showCursorPreview = !!value;\n if (magnifyGlass.state.active) {\n magnifyGlass.updateMagnifiedView();\n }\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.ForceDirectCapture\",\n name: \"⚡ Magnify Glass: Force Direct Capture\",\n type: \"combo\",\n options: [{ value: true, text: \"Yes\" }, { value: false, text: \"No\" }],\n defaultValue: settings[\"🔍MagnifyGlass.ForceDirectCapture\"] ?? false,\n tooltip: \"Force usage of Direct Capture mode even at low zoom levels.\",\n onChange: (value: any) => {\n if (magnifyGlass?.config) {\n // Update runtime flag\n magnifyGlass.config.forceDirectCapture = !!value;\n if (magnifyGlass.state.active) {\n magnifyGlass.updateMagnifiedView();\n }\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.Action.ResetPosition\",\n name: \"🔄 Magnify Glass: Reset Position\",\n type: \"boolean\",\n defaultValue: false,\n tooltip: \"Toggle to reset the glass position and disable follow cursor.\",\n onChange: (value: any) => {\n if (value) {\n if (magnifyGlass?.resetOffsets) {\n magnifyGlass.resetOffsets();\n }\n // Reset the toggle back to false\n setTimeout(() => {\n try {\n app.ui.settings.setSettingValue(\"🔍MagnifyGlass.Action.ResetPosition\", false);\n } catch (e) { /* ignore */ }\n }, 500);\n }\n }\n });\n\n app.ui.settings.addSetting({\n id: \"🔍MagnifyGlass.Action.ResetAll\",\n name: \"⚠️ Magnify Glass: Reset ALL Settings\",\n type: \"boolean\",\n defaultValue: false,\n tooltip: \"Toggle to reset ALL settings to defaults.\",\n onChange: (value: any) => {\n if (value) {\n if (confirm(\"Reset ALL Magnify Glass settings?\")) {\n // Glass Defaults\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ZoomFactor', 300);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.GlassSize', 300);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.GlassShape', 'Rounded Square');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.GlassPosition', 'Top-Right');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.TextureFiltering', 'Linear');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.BorderWidth', 1);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.BorderColor', '#6b7280');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.BorderEnabled', true);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.FollowCursor', false);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.AlwaysActiveMode', true);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ActivationKey', 'x');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ResetKey', 'o');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.AltRequired', false);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.OffsetStep', 5);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.OffsetStep', 5);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ShowCursorPreview', false);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ForceDirectCapture', false);\n\n\n // Panel Defaults\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelEnabled', true);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelPosition', 'Bottom');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelWidth', 300);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', 300);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelOpacity', 100);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelTextColor', '#6b7280');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', '#3b82f6');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.InfoPanelAnimations', false);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ShowHoveringControls', true);\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ControlsPosition', 'left');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g');\n app.ui.settings.setSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u');\n\n // Also force position reset\n if (magnifyGlass?.resetOffsets) {\n magnifyGlass.resetOffsets();\n }\n }\n\n // Reset the toggle back to false\n setTimeout(() => {\n try {\n app.ui.settings.setSettingValue(\"🔍MagnifyGlass.Action.ResetAll\", false);\n } catch (e) { /* ignore */ }\n }, 500);\n }\n }\n });\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/web/sidebar/SidebarSettings.js b/web/sidebar/SidebarSettings.js index 3fdc1b9..d0c0e43 100644 --- a/web/sidebar/SidebarSettings.js +++ b/web/sidebar/SidebarSettings.js @@ -256,6 +256,12 @@ function renderSettingsPanel(container) { (checked) => setSettingValue("🔍MagnifyGlass.AlwaysActiveMode", checked), `When enabled, glass stays visible. Toggle with ${activationKey}` )); + glassSection.body.appendChild(createToggle( + "Force Direct Capture", + getSettingValue("🔍MagnifyGlass.ForceDirectCapture", false), + (checked) => setSettingValue("🔍MagnifyGlass.ForceDirectCapture", checked), + `Force Direct Capture mode (accurate, pixel-perfect). Hotkey: ${getSettingValue("🔍MagnifyGlass.ForceDirectCaptureKey", "d").toUpperCase()}` + )); glassSection.body.appendChild(createToggle( "Show Mini Cursor", getSettingValue("🔍MagnifyGlass.ShowCursorPreview", false), diff --git a/web/sidebar/SidebarSettings.js.map b/web/sidebar/SidebarSettings.js.map index 1f1fb31..779d410 100644 --- a/web/sidebar/SidebarSettings.js.map +++ b/web/sidebar/SidebarSettings.js.map @@ -1 +1 @@ -{"version":3,"file":"SidebarSettings.js","sources":["../../src/sidebar/SidebarSettings.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - Sidebar Settings Panel\n * \n * All settings controls for the sidebar.\n */\n\n// @ts-ignore\nimport { app } from \"/scripts/app.js\";\nimport {\n GLASS_POSITIONS,\n GLASS_SHAPES,\n ACTIVATION_KEYS,\n RESET_KEYS,\n TOGGLE_FOLLOW_KEYS,\n PANEL_POSITIONS\n} from '../shared/constants';\n\n/**\n * Icons for the settings panel\n */\nconst Icons = {\n chevronDown: ``,\n reset: ``,\n};\n\n/**\n * Create a slider control with tooltip\n */\n/**\n * Create a slider control with tooltip\n */\nfunction createSlider(\n label: string,\n value: number,\n min: number,\n max: number,\n step: number,\n unit: string,\n onChange: (value: number) => void,\n tooltip?: string,\n onInput?: (value: number) => void\n): HTMLElement {\n const row = document.createElement('div');\n row.className = 'magnify-control-row';\n if (tooltip) row.title = tooltip;\n\n const labelRow = document.createElement('div');\n labelRow.className = 'magnify-control-label-row';\n\n const labelEl = document.createElement('label');\n labelEl.textContent = label;\n\n const valueEl = document.createElement('span');\n valueEl.className = 'control-value';\n valueEl.textContent = `${value}${unit}`;\n\n labelRow.appendChild(labelEl);\n labelRow.appendChild(valueEl);\n\n const slider = document.createElement('input');\n slider.type = 'range';\n slider.className = 'magnify-slider';\n slider.min = String(min);\n slider.max = String(max);\n slider.step = String(step);\n slider.value = String(value);\n\n // Prevent ComfyUI from capturing mouse events during drag\n slider.addEventListener('mousedown', (e) => e.stopPropagation());\n slider.addEventListener('touchstart', (e) => e.stopPropagation());\n slider.addEventListener('pointerdown', (e) => e.stopPropagation());\n\n slider.addEventListener('input', (e) => {\n e.stopPropagation();\n const newValue = parseFloat(slider.value);\n valueEl.textContent = `${newValue}${unit}`;\n if (onInput) onInput(newValue);\n });\n\n slider.addEventListener('change', (e) => {\n e.stopPropagation();\n const newValue = parseFloat(slider.value);\n onChange(newValue);\n });\n\n row.appendChild(labelRow);\n row.appendChild(slider);\n\n return row;\n}\n\n/**\n * Create a toggle control with tooltip\n */\nfunction createToggle(\n label: string,\n checked: boolean,\n onChange: (checked: boolean) => void,\n tooltip?: string\n): HTMLElement {\n const row = document.createElement('div');\n row.className = 'magnify-toggle-row';\n if (tooltip) row.title = tooltip;\n\n const labelEl = document.createElement('label');\n labelEl.textContent = label;\n\n const toggle = document.createElement('div');\n toggle.className = `magnify-toggle${checked ? ' active' : ''}`;\n\n toggle.addEventListener('click', () => {\n const isActive = toggle.classList.toggle('active');\n onChange(isActive);\n });\n\n row.appendChild(labelEl);\n row.appendChild(toggle);\n\n return row;\n}\n\n/**\n * Create a select dropdown control with tooltip\n */\nfunction createSelect(\n label: string,\n value: string,\n options: readonly string[] | string[],\n onChange: (value: string) => void,\n tooltip?: string,\n onInput?: (value: string) => void\n): HTMLElement {\n const row = document.createElement('div');\n row.className = 'magnify-control-row';\n if (tooltip) row.title = tooltip;\n\n const labelEl = document.createElement('label');\n labelEl.textContent = label;\n\n const select = document.createElement('select');\n select.className = 'magnify-select';\n\n options.forEach(opt => {\n const option = document.createElement('option');\n option.value = opt;\n option.textContent = opt;\n if (opt === value) option.selected = true;\n select.appendChild(option);\n });\n\n select.addEventListener('change', () => {\n // Call onInput first for live preview\n if (onInput) {\n onInput(select.value);\n }\n // Then persist the setting\n onChange(select.value);\n });\n\n row.appendChild(labelEl);\n row.appendChild(select);\n\n return row;\n}\n\n/**\n * Create a color picker control with tooltip\n */\n/**\n * Create a color picker control with tooltip\n */\nfunction createColorPicker(\n label: string,\n value: string,\n onChange: (value: string) => void,\n tooltip?: string,\n onInput?: (value: string) => void\n): HTMLElement {\n const row = document.createElement('div');\n row.className = 'magnify-control-row magnify-color-row';\n if (tooltip) row.title = tooltip;\n\n const labelEl = document.createElement('label');\n labelEl.textContent = label;\n\n const colorWrapper = document.createElement('div');\n colorWrapper.className = 'magnify-color-wrapper';\n\n const colorInput = document.createElement('input');\n colorInput.type = 'color';\n colorInput.className = 'magnify-color-input';\n colorInput.value = value;\n\n const colorPreview = document.createElement('span');\n colorPreview.className = 'magnify-color-preview';\n colorPreview.textContent = value;\n\n colorInput.addEventListener('input', () => {\n colorPreview.textContent = colorInput.value;\n if (onInput) onInput(colorInput.value);\n });\n\n colorInput.addEventListener('change', () => {\n onChange(colorInput.value);\n });\n\n colorWrapper.appendChild(colorInput);\n colorWrapper.appendChild(colorPreview);\n\n row.appendChild(labelEl);\n row.appendChild(colorWrapper);\n\n return row;\n}\n\n/**\n * Get current MagnifyGlass settings from app.ui.settings\n */\nfunction getSettingValue(id: string, defaultValue: any): any {\n try {\n const value = app.ui.settings.getSettingValue(id);\n return value !== undefined ? value : defaultValue;\n } catch {\n return defaultValue;\n }\n}\n\n/**\n * Set a MagnifyGlass setting via app.ui.settings\n */\nfunction setSettingValue(id: string, value: any): void {\n try {\n app.ui.settings.setSettingValue(id, value);\n } catch (e) {\n console.warn(`Failed to set setting ${id}:`, e);\n }\n}\n\n/** Storage key for section states */\nconst SECTION_STATE_KEY = 'magnifyglass-sidebar-sections';\n\n/**\n * Get saved section states from localStorage\n */\nfunction getSectionStates(): Record {\n try {\n const saved = localStorage.getItem(SECTION_STATE_KEY);\n return saved ? JSON.parse(saved) : {};\n } catch {\n return {};\n }\n}\n\n/**\n * Save section state to localStorage\n */\nfunction saveSectionState(title: string, collapsed: boolean): void {\n try {\n const states = getSectionStates();\n states[title] = collapsed;\n localStorage.setItem(SECTION_STATE_KEY, JSON.stringify(states));\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Create a collapsible section with persistent state\n */\nfunction createSection(title: string, defaultCollapsed: boolean = false): { section: HTMLElement; body: HTMLElement } {\n const section = document.createElement('div');\n section.className = 'magnify-sidebar-section';\n\n // Check if we have a saved state for this section\n // User requested to disable persistence: \"tabs should refresh, so they don't remain all opened\"\n // const savedStates = getSectionStates();\n // const collapsed = savedStates[title] !== undefined ? savedStates[title] : defaultCollapsed;\n const collapsed = defaultCollapsed;\n\n const header = document.createElement('div');\n header.className = `magnify-sidebar-section-header${collapsed ? ' collapsed' : ''}`;\n header.innerHTML = `${Icons.chevronDown}${title}`;\n\n const body = document.createElement('div');\n body.className = `magnify-sidebar-section-body${collapsed ? ' collapsed' : ''}`;\n // Apply inline style to prevent flash before CSS loads\n if (collapsed) {\n body.style.display = 'none';\n }\n\n header.addEventListener('click', () => {\n const isCollapsed = header.classList.toggle('collapsed');\n body.classList.toggle('collapsed');\n // Also toggle inline style for immediate effect\n body.style.display = isCollapsed ? 'none' : '';\n // Save the new state\n // User requested to disable persistence\n // saveSectionState(title, isCollapsed);\n });\n\n section.appendChild(header);\n section.appendChild(body);\n\n return { section, body };\n}\n\n/**\n * Render the settings panel into the container\n */\nexport function renderSettingsPanel(container: HTMLElement): void {\n // Get current hotkey values for tooltips\n const activationKey = getSettingValue('🔍MagnifyGlass.ActivationKey', 'x').toUpperCase();\n const resetKey = getSettingValue('🔍MagnifyGlass.ResetKey', 'o').toUpperCase();\n const toggleFollowKey = getSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h').toUpperCase();\n\n // ===== Glass Settings Section =====\n // Use true (collapsed) by default as requested\n const glassSection = createSection('Glass Settings', true);\n\n glassSection.body.appendChild(createSlider('Zoom Factor',\n getSettingValue('🔍MagnifyGlass.ZoomFactor', 300), 100, 1000, 25, '%',\n (value) => setSettingValue('🔍MagnifyGlass.ZoomFactor', value),\n 'Magnification level of the glass (100-1000%)',\n (value) => {\n const mg = (window as any).comfyUIMagnifyGlass;\n if (mg?.config) {\n mg.config.zoomFactor = value / 100;\n if (mg.state.active) mg.updateMagnifiedView();\n }\n }\n ));\n\n glassSection.body.appendChild(createSlider('Glass Size',\n getSettingValue('🔍MagnifyGlass.GlassSize', 250), 50, 500, 10, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.GlassSize', value),\n 'Size of the magnifying glass in pixels',\n (value) => {\n const mg = (window as any).comfyUIMagnifyGlass;\n if (mg?.config) {\n mg.config.glassSize = value;\n mg.applyUiChanges();\n if (mg.state.active) mg.updateMagnifiedView();\n }\n }\n ));\n\n glassSection.body.appendChild(createSelect('Shape',\n getSettingValue('🔍MagnifyGlass.GlassShape', 'Rounded Square'), GLASS_SHAPES,\n (value) => setSettingValue('🔍MagnifyGlass.GlassShape', value),\n 'Shape of the magnifying glass'\n ));\n\n glassSection.body.appendChild(createSelect('Position',\n getSettingValue('🔍MagnifyGlass.GlassPosition', 'Top-Right'), GLASS_POSITIONS,\n (value) => setSettingValue('🔍MagnifyGlass.GlassPosition', value),\n `Default position of the glass. Press ${resetKey} to reset.`\n ));\n\n glassSection.body.appendChild(createSelect('Filtering',\n getSettingValue('🔍MagnifyGlass.TextureFiltering', 'Linear'), ['Linear', 'Nearest'],\n (value) => setSettingValue('🔍MagnifyGlass.TextureFiltering', value),\n 'Texture filtering: Linear (smooth) or Nearest (pixelated)'\n ));\n\n glassSection.body.appendChild(createSlider('Border Width',\n getSettingValue('🔍MagnifyGlass.BorderWidth', 2), 0, 10, 0.5, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.BorderWidth', value),\n 'Width of the glass border in pixels',\n (value) => {\n const mg = (window as any).comfyUIMagnifyGlass;\n if (mg?.config) {\n mg.config.borderWidth = value;\n mg.applyUiChanges();\n }\n }\n ));\n\n glassSection.body.appendChild(createColorPicker('Border Color',\n getSettingValue('🔍MagnifyGlass.BorderColor', '#ffffff'),\n (value) => setSettingValue('🔍MagnifyGlass.BorderColor', value),\n 'Color of the glass border',\n (value) => {\n const mg = (window as any).comfyUIMagnifyGlass;\n if (mg?.config) {\n mg.config.borderColor = value;\n mg.applyUiChanges();\n }\n }\n ));\n\n glassSection.body.appendChild(createToggle('Show Border',\n getSettingValue('🔍MagnifyGlass.BorderEnabled', true),\n (checked) => setSettingValue('🔍MagnifyGlass.BorderEnabled', checked),\n 'Show or hide the glass border'\n ));\n\n glassSection.body.appendChild(createToggle('Follow Cursor',\n getSettingValue('🔍MagnifyGlass.FollowCursor', false),\n (checked) => setSettingValue('🔍MagnifyGlass.FollowCursor', checked),\n `Glass follows the cursor. Hotkey: ${toggleFollowKey}`\n ));\n\n glassSection.body.appendChild(createToggle('Always Active Mode',\n getSettingValue('🔍MagnifyGlass.AlwaysActiveMode', true),\n (checked) => setSettingValue('🔍MagnifyGlass.AlwaysActiveMode', checked),\n `When enabled, glass stays visible. Toggle with ${activationKey}`\n ));\n\n glassSection.body.appendChild(createToggle('Show Mini Cursor',\n getSettingValue('🔍MagnifyGlass.ShowCursorPreview', false),\n (checked) => setSettingValue('🔍MagnifyGlass.ShowCursorPreview', checked),\n 'Display a mini cursor in the glass preview'\n ));\n\n // The instruction implies this should be in glassSection, but the content suggests info panel.\n // Placing it in glassSection as per instruction, assuming createToggle is intended.\n // The condition `if (getSettingValue(\"🔍MagnifyGlass.InfoPanelEnabled\", true))` is removed\n // as it doesn't make sense for a glass setting to depend on info panel being enabled.\n // The tooltip and callback logic are kept as provided.\n // Moved to panel settings section\n // glassSection.body.appendChild(createToggle('Persist Info'...));\n\n container.appendChild(glassSection.section);\n\n // ===== Glass Hotkeys Section =====\n const hotkeySection = createSection('Glass Hotkeys', true);\n\n hotkeySection.body.appendChild(createSelect('Activation Key',\n getSettingValue('🔍MagnifyGlass.ActivationKey', 'x'), ACTIVATION_KEYS,\n (value) => setSettingValue('🔍MagnifyGlass.ActivationKey', value),\n 'Key to toggle or hold to activate the magnifying glass'\n ));\n\n hotkeySection.body.appendChild(createSelect('Reset Key',\n getSettingValue('🔍MagnifyGlass.ResetKey', 'o'), RESET_KEYS,\n (value) => setSettingValue('🔍MagnifyGlass.ResetKey', value),\n 'Key to reset glass position and disable follow cursor'\n ));\n\n hotkeySection.body.appendChild(createSelect('Toggle Follow Key',\n getSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h'), TOGGLE_FOLLOW_KEYS,\n (value) => setSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', value),\n 'Key to toggle follow cursor mode'\n ));\n\n const glassAltToggle = createToggle('Require Alt Key',\n getSettingValue('🔍MagnifyGlass.AltRequired', false),\n (checked) => {\n setSettingValue('🔍MagnifyGlass.AltRequired', checked);\n // Sync all alt toggles\n container.querySelectorAll('.magnify-alt-toggle .magnify-toggle').forEach(t => {\n if (checked) t.classList.add('active');\n else t.classList.remove('active');\n });\n },\n 'Require Alt key to be held with activation key'\n );\n glassAltToggle.classList.add('magnify-alt-toggle');\n hotkeySection.body.appendChild(glassAltToggle);\n\n // Moved to Panel Hotkeys section\n // hotkeySection.body.appendChild(createToggle('Require Alt Key'...));\n\n hotkeySection.body.appendChild(createSlider('Offset Step',\n getSettingValue('🔍MagnifyGlass.OffsetStep', 10), 1, 50, 1, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.OffsetStep', value),\n 'Amount to move glass per arrow key press (pixels)'\n ));\n\n container.appendChild(hotkeySection.section);\n\n // ===== Info Panel Section =====\n const panelSection = createSection('Info Panel', true);\n\n const toggleHotkey = getSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i').toUpperCase();\n const glassToggleKey = getSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g').toUpperCase();\n const pinHotkeyVal = getSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u').toUpperCase();\n\n panelSection.body.appendChild(createToggle('Enable Panel',\n getSettingValue('🔍MagnifyGlass.InfoPanelEnabled', true),\n (checked) => setSettingValue('🔍MagnifyGlass.InfoPanelEnabled', checked),\n `Show info panel with node details. Toggle: ${toggleHotkey}`\n ));\n\n panelSection.body.appendChild(createToggle('Persist Info',\n getSettingValue('🔍MagnifyGlass.InfoPanelPersist', false),\n (checked) => {\n setSettingValue('🔍MagnifyGlass.InfoPanelPersist', checked);\n // Sync with UI controls if needed\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.uiManager) {\n infoPanel.uiManager.updateControlStates();\n }\n },\n 'Keep displaying the last node info when hovering empty space'\n ));\n\n panelSection.body.appendChild(createSelect('Position',\n getSettingValue('🔍MagnifyGlass.InfoPanelPosition', 'Bottom'), PANEL_POSITIONS,\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelPosition', value),\n 'Position of the info panel relative to the glass'\n ));\n\n panelSection.body.appendChild(createSlider('Width',\n getSettingValue('🔍MagnifyGlass.InfoPanelWidth', 300), 200, 600, 20, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelWidth', value),\n 'Width of the info panel',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelWidth'] = value;\n infoPanel.uiManager.applyStyles();\n\n // Ensure visible and reflow if active\n if (infoPanel.magnifyGlass.state.active) {\n infoPanel.uiManager.show();\n infoPanel.positionManager.positionPanel();\n }\n }\n }\n ));\n\n panelSection.body.appendChild(createSlider('Max Height',\n getSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', 300), 200, 1500, 50, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', value),\n 'Maximum height of the info panel',\n (value) => {\n console.log('[MaxHeight] Handler called with value:', value);\n const infoPanel = (window as any).infoPanelManager;\n console.log('[MaxHeight] infoPanelManager:', infoPanel ? 'found' : 'NOT FOUND');\n if (infoPanel?.stateManager?.state?.settings) {\n console.log('[MaxHeight] Updating setting and calling applyStyles');\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelMaxHeight'] = value;\n infoPanel.uiManager.applyStyles();\n\n // Ensure visible and reflow if active\n if (infoPanel.magnifyGlass.state.active) {\n console.log('[MaxHeight] Glass is active, calling show() and positionPanel()');\n infoPanel.uiManager.show();\n infoPanel.positionManager.positionPanel();\n } else {\n console.log('[MaxHeight] Glass is NOT active, skipping show()');\n }\n } else {\n console.warn('[MaxHeight] Check failed - stateManager/state/settings missing');\n }\n }\n ));\n\n panelSection.body.appendChild(createSlider('Font Size',\n getSettingValue('🔍MagnifyGlass.InfoPanelFontSize', 14), 8, 24, 1, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelFontSize', value),\n 'Font size of text in the info panel',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelFontSize'] = value;\n infoPanel.uiManager.applyStyles();\n }\n }\n ));\n\n panelSection.body.appendChild(createSlider('Opacity',\n getSettingValue('🔍MagnifyGlass.InfoPanelOpacity', 95), 10, 100, 5, '%',\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelOpacity', value),\n 'Background opacity of the info panel',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelOpacity'] = value;\n infoPanel.uiManager.applyStyles();\n }\n }\n ));\n\n const fontFamilyOptions = [\n 'System Default', 'Inter', 'Roboto', 'JetBrains Mono', 'Fira Code',\n 'IBM Plex Sans', 'Space Grotesk', 'Lexend', 'Outfit', 'monospace'\n ];\n panelSection.body.appendChild(createSelect('Font Family',\n getSettingValue('🔍MagnifyGlass.InfoPanelFontFamily', 'System Default'), fontFamilyOptions,\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelFontFamily', value),\n 'Font family for the info panel text',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelFontFamily'] = value;\n infoPanel.uiManager.applyStyles();\n }\n }\n ));\n\n panelSection.body.appendChild(createColorPicker('Text Color',\n getSettingValue('🔍MagnifyGlass.InfoPanelTextColor', '#6b7280'),\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelTextColor', value),\n 'Text color in the info panel',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelTextColor'] = value;\n infoPanel.uiManager.applyStyles();\n }\n }\n ));\n\n panelSection.body.appendChild(createColorPicker('Accent Color',\n getSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', '#3b82f6'),\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', value),\n 'Accent color for highlights',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelAccentColor'] = value;\n infoPanel.uiManager.applyStyles();\n }\n }\n ));\n\n panelSection.body.appendChild(createToggle('Hover Controls',\n getSettingValue('🔍MagnifyGlass.ShowHoveringControls', true),\n (checked) => setSettingValue('🔍MagnifyGlass.ShowHoveringControls', checked),\n 'Show floating control buttons near the panel'\n ));\n\n panelSection.body.appendChild(createSelect('Controls Position',\n getSettingValue('🔍MagnifyGlass.ControlsPosition', 'left'),\n ['top', 'bottom', 'left', 'right', 'top-left', 'top-right', 'bottom-left', 'bottom-right'],\n (value) => setSettingValue('🔍MagnifyGlass.ControlsPosition', value),\n 'Position of floating control buttons',\n (value) => {\n // Live update controls position\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.ControlsPosition'] = value;\n infoPanel.uiManager.updateControlsLayout(value);\n if (infoPanel.magnifyGlass.state.active) {\n infoPanel.positionManager.positionFloatingControls();\n }\n }\n }\n ));\n\n container.appendChild(panelSection.section);\n\n // ===== Panel Hotkeys Section =====\n const panelHotkeySection = createSection('Panel Hotkeys', true);\n\n panelHotkeySection.body.appendChild(createSelect('Toggle Key',\n getSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i'), ['i', 'j', 'k', 'l', 'n', 'm'],\n (value) => setSettingValue('🔍MagnifyGlass.ToggleHotkey', value),\n 'Key to toggle info panel visibility'\n ));\n\n panelHotkeySection.body.appendChild(createSelect('Glass Toggle Key',\n getSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g'), ['g', 'f', 'v', 'b'],\n (value) => setSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', value),\n 'Key to toggle glass preview in panel'\n ));\n\n panelHotkeySection.body.appendChild(createSelect('Pin Key',\n getSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u'), ['u', 'p', 'y', 't'],\n (value) => setSettingValue('🔍MagnifyGlass.PinPanelHotkey', value),\n 'Key to pin/unpin the info panel position'\n ));\n\n const panelAltToggle = createToggle('Require Alt Key',\n getSettingValue('🔍MagnifyGlass.AltRequired', false),\n (checked) => {\n setSettingValue('🔍MagnifyGlass.AltRequired', checked);\n // Sync all alt toggles\n container.querySelectorAll('.magnify-alt-toggle .magnify-toggle').forEach(t => {\n if (checked) t.classList.add('active');\n else t.classList.remove('active');\n });\n },\n 'Require Alt key to be held with hotkeys'\n );\n panelAltToggle.classList.add('magnify-alt-toggle');\n panelHotkeySection.body.appendChild(panelAltToggle);\n\n container.appendChild(panelHotkeySection.section);\n\n\n\n // ===== Button Row =====\n const buttonRow = document.createElement('div');\n buttonRow.style.padding = '16px';\n buttonRow.style.borderTop = '1px solid var(--border-color, #333)';\n buttonRow.style.display = 'flex';\n buttonRow.style.flexDirection = 'column';\n buttonRow.style.gap = '8px';\n\n // Reset Position Button\n const resetBtn = document.createElement('button');\n resetBtn.className = 'magnify-btn';\n resetBtn.style.width = '100%';\n resetBtn.innerHTML = `${Icons.reset} Reset Position`;\n resetBtn.title = `Reset glass position and disable follow cursor. Hotkey: ${resetKey}`;\n\n resetBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n const magnifyGlass = window.comfyUIMagnifyGlass;\n if (magnifyGlass && magnifyGlass.resetOffsets) {\n magnifyGlass.resetOffsets();\n // Update follow cursor toggle in UI\n const followToggles = container.querySelectorAll('.magnify-toggle-row');\n followToggles.forEach(row => {\n const label = row.querySelector('label');\n if (label && label.textContent === 'Follow Cursor') {\n const toggle = row.querySelector('.magnify-toggle');\n if (toggle) toggle.classList.remove('active');\n }\n });\n }\n });\n\n buttonRow.appendChild(resetBtn);\n\n // Reset All Settings Button\n const resetAllBtn = document.createElement('button');\n resetAllBtn.className = 'magnify-btn magnify-btn-secondary';\n resetAllBtn.style.width = '100%';\n resetAllBtn.innerHTML = `${Icons.reset} Reset All Settings`;\n resetAllBtn.title = 'Reset all settings to their default values';\n\n resetAllBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n\n // Confirm with user\n if (!confirm('Reset all MagnifyGlass settings to defaults?')) {\n return;\n }\n\n // Default glass settings\n setSettingValue('🔍MagnifyGlass.ZoomFactor', 300);\n setSettingValue('🔍MagnifyGlass.GlassSize', 300);\n setSettingValue('🔍MagnifyGlass.GlassShape', 'Rounded Square');\n setSettingValue('🔍MagnifyGlass.GlassPosition', 'Top-Right');\n setSettingValue('🔍MagnifyGlass.TextureFiltering', 'Linear');\n setSettingValue('🔍MagnifyGlass.BorderWidth', 1);\n setSettingValue('🔍MagnifyGlass.BorderColor', '#6b7280');\n setSettingValue('🔍MagnifyGlass.BorderEnabled', true);\n setSettingValue('🔍MagnifyGlass.FollowCursor', false);\n setSettingValue('🔍MagnifyGlass.AlwaysActiveMode', true);\n setSettingValue('🔍MagnifyGlass.ActivationKey', 'x');\n setSettingValue('🔍MagnifyGlass.ResetKey', 'o');\n setSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h');\n setSettingValue('🔍MagnifyGlass.AltRequired', false);\n setSettingValue('🔍MagnifyGlass.OffsetStep', 5);\n setSettingValue('🔍MagnifyGlass.ShowCursorPreview', false);\n\n\n // Default panel settings\n setSettingValue('🔍MagnifyGlass.InfoPanelEnabled', true);\n setSettingValue('🔍MagnifyGlass.InfoPanelPosition', 'Bottom');\n setSettingValue('🔍MagnifyGlass.InfoPanelWidth', 300);\n setSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', 300);\n setSettingValue('🔍MagnifyGlass.InfoPanelOpacity', 100);\n setSettingValue('🔍MagnifyGlass.InfoPanelFontSize', 14);\n setSettingValue('🔍MagnifyGlass.InfoPanelFontFamily', 'System Default');\n setSettingValue('🔍MagnifyGlass.InfoPanelPersist', false);\n setSettingValue('🔍MagnifyGlass.InfoPanelTextColor', '#6b7280');\n setSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', '#3b82f6');\n setSettingValue('🔍MagnifyGlass.InfoPanelAnimations', false);\n setSettingValue('🔍MagnifyGlass.ShowHoveringControls', true);\n setSettingValue('🔍MagnifyGlass.ControlsPosition', 'left');\n setSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i');\n setSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g');\n setSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u');\n\n // Also reset position\n const magnifyGlass = window.comfyUIMagnifyGlass;\n if (magnifyGlass && magnifyGlass.resetOffsets) {\n magnifyGlass.resetOffsets();\n }\n });\n\n buttonRow.appendChild(resetAllBtn);\n container.appendChild(buttonRow);\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"SidebarSettings.js","sources":["../../src/sidebar/SidebarSettings.ts"],"sourcesContent":["/**\n * ComfyUI MagnifyGlass - Sidebar Settings Panel\n * \n * All settings controls for the sidebar.\n */\n\n// @ts-ignore\nimport { app } from \"/scripts/app.js\";\nimport {\n GLASS_POSITIONS,\n GLASS_SHAPES,\n ACTIVATION_KEYS,\n RESET_KEYS,\n TOGGLE_FOLLOW_KEYS,\n PANEL_POSITIONS\n} from '../shared/constants';\n\n/**\n * Icons for the settings panel\n */\nconst Icons = {\n chevronDown: ``,\n reset: ``,\n};\n\n/**\n * Create a slider control with tooltip\n */\n/**\n * Create a slider control with tooltip\n */\nfunction createSlider(\n label: string,\n value: number,\n min: number,\n max: number,\n step: number,\n unit: string,\n onChange: (value: number) => void,\n tooltip?: string,\n onInput?: (value: number) => void\n): HTMLElement {\n const row = document.createElement('div');\n row.className = 'magnify-control-row';\n if (tooltip) row.title = tooltip;\n\n const labelRow = document.createElement('div');\n labelRow.className = 'magnify-control-label-row';\n\n const labelEl = document.createElement('label');\n labelEl.textContent = label;\n\n const valueEl = document.createElement('span');\n valueEl.className = 'control-value';\n valueEl.textContent = `${value}${unit}`;\n\n labelRow.appendChild(labelEl);\n labelRow.appendChild(valueEl);\n\n const slider = document.createElement('input');\n slider.type = 'range';\n slider.className = 'magnify-slider';\n slider.min = String(min);\n slider.max = String(max);\n slider.step = String(step);\n slider.value = String(value);\n\n // Prevent ComfyUI from capturing mouse events during drag\n slider.addEventListener('mousedown', (e) => e.stopPropagation());\n slider.addEventListener('touchstart', (e) => e.stopPropagation());\n slider.addEventListener('pointerdown', (e) => e.stopPropagation());\n\n slider.addEventListener('input', (e) => {\n e.stopPropagation();\n const newValue = parseFloat(slider.value);\n valueEl.textContent = `${newValue}${unit}`;\n if (onInput) onInput(newValue);\n });\n\n slider.addEventListener('change', (e) => {\n e.stopPropagation();\n const newValue = parseFloat(slider.value);\n onChange(newValue);\n });\n\n row.appendChild(labelRow);\n row.appendChild(slider);\n\n return row;\n}\n\n/**\n * Create a toggle control with tooltip\n */\nfunction createToggle(\n label: string,\n checked: boolean,\n onChange: (checked: boolean) => void,\n tooltip?: string\n): HTMLElement {\n const row = document.createElement('div');\n row.className = 'magnify-toggle-row';\n if (tooltip) row.title = tooltip;\n\n const labelEl = document.createElement('label');\n labelEl.textContent = label;\n\n const toggle = document.createElement('div');\n toggle.className = `magnify-toggle${checked ? ' active' : ''}`;\n\n toggle.addEventListener('click', () => {\n const isActive = toggle.classList.toggle('active');\n onChange(isActive);\n });\n\n row.appendChild(labelEl);\n row.appendChild(toggle);\n\n return row;\n}\n\n/**\n * Create a select dropdown control with tooltip\n */\nfunction createSelect(\n label: string,\n value: string,\n options: readonly string[] | string[],\n onChange: (value: string) => void,\n tooltip?: string,\n onInput?: (value: string) => void\n): HTMLElement {\n const row = document.createElement('div');\n row.className = 'magnify-control-row';\n if (tooltip) row.title = tooltip;\n\n const labelEl = document.createElement('label');\n labelEl.textContent = label;\n\n const select = document.createElement('select');\n select.className = 'magnify-select';\n\n options.forEach(opt => {\n const option = document.createElement('option');\n option.value = opt;\n option.textContent = opt;\n if (opt === value) option.selected = true;\n select.appendChild(option);\n });\n\n select.addEventListener('change', () => {\n // Call onInput first for live preview\n if (onInput) {\n onInput(select.value);\n }\n // Then persist the setting\n onChange(select.value);\n });\n\n row.appendChild(labelEl);\n row.appendChild(select);\n\n return row;\n}\n\n/**\n * Create a color picker control with tooltip\n */\n/**\n * Create a color picker control with tooltip\n */\nfunction createColorPicker(\n label: string,\n value: string,\n onChange: (value: string) => void,\n tooltip?: string,\n onInput?: (value: string) => void\n): HTMLElement {\n const row = document.createElement('div');\n row.className = 'magnify-control-row magnify-color-row';\n if (tooltip) row.title = tooltip;\n\n const labelEl = document.createElement('label');\n labelEl.textContent = label;\n\n const colorWrapper = document.createElement('div');\n colorWrapper.className = 'magnify-color-wrapper';\n\n const colorInput = document.createElement('input');\n colorInput.type = 'color';\n colorInput.className = 'magnify-color-input';\n colorInput.value = value;\n\n const colorPreview = document.createElement('span');\n colorPreview.className = 'magnify-color-preview';\n colorPreview.textContent = value;\n\n colorInput.addEventListener('input', () => {\n colorPreview.textContent = colorInput.value;\n if (onInput) onInput(colorInput.value);\n });\n\n colorInput.addEventListener('change', () => {\n onChange(colorInput.value);\n });\n\n colorWrapper.appendChild(colorInput);\n colorWrapper.appendChild(colorPreview);\n\n row.appendChild(labelEl);\n row.appendChild(colorWrapper);\n\n return row;\n}\n\n/**\n * Get current MagnifyGlass settings from app.ui.settings\n */\nfunction getSettingValue(id: string, defaultValue: any): any {\n try {\n const value = app.ui.settings.getSettingValue(id);\n return value !== undefined ? value : defaultValue;\n } catch {\n return defaultValue;\n }\n}\n\n/**\n * Set a MagnifyGlass setting via app.ui.settings\n */\nfunction setSettingValue(id: string, value: any): void {\n try {\n app.ui.settings.setSettingValue(id, value);\n } catch (e) {\n console.warn(`Failed to set setting ${id}:`, e);\n }\n}\n\n/** Storage key for section states */\nconst SECTION_STATE_KEY = 'magnifyglass-sidebar-sections';\n\n/**\n * Get saved section states from localStorage\n */\nfunction getSectionStates(): Record {\n try {\n const saved = localStorage.getItem(SECTION_STATE_KEY);\n return saved ? JSON.parse(saved) : {};\n } catch {\n return {};\n }\n}\n\n/**\n * Save section state to localStorage\n */\nfunction saveSectionState(title: string, collapsed: boolean): void {\n try {\n const states = getSectionStates();\n states[title] = collapsed;\n localStorage.setItem(SECTION_STATE_KEY, JSON.stringify(states));\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Create a collapsible section with persistent state\n */\nfunction createSection(title: string, defaultCollapsed: boolean = false): { section: HTMLElement; body: HTMLElement } {\n const section = document.createElement('div');\n section.className = 'magnify-sidebar-section';\n\n // Check if we have a saved state for this section\n // User requested to disable persistence: \"tabs should refresh, so they don't remain all opened\"\n // const savedStates = getSectionStates();\n // const collapsed = savedStates[title] !== undefined ? savedStates[title] : defaultCollapsed;\n const collapsed = defaultCollapsed;\n\n const header = document.createElement('div');\n header.className = `magnify-sidebar-section-header${collapsed ? ' collapsed' : ''}`;\n header.innerHTML = `${Icons.chevronDown}${title}`;\n\n const body = document.createElement('div');\n body.className = `magnify-sidebar-section-body${collapsed ? ' collapsed' : ''}`;\n // Apply inline style to prevent flash before CSS loads\n if (collapsed) {\n body.style.display = 'none';\n }\n\n header.addEventListener('click', () => {\n const isCollapsed = header.classList.toggle('collapsed');\n body.classList.toggle('collapsed');\n // Also toggle inline style for immediate effect\n body.style.display = isCollapsed ? 'none' : '';\n // Save the new state\n // User requested to disable persistence\n // saveSectionState(title, isCollapsed);\n });\n\n section.appendChild(header);\n section.appendChild(body);\n\n return { section, body };\n}\n\n/**\n * Render the settings panel into the container\n */\nexport function renderSettingsPanel(container: HTMLElement): void {\n // Get current hotkey values for tooltips\n const activationKey = getSettingValue('🔍MagnifyGlass.ActivationKey', 'x').toUpperCase();\n const resetKey = getSettingValue('🔍MagnifyGlass.ResetKey', 'o').toUpperCase();\n const toggleFollowKey = getSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h').toUpperCase();\n\n // ===== Glass Settings Section =====\n // Use true (collapsed) by default as requested\n const glassSection = createSection('Glass Settings', true);\n\n glassSection.body.appendChild(createSlider('Zoom Factor',\n getSettingValue('🔍MagnifyGlass.ZoomFactor', 300), 100, 1000, 25, '%',\n (value) => setSettingValue('🔍MagnifyGlass.ZoomFactor', value),\n 'Magnification level of the glass (100-1000%)',\n (value) => {\n const mg = (window as any).comfyUIMagnifyGlass;\n if (mg?.config) {\n mg.config.zoomFactor = value / 100;\n if (mg.state.active) mg.updateMagnifiedView();\n }\n }\n ));\n\n glassSection.body.appendChild(createSlider('Glass Size',\n getSettingValue('🔍MagnifyGlass.GlassSize', 250), 50, 500, 10, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.GlassSize', value),\n 'Size of the magnifying glass in pixels',\n (value) => {\n const mg = (window as any).comfyUIMagnifyGlass;\n if (mg?.config) {\n mg.config.glassSize = value;\n mg.applyUiChanges();\n if (mg.state.active) mg.updateMagnifiedView();\n }\n }\n ));\n\n glassSection.body.appendChild(createSelect('Shape',\n getSettingValue('🔍MagnifyGlass.GlassShape', 'Rounded Square'), GLASS_SHAPES,\n (value) => setSettingValue('🔍MagnifyGlass.GlassShape', value),\n 'Shape of the magnifying glass'\n ));\n\n glassSection.body.appendChild(createSelect('Position',\n getSettingValue('🔍MagnifyGlass.GlassPosition', 'Top-Right'), GLASS_POSITIONS,\n (value) => setSettingValue('🔍MagnifyGlass.GlassPosition', value),\n `Default position of the glass. Press ${resetKey} to reset.`\n ));\n\n glassSection.body.appendChild(createSelect('Filtering',\n getSettingValue('🔍MagnifyGlass.TextureFiltering', 'Linear'), ['Linear', 'Nearest'],\n (value) => setSettingValue('🔍MagnifyGlass.TextureFiltering', value),\n 'Texture filtering: Linear (smooth) or Nearest (pixelated)'\n ));\n\n glassSection.body.appendChild(createSlider('Border Width',\n getSettingValue('🔍MagnifyGlass.BorderWidth', 2), 0, 10, 0.5, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.BorderWidth', value),\n 'Width of the glass border in pixels',\n (value) => {\n const mg = (window as any).comfyUIMagnifyGlass;\n if (mg?.config) {\n mg.config.borderWidth = value;\n mg.applyUiChanges();\n }\n }\n ));\n\n glassSection.body.appendChild(createColorPicker('Border Color',\n getSettingValue('🔍MagnifyGlass.BorderColor', '#ffffff'),\n (value) => setSettingValue('🔍MagnifyGlass.BorderColor', value),\n 'Color of the glass border',\n (value) => {\n const mg = (window as any).comfyUIMagnifyGlass;\n if (mg?.config) {\n mg.config.borderColor = value;\n mg.applyUiChanges();\n }\n }\n ));\n\n glassSection.body.appendChild(createToggle('Show Border',\n getSettingValue('🔍MagnifyGlass.BorderEnabled', true),\n (checked) => setSettingValue('🔍MagnifyGlass.BorderEnabled', checked),\n 'Show or hide the glass border'\n ));\n\n glassSection.body.appendChild(createToggle('Follow Cursor',\n getSettingValue('🔍MagnifyGlass.FollowCursor', false),\n (checked) => setSettingValue('🔍MagnifyGlass.FollowCursor', checked),\n `Glass follows the cursor. Hotkey: ${toggleFollowKey}`\n ));\n\n glassSection.body.appendChild(createToggle('Always Active Mode',\n getSettingValue('🔍MagnifyGlass.AlwaysActiveMode', true),\n (checked) => setSettingValue('🔍MagnifyGlass.AlwaysActiveMode', checked),\n `When enabled, glass stays visible. Toggle with ${activationKey}`\n ));\n\n glassSection.body.appendChild(createToggle('Force Direct Capture',\n getSettingValue('🔍MagnifyGlass.ForceDirectCapture', false),\n (checked) => setSettingValue('🔍MagnifyGlass.ForceDirectCapture', checked),\n `Force Direct Capture mode (accurate, pixel-perfect). Hotkey: ${getSettingValue('🔍MagnifyGlass.ForceDirectCaptureKey', 'd').toUpperCase()}`\n ));\n\n glassSection.body.appendChild(createToggle('Show Mini Cursor',\n getSettingValue('🔍MagnifyGlass.ShowCursorPreview', false),\n (checked) => setSettingValue('🔍MagnifyGlass.ShowCursorPreview', checked),\n 'Display a mini cursor in the glass preview'\n ));\n\n // The instruction implies this should be in glassSection, but the content suggests info panel.\n // Placing it in glassSection as per instruction, assuming createToggle is intended.\n // The condition `if (getSettingValue(\"🔍MagnifyGlass.InfoPanelEnabled\", true))` is removed\n // as it doesn't make sense for a glass setting to depend on info panel being enabled.\n // The tooltip and callback logic are kept as provided.\n // Moved to panel settings section\n // glassSection.body.appendChild(createToggle('Persist Info'...));\n\n container.appendChild(glassSection.section);\n\n // ===== Glass Hotkeys Section =====\n const hotkeySection = createSection('Glass Hotkeys', true);\n\n hotkeySection.body.appendChild(createSelect('Activation Key',\n getSettingValue('🔍MagnifyGlass.ActivationKey', 'x'), ACTIVATION_KEYS,\n (value) => setSettingValue('🔍MagnifyGlass.ActivationKey', value),\n 'Key to toggle or hold to activate the magnifying glass'\n ));\n\n hotkeySection.body.appendChild(createSelect('Reset Key',\n getSettingValue('🔍MagnifyGlass.ResetKey', 'o'), RESET_KEYS,\n (value) => setSettingValue('🔍MagnifyGlass.ResetKey', value),\n 'Key to reset glass position and disable follow cursor'\n ));\n\n hotkeySection.body.appendChild(createSelect('Toggle Follow Key',\n getSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h'), TOGGLE_FOLLOW_KEYS,\n (value) => setSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', value),\n 'Key to toggle follow cursor mode'\n ));\n\n const glassAltToggle = createToggle('Require Alt Key',\n getSettingValue('🔍MagnifyGlass.AltRequired', false),\n (checked) => {\n setSettingValue('🔍MagnifyGlass.AltRequired', checked);\n // Sync all alt toggles\n container.querySelectorAll('.magnify-alt-toggle .magnify-toggle').forEach(t => {\n if (checked) t.classList.add('active');\n else t.classList.remove('active');\n });\n },\n 'Require Alt key to be held with activation key'\n );\n glassAltToggle.classList.add('magnify-alt-toggle');\n hotkeySection.body.appendChild(glassAltToggle);\n\n // Moved to Panel Hotkeys section\n // hotkeySection.body.appendChild(createToggle('Require Alt Key'...));\n\n hotkeySection.body.appendChild(createSlider('Offset Step',\n getSettingValue('🔍MagnifyGlass.OffsetStep', 10), 1, 50, 1, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.OffsetStep', value),\n 'Amount to move glass per arrow key press (pixels)'\n ));\n\n container.appendChild(hotkeySection.section);\n\n // ===== Info Panel Section =====\n const panelSection = createSection('Info Panel', true);\n\n const toggleHotkey = getSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i').toUpperCase();\n const glassToggleKey = getSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g').toUpperCase();\n const pinHotkeyVal = getSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u').toUpperCase();\n\n panelSection.body.appendChild(createToggle('Enable Panel',\n getSettingValue('🔍MagnifyGlass.InfoPanelEnabled', true),\n (checked) => setSettingValue('🔍MagnifyGlass.InfoPanelEnabled', checked),\n `Show info panel with node details. Toggle: ${toggleHotkey}`\n ));\n\n panelSection.body.appendChild(createToggle('Persist Info',\n getSettingValue('🔍MagnifyGlass.InfoPanelPersist', false),\n (checked) => {\n setSettingValue('🔍MagnifyGlass.InfoPanelPersist', checked);\n // Sync with UI controls if needed\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.uiManager) {\n infoPanel.uiManager.updateControlStates();\n }\n },\n 'Keep displaying the last node info when hovering empty space'\n ));\n\n panelSection.body.appendChild(createSelect('Position',\n getSettingValue('🔍MagnifyGlass.InfoPanelPosition', 'Bottom'), PANEL_POSITIONS,\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelPosition', value),\n 'Position of the info panel relative to the glass'\n ));\n\n panelSection.body.appendChild(createSlider('Width',\n getSettingValue('🔍MagnifyGlass.InfoPanelWidth', 300), 200, 600, 20, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelWidth', value),\n 'Width of the info panel',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelWidth'] = value;\n infoPanel.uiManager.applyStyles();\n\n // Ensure visible and reflow if active\n if (infoPanel.magnifyGlass.state.active) {\n infoPanel.uiManager.show();\n infoPanel.positionManager.positionPanel();\n }\n }\n }\n ));\n\n panelSection.body.appendChild(createSlider('Max Height',\n getSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', 300), 200, 1500, 50, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', value),\n 'Maximum height of the info panel',\n (value) => {\n console.log('[MaxHeight] Handler called with value:', value);\n const infoPanel = (window as any).infoPanelManager;\n console.log('[MaxHeight] infoPanelManager:', infoPanel ? 'found' : 'NOT FOUND');\n if (infoPanel?.stateManager?.state?.settings) {\n console.log('[MaxHeight] Updating setting and calling applyStyles');\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelMaxHeight'] = value;\n infoPanel.uiManager.applyStyles();\n\n // Ensure visible and reflow if active\n if (infoPanel.magnifyGlass.state.active) {\n console.log('[MaxHeight] Glass is active, calling show() and positionPanel()');\n infoPanel.uiManager.show();\n infoPanel.positionManager.positionPanel();\n } else {\n console.log('[MaxHeight] Glass is NOT active, skipping show()');\n }\n } else {\n console.warn('[MaxHeight] Check failed - stateManager/state/settings missing');\n }\n }\n ));\n\n panelSection.body.appendChild(createSlider('Font Size',\n getSettingValue('🔍MagnifyGlass.InfoPanelFontSize', 14), 8, 24, 1, 'px',\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelFontSize', value),\n 'Font size of text in the info panel',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelFontSize'] = value;\n infoPanel.uiManager.applyStyles();\n }\n }\n ));\n\n panelSection.body.appendChild(createSlider('Opacity',\n getSettingValue('🔍MagnifyGlass.InfoPanelOpacity', 95), 10, 100, 5, '%',\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelOpacity', value),\n 'Background opacity of the info panel',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelOpacity'] = value;\n infoPanel.uiManager.applyStyles();\n }\n }\n ));\n\n const fontFamilyOptions = [\n 'System Default', 'Inter', 'Roboto', 'JetBrains Mono', 'Fira Code',\n 'IBM Plex Sans', 'Space Grotesk', 'Lexend', 'Outfit', 'monospace'\n ];\n panelSection.body.appendChild(createSelect('Font Family',\n getSettingValue('🔍MagnifyGlass.InfoPanelFontFamily', 'System Default'), fontFamilyOptions,\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelFontFamily', value),\n 'Font family for the info panel text',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelFontFamily'] = value;\n infoPanel.uiManager.applyStyles();\n }\n }\n ));\n\n panelSection.body.appendChild(createColorPicker('Text Color',\n getSettingValue('🔍MagnifyGlass.InfoPanelTextColor', '#6b7280'),\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelTextColor', value),\n 'Text color in the info panel',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelTextColor'] = value;\n infoPanel.uiManager.applyStyles();\n }\n }\n ));\n\n panelSection.body.appendChild(createColorPicker('Accent Color',\n getSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', '#3b82f6'),\n (value) => setSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', value),\n 'Accent color for highlights',\n (value) => {\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelAccentColor'] = value;\n infoPanel.uiManager.applyStyles();\n }\n }\n ));\n\n panelSection.body.appendChild(createToggle('Hover Controls',\n getSettingValue('🔍MagnifyGlass.ShowHoveringControls', true),\n (checked) => setSettingValue('🔍MagnifyGlass.ShowHoveringControls', checked),\n 'Show floating control buttons near the panel'\n ));\n\n panelSection.body.appendChild(createSelect('Controls Position',\n getSettingValue('🔍MagnifyGlass.ControlsPosition', 'left'),\n ['top', 'bottom', 'left', 'right', 'top-left', 'top-right', 'bottom-left', 'bottom-right'],\n (value) => setSettingValue('🔍MagnifyGlass.ControlsPosition', value),\n 'Position of floating control buttons',\n (value) => {\n // Live update controls position\n const infoPanel = (window as any).infoPanelManager;\n if (infoPanel?.stateManager?.state?.settings) {\n infoPanel.stateManager.state.settings['🔍MagnifyGlass.ControlsPosition'] = value;\n infoPanel.uiManager.updateControlsLayout(value);\n if (infoPanel.magnifyGlass.state.active) {\n infoPanel.positionManager.positionFloatingControls();\n }\n }\n }\n ));\n\n container.appendChild(panelSection.section);\n\n // ===== Panel Hotkeys Section =====\n const panelHotkeySection = createSection('Panel Hotkeys', true);\n\n panelHotkeySection.body.appendChild(createSelect('Toggle Key',\n getSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i'), ['i', 'j', 'k', 'l', 'n', 'm'],\n (value) => setSettingValue('🔍MagnifyGlass.ToggleHotkey', value),\n 'Key to toggle info panel visibility'\n ));\n\n panelHotkeySection.body.appendChild(createSelect('Glass Toggle Key',\n getSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g'), ['g', 'f', 'v', 'b'],\n (value) => setSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', value),\n 'Key to toggle glass preview in panel'\n ));\n\n panelHotkeySection.body.appendChild(createSelect('Pin Key',\n getSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u'), ['u', 'p', 'y', 't'],\n (value) => setSettingValue('🔍MagnifyGlass.PinPanelHotkey', value),\n 'Key to pin/unpin the info panel position'\n ));\n\n const panelAltToggle = createToggle('Require Alt Key',\n getSettingValue('🔍MagnifyGlass.AltRequired', false),\n (checked) => {\n setSettingValue('🔍MagnifyGlass.AltRequired', checked);\n // Sync all alt toggles\n container.querySelectorAll('.magnify-alt-toggle .magnify-toggle').forEach(t => {\n if (checked) t.classList.add('active');\n else t.classList.remove('active');\n });\n },\n 'Require Alt key to be held with hotkeys'\n );\n panelAltToggle.classList.add('magnify-alt-toggle');\n panelHotkeySection.body.appendChild(panelAltToggle);\n\n container.appendChild(panelHotkeySection.section);\n\n\n\n // ===== Button Row =====\n const buttonRow = document.createElement('div');\n buttonRow.style.padding = '16px';\n buttonRow.style.borderTop = '1px solid var(--border-color, #333)';\n buttonRow.style.display = 'flex';\n buttonRow.style.flexDirection = 'column';\n buttonRow.style.gap = '8px';\n\n // Reset Position Button\n const resetBtn = document.createElement('button');\n resetBtn.className = 'magnify-btn';\n resetBtn.style.width = '100%';\n resetBtn.innerHTML = `${Icons.reset} Reset Position`;\n resetBtn.title = `Reset glass position and disable follow cursor. Hotkey: ${resetKey}`;\n\n resetBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n const magnifyGlass = window.comfyUIMagnifyGlass;\n if (magnifyGlass && magnifyGlass.resetOffsets) {\n magnifyGlass.resetOffsets();\n // Update follow cursor toggle in UI\n const followToggles = container.querySelectorAll('.magnify-toggle-row');\n followToggles.forEach(row => {\n const label = row.querySelector('label');\n if (label && label.textContent === 'Follow Cursor') {\n const toggle = row.querySelector('.magnify-toggle');\n if (toggle) toggle.classList.remove('active');\n }\n });\n }\n });\n\n buttonRow.appendChild(resetBtn);\n\n // Reset All Settings Button\n const resetAllBtn = document.createElement('button');\n resetAllBtn.className = 'magnify-btn magnify-btn-secondary';\n resetAllBtn.style.width = '100%';\n resetAllBtn.innerHTML = `${Icons.reset} Reset All Settings`;\n resetAllBtn.title = 'Reset all settings to their default values';\n\n resetAllBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n\n // Confirm with user\n if (!confirm('Reset all MagnifyGlass settings to defaults?')) {\n return;\n }\n\n // Default glass settings\n setSettingValue('🔍MagnifyGlass.ZoomFactor', 300);\n setSettingValue('🔍MagnifyGlass.GlassSize', 300);\n setSettingValue('🔍MagnifyGlass.GlassShape', 'Rounded Square');\n setSettingValue('🔍MagnifyGlass.GlassPosition', 'Top-Right');\n setSettingValue('🔍MagnifyGlass.TextureFiltering', 'Linear');\n setSettingValue('🔍MagnifyGlass.BorderWidth', 1);\n setSettingValue('🔍MagnifyGlass.BorderColor', '#6b7280');\n setSettingValue('🔍MagnifyGlass.BorderEnabled', true);\n setSettingValue('🔍MagnifyGlass.FollowCursor', false);\n setSettingValue('🔍MagnifyGlass.AlwaysActiveMode', true);\n setSettingValue('🔍MagnifyGlass.ActivationKey', 'x');\n setSettingValue('🔍MagnifyGlass.ResetKey', 'o');\n setSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h');\n setSettingValue('🔍MagnifyGlass.AltRequired', false);\n setSettingValue('🔍MagnifyGlass.OffsetStep', 5);\n setSettingValue('🔍MagnifyGlass.ShowCursorPreview', false);\n\n\n // Default panel settings\n setSettingValue('🔍MagnifyGlass.InfoPanelEnabled', true);\n setSettingValue('🔍MagnifyGlass.InfoPanelPosition', 'Bottom');\n setSettingValue('🔍MagnifyGlass.InfoPanelWidth', 300);\n setSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', 300);\n setSettingValue('🔍MagnifyGlass.InfoPanelOpacity', 100);\n setSettingValue('🔍MagnifyGlass.InfoPanelFontSize', 14);\n setSettingValue('🔍MagnifyGlass.InfoPanelFontFamily', 'System Default');\n setSettingValue('🔍MagnifyGlass.InfoPanelPersist', false);\n setSettingValue('🔍MagnifyGlass.InfoPanelTextColor', '#6b7280');\n setSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', '#3b82f6');\n setSettingValue('🔍MagnifyGlass.InfoPanelAnimations', false);\n setSettingValue('🔍MagnifyGlass.ShowHoveringControls', true);\n setSettingValue('🔍MagnifyGlass.ControlsPosition', 'left');\n setSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i');\n setSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g');\n setSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u');\n\n // Also reset position\n const magnifyGlass = window.comfyUIMagnifyGlass;\n if (magnifyGlass && magnifyGlass.resetOffsets) {\n magnifyGlass.resetOffsets();\n }\n });\n\n buttonRow.appendChild(resetAllBtn);\n container.appendChild(buttonRow);\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file