Files
AEmotionStudio-ComfyUI-Magn…/src/sidebar/SidebarSettings.ts
T

743 lines
28 KiB
TypeScript

/**
* ComfyUI MagnifyGlass - Sidebar Settings Panel
*
* All settings controls for the sidebar.
*/
// @ts-ignore
import { app } from "/scripts/app.js";
import {
GLASS_POSITIONS,
GLASS_SHAPES,
ACTIVATION_KEYS,
RESET_KEYS,
TOGGLE_FOLLOW_KEYS,
PANEL_POSITIONS
} from '../shared/constants';
/**
* Icons for the settings panel
*/
const Icons = {
chevronDown: `<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>`,
reset: `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"></polyline><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path></svg>`,
};
/**
* Create a slider control with tooltip
*/
/**
* Create a slider control with tooltip
*/
function createSlider(
label: string,
value: number,
min: number,
max: number,
step: number,
unit: string,
onChange: (value: number) => void,
tooltip?: string,
onInput?: (value: number) => void
): HTMLElement {
const row = document.createElement('div');
row.className = 'magnify-control-row';
if (tooltip) row.title = tooltip;
const labelRow = document.createElement('div');
labelRow.className = 'magnify-control-label-row';
const labelEl = document.createElement('label');
labelEl.textContent = label;
const valueEl = document.createElement('span');
valueEl.className = 'control-value';
valueEl.textContent = `${value}${unit}`;
labelRow.appendChild(labelEl);
labelRow.appendChild(valueEl);
const slider = document.createElement('input');
slider.type = 'range';
slider.className = 'magnify-slider';
slider.min = String(min);
slider.max = String(max);
slider.step = String(step);
slider.value = String(value);
// Prevent ComfyUI from capturing mouse events during drag
slider.addEventListener('mousedown', (e) => e.stopPropagation());
slider.addEventListener('touchstart', (e) => e.stopPropagation());
slider.addEventListener('pointerdown', (e) => e.stopPropagation());
slider.addEventListener('input', (e) => {
e.stopPropagation();
const newValue = parseFloat(slider.value);
valueEl.textContent = `${newValue}${unit}`;
if (onInput) onInput(newValue);
});
slider.addEventListener('change', (e) => {
e.stopPropagation();
const newValue = parseFloat(slider.value);
onChange(newValue);
});
row.appendChild(labelRow);
row.appendChild(slider);
return row;
}
/**
* Create a toggle control with tooltip
*/
function createToggle(
label: string,
checked: boolean,
onChange: (checked: boolean) => void,
tooltip?: string
): HTMLElement {
const row = document.createElement('div');
row.className = 'magnify-toggle-row';
if (tooltip) row.title = tooltip;
const labelEl = document.createElement('label');
labelEl.textContent = label;
const toggle = document.createElement('div');
toggle.className = `magnify-toggle${checked ? ' active' : ''}`;
toggle.addEventListener('click', () => {
const isActive = toggle.classList.toggle('active');
onChange(isActive);
});
row.appendChild(labelEl);
row.appendChild(toggle);
return row;
}
/**
* Create a select dropdown control with tooltip
*/
function createSelect(
label: string,
value: string,
options: readonly string[] | string[],
onChange: (value: string) => void,
tooltip?: string,
onInput?: (value: string) => void
): HTMLElement {
const row = document.createElement('div');
row.className = 'magnify-control-row';
if (tooltip) row.title = tooltip;
const labelEl = document.createElement('label');
labelEl.textContent = label;
const select = document.createElement('select');
select.className = 'magnify-select';
options.forEach(opt => {
const option = document.createElement('option');
option.value = opt;
option.textContent = opt;
if (opt === value) option.selected = true;
select.appendChild(option);
});
select.addEventListener('change', () => {
// Call onInput first for live preview
if (onInput) {
onInput(select.value);
}
// Then persist the setting
onChange(select.value);
});
row.appendChild(labelEl);
row.appendChild(select);
return row;
}
/**
* Create a color picker control with tooltip
*/
/**
* Create a color picker control with tooltip
*/
function createColorPicker(
label: string,
value: string,
onChange: (value: string) => void,
tooltip?: string,
onInput?: (value: string) => void
): HTMLElement {
const row = document.createElement('div');
row.className = 'magnify-control-row magnify-color-row';
if (tooltip) row.title = tooltip;
const labelEl = document.createElement('label');
labelEl.textContent = label;
const colorWrapper = document.createElement('div');
colorWrapper.className = 'magnify-color-wrapper';
const colorInput = document.createElement('input');
colorInput.type = 'color';
colorInput.className = 'magnify-color-input';
colorInput.value = value;
const colorPreview = document.createElement('span');
colorPreview.className = 'magnify-color-preview';
colorPreview.textContent = value;
colorInput.addEventListener('input', () => {
colorPreview.textContent = colorInput.value;
if (onInput) onInput(colorInput.value);
});
colorInput.addEventListener('change', () => {
onChange(colorInput.value);
});
colorWrapper.appendChild(colorInput);
colorWrapper.appendChild(colorPreview);
row.appendChild(labelEl);
row.appendChild(colorWrapper);
return row;
}
/**
* Get current MagnifyGlass settings from app.ui.settings
*/
function getSettingValue(id: string, defaultValue: any): any {
try {
const value = app.ui.settings.getSettingValue(id);
return value !== undefined ? value : defaultValue;
} catch {
return defaultValue;
}
}
/**
* Set a MagnifyGlass setting via app.ui.settings
*/
function setSettingValue(id: string, value: any): void {
try {
app.ui.settings.setSettingValue(id, value);
} catch (e) {
console.warn(`Failed to set setting ${id}:`, e);
}
}
/** Storage key for section states */
const SECTION_STATE_KEY = 'magnifyglass-sidebar-sections';
/**
* Get saved section states from localStorage
*/
function getSectionStates(): Record<string, boolean> {
try {
const saved = localStorage.getItem(SECTION_STATE_KEY);
return saved ? JSON.parse(saved) : {};
} catch {
return {};
}
}
/**
* Save section state to localStorage
*/
function saveSectionState(title: string, collapsed: boolean): void {
try {
const states = getSectionStates();
states[title] = collapsed;
localStorage.setItem(SECTION_STATE_KEY, JSON.stringify(states));
} catch {
// Ignore storage errors
}
}
/**
* Create a collapsible section with persistent state
*/
function createSection(title: string, defaultCollapsed: boolean = false): { section: HTMLElement; body: HTMLElement } {
const section = document.createElement('div');
section.className = 'magnify-sidebar-section';
// Check if we have a saved state for this section
const savedStates = getSectionStates();
const collapsed = savedStates[title] !== undefined ? savedStates[title] : defaultCollapsed;
const header = document.createElement('div');
header.className = `magnify-sidebar-section-header${collapsed ? ' collapsed' : ''}`;
header.innerHTML = `${Icons.chevronDown}<span>${title}</span>`;
const body = document.createElement('div');
body.className = `magnify-sidebar-section-body${collapsed ? ' collapsed' : ''}`;
header.addEventListener('click', () => {
const isCollapsed = header.classList.toggle('collapsed');
body.classList.toggle('collapsed');
// Save the new state
saveSectionState(title, isCollapsed);
});
section.appendChild(header);
section.appendChild(body);
return { section, body };
}
/**
* Render the settings panel into the container
*/
export function renderSettingsPanel(container: HTMLElement): void {
// Get current hotkey values for tooltips
const activationKey = getSettingValue('🔍MagnifyGlass.ActivationKey', 'x').toUpperCase();
const resetKey = getSettingValue('🔍MagnifyGlass.ResetKey', 'o').toUpperCase();
const toggleFollowKey = getSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h').toUpperCase();
// ===== Glass Settings Section =====
const glassSection = createSection('Glass Settings');
glassSection.body.appendChild(createSlider('Zoom Factor',
getSettingValue('🔍MagnifyGlass.ZoomFactor', 300), 100, 1000, 25, '%',
(value) => setSettingValue('🔍MagnifyGlass.ZoomFactor', value),
'Magnification level of the glass (100-1000%)',
(value) => {
const mg = (window as any).comfyUIMagnifyGlass;
if (mg?.config) {
mg.config.zoomFactor = value / 100;
if (mg.state.active) mg.updateMagnifiedView();
}
}
));
glassSection.body.appendChild(createSlider('Glass Size',
getSettingValue('🔍MagnifyGlass.GlassSize', 250), 50, 500, 10, 'px',
(value) => setSettingValue('🔍MagnifyGlass.GlassSize', value),
'Size of the magnifying glass in pixels',
(value) => {
const mg = (window as any).comfyUIMagnifyGlass;
if (mg?.config) {
mg.config.glassSize = value;
mg.applyUiChanges();
if (mg.state.active) mg.updateMagnifiedView();
}
}
));
glassSection.body.appendChild(createSelect('Shape',
getSettingValue('🔍MagnifyGlass.GlassShape', 'Rounded Square'), GLASS_SHAPES,
(value) => setSettingValue('🔍MagnifyGlass.GlassShape', value),
'Shape of the magnifying glass'
));
glassSection.body.appendChild(createSelect('Position',
getSettingValue('🔍MagnifyGlass.GlassPosition', 'Top-Right'), GLASS_POSITIONS,
(value) => setSettingValue('🔍MagnifyGlass.GlassPosition', value),
`Default position of the glass. Press ${resetKey} to reset.`
));
glassSection.body.appendChild(createSelect('Filtering',
getSettingValue('🔍MagnifyGlass.TextureFiltering', 'Linear'), ['Linear', 'Nearest'],
(value) => setSettingValue('🔍MagnifyGlass.TextureFiltering', value),
'Texture filtering: Linear (smooth) or Nearest (pixelated)'
));
glassSection.body.appendChild(createSlider('Border Width',
getSettingValue('🔍MagnifyGlass.BorderWidth', 2), 0, 10, 0.5, 'px',
(value) => setSettingValue('🔍MagnifyGlass.BorderWidth', value),
'Width of the glass border in pixels',
(value) => {
const mg = (window as any).comfyUIMagnifyGlass;
if (mg?.config) {
mg.config.borderWidth = value;
mg.applyUiChanges();
}
}
));
glassSection.body.appendChild(createColorPicker('Border Color',
getSettingValue('🔍MagnifyGlass.BorderColor', '#ffffff'),
(value) => setSettingValue('🔍MagnifyGlass.BorderColor', value),
'Color of the glass border',
(value) => {
const mg = (window as any).comfyUIMagnifyGlass;
if (mg?.config) {
mg.config.borderColor = value;
mg.applyUiChanges();
}
}
));
glassSection.body.appendChild(createToggle('Show Border',
getSettingValue('🔍MagnifyGlass.BorderEnabled', true),
(checked) => setSettingValue('🔍MagnifyGlass.BorderEnabled', checked),
'Show or hide the glass border'
));
glassSection.body.appendChild(createToggle('Follow Cursor',
getSettingValue('🔍MagnifyGlass.FollowCursor', false),
(checked) => setSettingValue('🔍MagnifyGlass.FollowCursor', checked),
`Glass follows the cursor. Hotkey: ${toggleFollowKey}`
));
glassSection.body.appendChild(createToggle('Always Active Mode',
getSettingValue('🔍MagnifyGlass.AlwaysActiveMode', true),
(checked) => setSettingValue('🔍MagnifyGlass.AlwaysActiveMode', checked),
`When enabled, glass stays visible. Toggle with ${activationKey}`
));
// The instruction implies this should be in glassSection, but the content suggests info panel.
// Placing it in glassSection as per instruction, assuming createToggle is intended.
// The condition `if (getSettingValue("🔍MagnifyGlass.InfoPanelEnabled", true))` is removed
// as it doesn't make sense for a glass setting to depend on info panel being enabled.
// The tooltip and callback logic are kept as provided.
glassSection.body.appendChild(createToggle('Persist Info',
getSettingValue('🔍MagnifyGlass.InfoPanelPersist', false),
(checked) => {
setSettingValue('🔍MagnifyGlass.InfoPanelPersist', checked);
// Sync with UI controls if needed
const infoPanel = (window as any).infoPanelManager;
if (infoPanel?.uiManager) {
infoPanel.uiManager.updateControlStates();
}
}, 'Keep displaying the last node info when hovering empty space'
));
container.appendChild(glassSection.section);
// ===== Hotkeys Section =====
const hotkeySection = createSection('Hotkeys', true);
hotkeySection.body.appendChild(createSelect('Activation Key',
getSettingValue('🔍MagnifyGlass.ActivationKey', 'x'), ACTIVATION_KEYS,
(value) => setSettingValue('🔍MagnifyGlass.ActivationKey', value),
'Key to toggle or hold to activate the magnifying glass'
));
hotkeySection.body.appendChild(createSelect('Reset Key',
getSettingValue('🔍MagnifyGlass.ResetKey', 'o'), RESET_KEYS,
(value) => setSettingValue('🔍MagnifyGlass.ResetKey', value),
'Key to reset glass position and disable follow cursor'
));
hotkeySection.body.appendChild(createSelect('Toggle Follow Key',
getSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h'), TOGGLE_FOLLOW_KEYS,
(value) => setSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', value),
'Key to toggle follow cursor mode'
));
hotkeySection.body.appendChild(createToggle('Require Alt Key',
getSettingValue('🔍MagnifyGlass.AltRequired', false),
(checked) => setSettingValue('🔍MagnifyGlass.AltRequired', checked),
'Require Alt key to be held with activation key'
));
hotkeySection.body.appendChild(createSlider('Offset Step',
getSettingValue('🔍MagnifyGlass.OffsetStep', 10), 1, 50, 1, 'px',
(value) => setSettingValue('🔍MagnifyGlass.OffsetStep', value),
'Amount to move glass per arrow key press (pixels)'
));
container.appendChild(hotkeySection.section);
// ===== Info Panel Section =====
const panelSection = createSection('Info Panel', true);
const toggleHotkey = getSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i').toUpperCase();
const glassToggleKey = getSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g').toUpperCase();
const pinHotkeyVal = getSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u').toUpperCase();
panelSection.body.appendChild(createToggle('Enable Panel',
getSettingValue('🔍MagnifyGlass.InfoPanelEnabled', true),
(checked) => setSettingValue('🔍MagnifyGlass.InfoPanelEnabled', checked),
`Show info panel with node details. Toggle: ${toggleHotkey}`
));
panelSection.body.appendChild(createToggle('Persist Info',
getSettingValue('🔍MagnifyGlass.InfoPanelPersist', false),
(checked) => {
setSettingValue('🔍MagnifyGlass.InfoPanelPersist', checked);
// Sync with UI controls if needed
const infoPanel = (window as any).infoPanelManager;
if (infoPanel?.uiManager) {
infoPanel.uiManager.updateControlStates();
}
},
'Keep displaying the last node info when hovering empty space'
));
panelSection.body.appendChild(createSelect('Position',
getSettingValue('🔍MagnifyGlass.InfoPanelPosition', 'Bottom'), PANEL_POSITIONS,
(value) => setSettingValue('🔍MagnifyGlass.InfoPanelPosition', value),
'Position of the info panel relative to the glass'
));
panelSection.body.appendChild(createSlider('Width',
getSettingValue('🔍MagnifyGlass.InfoPanelWidth', 300), 200, 600, 20, 'px',
(value) => setSettingValue('🔍MagnifyGlass.InfoPanelWidth', value),
'Width of the info panel',
(value) => {
const infoPanel = (window as any).infoPanelManager;
if (infoPanel?.stateManager?.state?.settings) {
infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelWidth'] = value;
infoPanel.uiManager.applyStyles();
// Ensure visible and reflow if active
if (infoPanel.magnifyGlass.state.active) {
infoPanel.uiManager.show();
infoPanel.positionManager.positionPanel();
}
}
}
));
panelSection.body.appendChild(createSlider('Max Height',
getSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', 300), 200, 1500, 50, 'px',
(value) => setSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', value),
'Maximum height of the info panel',
(value) => {
console.log('[MaxHeight] Handler called with value:', value);
const infoPanel = (window as any).infoPanelManager;
console.log('[MaxHeight] infoPanelManager:', infoPanel ? 'found' : 'NOT FOUND');
if (infoPanel?.stateManager?.state?.settings) {
console.log('[MaxHeight] Updating setting and calling applyStyles');
infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelMaxHeight'] = value;
infoPanel.uiManager.applyStyles();
// Ensure visible and reflow if active
if (infoPanel.magnifyGlass.state.active) {
console.log('[MaxHeight] Glass is active, calling show() and positionPanel()');
infoPanel.uiManager.show();
infoPanel.positionManager.positionPanel();
} else {
console.log('[MaxHeight] Glass is NOT active, skipping show()');
}
} else {
console.warn('[MaxHeight] Check failed - stateManager/state/settings missing');
}
}
));
panelSection.body.appendChild(createSlider('Font Size',
getSettingValue('🔍MagnifyGlass.InfoPanelFontSize', 14), 8, 24, 1, 'px',
(value) => setSettingValue('🔍MagnifyGlass.InfoPanelFontSize', value),
'Font size of text in the info panel',
(value) => {
const infoPanel = (window as any).infoPanelManager;
if (infoPanel?.stateManager?.state?.settings) {
infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelFontSize'] = value;
infoPanel.uiManager.applyStyles();
}
}
));
panelSection.body.appendChild(createSlider('Opacity',
getSettingValue('🔍MagnifyGlass.InfoPanelOpacity', 95), 10, 100, 5, '%',
(value) => setSettingValue('🔍MagnifyGlass.InfoPanelOpacity', value),
'Background opacity of the info panel',
(value) => {
const infoPanel = (window as any).infoPanelManager;
if (infoPanel?.stateManager?.state?.settings) {
infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelOpacity'] = value;
infoPanel.uiManager.applyStyles();
}
}
));
panelSection.body.appendChild(createColorPicker('Text Color',
getSettingValue('🔍MagnifyGlass.InfoPanelTextColor', '#6b7280'),
(value) => setSettingValue('🔍MagnifyGlass.InfoPanelTextColor', value),
'Text color in the info panel',
(value) => {
const infoPanel = (window as any).infoPanelManager;
if (infoPanel?.stateManager?.state?.settings) {
infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelTextColor'] = value;
infoPanel.uiManager.applyStyles();
}
}
));
panelSection.body.appendChild(createColorPicker('Accent Color',
getSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', '#3b82f6'),
(value) => setSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', value),
'Accent color for highlights',
(value) => {
const infoPanel = (window as any).infoPanelManager;
if (infoPanel?.stateManager?.state?.settings) {
infoPanel.stateManager.state.settings['🔍MagnifyGlass.InfoPanelAccentColor'] = value;
infoPanel.uiManager.applyStyles();
}
}
));
panelSection.body.appendChild(createToggle('Animations',
getSettingValue('🔍MagnifyGlass.InfoPanelAnimations', false),
(checked) => setSettingValue('🔍MagnifyGlass.InfoPanelAnimations', checked),
'Enable smooth animations for panel updates'
));
panelSection.body.appendChild(createToggle('Hover Controls',
getSettingValue('🔍MagnifyGlass.ShowHoveringControls', true),
(checked) => setSettingValue('🔍MagnifyGlass.ShowHoveringControls', checked),
'Show floating control buttons near the panel'
));
panelSection.body.appendChild(createSelect('Controls Position',
getSettingValue('🔍MagnifyGlass.ControlsPosition', 'left'),
['top', 'bottom', 'left', 'right', 'top-left', 'top-right', 'bottom-left', 'bottom-right'],
(value) => setSettingValue('🔍MagnifyGlass.ControlsPosition', value),
'Position of floating control buttons',
(value) => {
// Live update controls position
const infoPanel = (window as any).infoPanelManager;
if (infoPanel?.stateManager?.state?.settings) {
infoPanel.stateManager.state.settings['🔍MagnifyGlass.ControlsPosition'] = value;
infoPanel.uiManager.updateControlsLayout(value);
if (infoPanel.magnifyGlass.state.active) {
infoPanel.positionManager.positionFloatingControls();
}
}
}
));
container.appendChild(panelSection.section);
// ===== Panel Hotkeys Section =====
const panelHotkeySection = createSection('Panel Hotkeys', true);
panelHotkeySection.body.appendChild(createSelect('Toggle Key',
getSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i'), ['i', 'j', 'k', 'l', 'n', 'm'],
(value) => setSettingValue('🔍MagnifyGlass.ToggleHotkey', value),
'Key to toggle info panel visibility'
));
panelHotkeySection.body.appendChild(createSelect('Glass Toggle Key',
getSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g'), ['g', 'f', 'v', 'b'],
(value) => setSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', value),
'Key to toggle glass preview in panel'
));
panelHotkeySection.body.appendChild(createSelect('Pin Key',
getSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u'), ['u', 'p', 'y', 't'],
(value) => setSettingValue('🔍MagnifyGlass.PinPanelHotkey', value),
'Key to pin/unpin the info panel position'
));
container.appendChild(panelHotkeySection.section);
// ===== Debug Section =====
const debugSection = createSection('Debug', true);
debugSection.body.appendChild(createToggle('Debug Mode',
getSettingValue('🔍MagnifyGlass.DebugMode', false),
(checked) => setSettingValue('🔍MagnifyGlass.DebugMode', checked),
'Enable debug logging and visual indicators'
));
container.appendChild(debugSection.section);
// ===== Button Row =====
const buttonRow = document.createElement('div');
buttonRow.style.padding = '16px';
buttonRow.style.borderTop = '1px solid var(--border-color, #333)';
buttonRow.style.display = 'flex';
buttonRow.style.flexDirection = 'column';
buttonRow.style.gap = '8px';
// Reset Position Button
const resetBtn = document.createElement('button');
resetBtn.className = 'magnify-btn';
resetBtn.style.width = '100%';
resetBtn.innerHTML = `${Icons.reset} Reset Position`;
resetBtn.title = `Reset glass position and disable follow cursor. Hotkey: ${resetKey}`;
resetBtn.addEventListener('click', (e) => {
e.stopPropagation();
const magnifyGlass = window.comfyUIMagnifyGlass;
if (magnifyGlass && magnifyGlass.resetOffsets) {
magnifyGlass.resetOffsets();
// Update follow cursor toggle in UI
const followToggles = container.querySelectorAll('.magnify-toggle-row');
followToggles.forEach(row => {
const label = row.querySelector('label');
if (label && label.textContent === 'Follow Cursor') {
const toggle = row.querySelector('.magnify-toggle');
if (toggle) toggle.classList.remove('active');
}
});
}
});
buttonRow.appendChild(resetBtn);
// Reset All Settings Button
const resetAllBtn = document.createElement('button');
resetAllBtn.className = 'magnify-btn magnify-btn-secondary';
resetAllBtn.style.width = '100%';
resetAllBtn.innerHTML = `${Icons.reset} Reset All Settings`;
resetAllBtn.title = 'Reset all settings to their default values';
resetAllBtn.addEventListener('click', (e) => {
e.stopPropagation();
// Confirm with user
if (!confirm('Reset all MagnifyGlass settings to defaults?')) {
return;
}
// Default glass settings
setSettingValue('🔍MagnifyGlass.ZoomFactor', 300);
setSettingValue('🔍MagnifyGlass.GlassSize', 300);
setSettingValue('🔍MagnifyGlass.GlassShape', 'Rounded Square');
setSettingValue('🔍MagnifyGlass.GlassPosition', 'Top-Right');
setSettingValue('🔍MagnifyGlass.TextureFiltering', 'Linear');
setSettingValue('🔍MagnifyGlass.BorderWidth', 1);
setSettingValue('🔍MagnifyGlass.BorderColor', '#6b7280');
setSettingValue('🔍MagnifyGlass.BorderEnabled', true);
setSettingValue('🔍MagnifyGlass.FollowCursor', false);
setSettingValue('🔍MagnifyGlass.AlwaysActiveMode', true);
setSettingValue('🔍MagnifyGlass.ActivationKey', 'x');
setSettingValue('🔍MagnifyGlass.ResetKey', 'o');
setSettingValue('🔍MagnifyGlass.ToggleFollowCursorKey', 'h');
setSettingValue('🔍MagnifyGlass.AltRequired', false);
setSettingValue('🔍MagnifyGlass.OffsetStep', 5);
setSettingValue('🔍MagnifyGlass.DebugMode', false);
// Default panel settings
setSettingValue('🔍MagnifyGlass.InfoPanelEnabled', true);
setSettingValue('🔍MagnifyGlass.InfoPanelPosition', 'Bottom');
setSettingValue('🔍MagnifyGlass.InfoPanelWidth', 300);
setSettingValue('🔍MagnifyGlass.InfoPanelMaxHeight', 300);
setSettingValue('🔍MagnifyGlass.InfoPanelOpacity', 100);
setSettingValue('🔍MagnifyGlass.InfoPanelFontSize', 14);
setSettingValue('🔍MagnifyGlass.InfoPanelPersist', false);
setSettingValue('🔍MagnifyGlass.InfoPanelTextColor', '#6b7280');
setSettingValue('🔍MagnifyGlass.InfoPanelAccentColor', '#3b82f6');
setSettingValue('🔍MagnifyGlass.InfoPanelAnimations', false);
setSettingValue('🔍MagnifyGlass.ShowHoveringControls', true);
setSettingValue('🔍MagnifyGlass.ControlsPosition', 'left');
setSettingValue('🔍MagnifyGlass.ToggleHotkey', 'i');
setSettingValue('🔍MagnifyGlass.GlassPreviewToggleHotkey', 'g');
setSettingValue('🔍MagnifyGlass.PinPanelHotkey', 'u');
// Also reset position
const magnifyGlass = window.comfyUIMagnifyGlass;
if (magnifyGlass && magnifyGlass.resetOffsets) {
magnifyGlass.resetOffsets();
}
});
buttonRow.appendChild(resetAllBtn);
container.appendChild(buttonRow);
}