您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Get focused by hiding the clutter, hide chat history, lag free text box, VIBE Mode, and themes!
当前为
// ==UserScript== // @name Eye in the Cloud - A Google AI Studio Focused Experience // @namespace https://github.com/soitgoes-again/eyeinthecloud // @version 0.639 // @description Get focused by hiding the clutter, hide chat history, lag free text box, VIBE Mode, and themes! // @author so it goes...again // @match https://aistudio.google.com/* // @resource MAIN_CSS https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/css/main.css // @resource POPUP_CSS https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/css/modal-popup.css // @resource SNIPPETS_CSS https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/css/modal-snippets.css // @resource EYE_MODAL_CSS https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/css/modal-eye.css // @resource PROMPT_COMPOSER_CSS https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/css/modal-promptcomposer.css // @resource GOOGLE_OVERRIDES_CSS https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/css/google-overrides.css // @resource DOS_THEME_CSS https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/css/theme.dos.css // @resource NATURE_THEME_CSS https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/css/theme.nature.css // @resource THEME_TEMPLATE_CSS https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/css/theme.template.css // @resource PERSONAL_THEME_CSS https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/css/theme.personal.css // @resource PROMPT_TEMPLATES https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/js/prompt_templates.json // @resource SNIPPETS_JSON https://raw.githubusercontent.com/soitgoes-again/eyeinthecloud/main/js/snippets.json // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_registerMenuCommand // @grant GM_getResourceText // @run-at document-idle // ==/UserScript== !function() { "use strict"; window.Config = { selectors: { leftSidebar: "ms-navbar", rightSidebar: "ms-right-side-panel", header: "ms-header-root", toolbar: "ms-toolbar", chatInput: "ms-prompt-input-wrapper textarea", runButton: 'button.run-button[aria-label="Run"]', overallLayout: "body > app-root > ms-app > div", chatContainer: "ms-autoscroll-container", userTurn: 'ms-chat-turn:has([data-turn-role="User"])', aiTurn: 'ms-chat-turn:has([data-turn-role="Model"])', aiTurnMoreOptionsButton: 'ms-chat-turn-options button[aria-label="Open options"], ms-chat-turn-options button[aria-label="More options"]', aiTurnContextMenuItems: 'div.cdk-overlay-pane:not([style*="display: none"]) .mat-mdc-menu-item, div.cdk-overlay-pane:not([style*="display: none"]) .mdc-list-item', siteHeading: "h1.gradient-text", promptChipsContainer: ".chips-container", inputPlaceholderOverlay: ".placeholder-overlay", chatTurnFooter: ".turn-footer", aiTurnCodeBlock: "pre > code, pre, ms-code-block", zeroStateWrapper: ".zero-state-wrapper", anyChatTurn: "ms-chat-turn", siteDisclaimerText: ".disclaimer-container span.disclaimer", promptInputWrapper: ".prompt-input-wrapper-container" }, ids: { scriptButton: "advanced-control-toggle-button", popup: "advanced-control-popup", aiThemeStudioButton: "eic-global-ai-theme-gen-btn", aiThemeModalOverlay: "eic-eye-modal-overlay", aiThemeModal: "eic-eye-modal", aiThemeModalSvgBg: "eic-modal-svg-background", aiThemeModalTextarea: "eic-eye-modal-textarea", pageOverlay: "eic-modal-overlay" }, classes: { layoutHide: "adv-controls-hide-ui", aiThemeModalVisible: "eic-eye-modal-animate-in", aiThemeTextareaVisible: "eic-textarea-visible" }, settingsKey: "eyeinthecloud", defaultSettings: { showAllHistory: !0, numTurnsToShow: 10, historyViewMode: "turns", hideLeftSidebar: !1, hideRightSidebar: !1, hideHeader: !1, hideToolbar: !1, headingText: "Eye in the Cloud", hidePromptChips: !1, hideFeedbackButtons: !1, activeTheme: "default", promptSnippets: JSON.parse(GM_getResourceText("SNIPPETS_JSON")), showSnippetToolbarInModal: !0, vibeModeActive: !1, personalThemePalette: { svgDefault: {}, svgHover: {}, svgActive: {}, confirmationMessage: "The Eye sees your vision take form." }, customProfileAssets: { colorPalette: {}, svgDefault: {}, svgHover: {}, svgActive: {} }, isCustomProfileActive: !1, popupActiveTab: "history" }, icons: { visible: "visibility", hidden: "visibility_off", dos: "dos", nature: "nature", default: "eyeInTheCloud" }, animationDefaults: { modalFadeInScale: "eicModalAppear 0.4s ease-out forwards", modalFadeOutScale: "eicModalDisappear 0.3s ease-in forwards", elementFadeIn: "eicElementFadeIn 0.3s ease-out forwards", elementFadeOut: "eicElementFadeOut 0.2s ease-in forwards" }, vars: { avgSnippetButtonWidth: 120, moreSnippetsButtonWidth: 60, maxRenderedToolbarSnippets: 10 }, textStrings: { deleteActionMenuItemText: "delete" }, minExchangesForProfileTheme: 3 }; window.State = { isVibeModeActive: !1, activeTheme: "default", scriptToggleButton: null, popupElement: null, aiThemeStudioButton: null, aiThemeModalOverlay: null, aiThemeModal: null, aiThemeModalSvgBg: null, aiThemeModalTextarea: null, pageOverlay: null, chatObserver: null, debounceTimer: null, uiUpdateDebounceTimer: null, waitingForThemeAiTurnAfter: null, aiThemeModalState: "idle", aiThemeModalCurrentSvgData: {}, aiThemeModalConfirmationText: "" }; window.Settings = { async load() { const storedSettings = JSON.parse(await GM_getValue(window.Config.settingsKey) || "{}"); const defaultSettingsCopy = JSON.parse(JSON.stringify(window.Config.defaultSettings)); window.State.settings = function mergeDeep(target, source) { for (const key in source) { if (Array.isArray(source[key])) { target[key] = source[key]?.length > 0 ? source[key] : target[key]; } else if (source[key] && "object" == typeof source[key]) { target[key] = mergeDeep(target[key] || {}, source[key]); } else if (void 0 !== source[key]) { target[key] = source[key]; } } return target; }(defaultSettingsCopy, storedSettings); }, async save() { try { const settingsToSave = { ...window.State.settings, vibeModeActive: window.State.isVibeModeActive }; await GM_setValue(window.Config.settingsKey, JSON.stringify(settingsToSave)); return !0; } catch (error) { return !1; } }, update(key, value, updateUI = !0) { window.State.settings[key] = value; this.save(); if (updateUI && window.UI) { if ("numTurnsToShow" === key || "showAllHistory" === key || "historyViewMode" === key) { window.HistoryManager.applyVisibilityRules(); if (window.HistoryManager && "function" == typeof window.HistoryManager.updateHistoryControlsState) { window.HistoryManager.updateHistoryControlsState(); } } else if ([ "hideLeftSidebar", "hideRightSidebar", "hideHeader", "hideToolbar" ].includes(key)) { window.UI.applyLayoutRules(); } if ("headingText" === key) { window.UI.updateHeadingText(); } if ("hidePromptChips" === key) { window.UI.updatePromptChipsVisibility(); } if ("hideFeedbackButtons" === key) { window.UI.updateTurnFooterVisibility(); } if (window.Popup && window.State.popupElement && window.State.popupElement.classList.contains("visible")) { window.Popup.updateUIState(); } } }, batchUpdate(settingsToUpdate, updateUI = !0) { let updated = !1; for (const key in settingsToUpdate) { if (window.State.settings.hasOwnProperty(key) && JSON.stringify(window.State.settings[key]) !== JSON.stringify(settingsToUpdate[key])) { window.State.settings[key] = settingsToUpdate[key]; updated = !0; } } if (updated) { this.save(); if (updateUI) { if (window.UI) { window.UI.applyLayoutRules?.(); window.HistoryManager.applyVisibilityRules?.(); window.UI.updateHeadingText?.(); window.UI.updatePromptChipsVisibility?.(); window.UI.updateTurnFooterVisibility?.(); } if (window.Popup && window.State.popupElement?.classList.contains("visible")) { window.Popup.updateUIState?.(); } } } }, async resetToDefaults() { await GM_deleteValue(window.Config.settingsKey); await this.load(); window.ThemeManager.applyTheme("default"); } }; window.Styles = { coreStyles: `\n /* Basic UI hiding classes - essential structure only */\n .adv-controls-hide-ui-sidebars ms-navbar,\n .adv-controls-hide-ui-sidebars ms-right-side-panel {\n display: none !important;\n }\n .adv-controls-hide-ui-header ms-header-root {\n display: none !important;\n }\n .adv-controls-hide-ui-toolbar ms-toolbar {\n display: none !important;\n }\n `, addCoreStyles() { if (this.coreStyles) { GM_addStyle(this.coreStyles); } }, addPopupStyles() {} }; window.DOM = { createElement(tag, attributes = {}, children = []) { const element = document.createElement(tag); let svgIconName = null; for (const [key, value] of Object.entries(attributes)) { if ("className" === key) { element.className = value; } else if ("textContent" === key) { element.textContent = value; } else if ("events" === key) { for (const [event, handler] of Object.entries(value)) { element.addEventListener(event, handler); } } else if ("svgIcon" === key) { svgIconName = value; } else { element.setAttribute(key, value); } } if (svgIconName && window.Icons) { const svgString = window.Icons.getSvgString(svgIconName); if (svgString) { try { const parser = new DOMParser; const doc = parser.parseFromString(svgString, "image/svg+xml"); const svgNode = doc.documentElement; if ("parsererror" === svgNode.nodeName || !svgNode) { svgNode.querySelector("parsererror > div"); } else { svgNode.classList.add("eic-injected-svg-node"); svgNode.classList.add(`eic-svg-${svgIconName}`); if (attributes.textContent || attributes["aria-label"]) { svgNode.setAttribute("aria-hidden", "true"); } const svgTitle = svgNode.querySelector("title"); if (svgTitle) { svgTitle.remove(); } element.classList.add("eic-svg-icon-container"); try { element.appendChild(svgNode); } catch (appendError) {} } } catch (e) {} } } if (!Array.isArray(children)) { children = [ children ]; } const filteredChildren = children.filter((child => child)); filteredChildren.forEach((child => { try { if ("string" == typeof child) { element.appendChild(document.createTextNode(child)); } else { element.appendChild(child); } } catch (childError) {} })); return element; }, createToggle(id, labelText, checked, onChange) { const container = this.createElement("div", { className: "toggle-setting" }); const label = this.createElement("label", { className: "toggle-label", htmlFor: id, textContent: labelText }); const toggle = this.createElement("input", { type: "checkbox", className: "basic-slide-toggle", id: id, events: { change: e => onChange(e.target.checked) } }); toggle.checked = checked; container.appendChild(label); container.appendChild(toggle); return container; } }; window.NotificationManager = { showNotification(message, duration = 3e3) { const existingNotification = document.getElementById("eic-notification"); if (existingNotification) { existingNotification.remove(); } const notification = window.DOM.createElement("div", { id: "eic-notification", className: "eic-notification", textContent: message }); document.body.appendChild(notification); setTimeout((() => notification.classList.add("show")), 10); setTimeout((() => { notification.classList.remove("show"); setTimeout((() => notification.remove()), 300); }), duration); } }; window.EventBus = { events: {}, subscribe(eventName, callback) { if (!this.events[eventName]) { this.events[eventName] = []; } this.events[eventName].push(callback); return () => { this.events[eventName] = this.events[eventName].filter((cb => cb !== callback)); }; }, publish(eventName, data) { if (this.events[eventName]) { this.events[eventName].forEach((callback => { callback(data); })); } } }; window.Icons = { defaults: { eyeInTheCloudDefault: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { "d": "M12,5C7,5,2.73,8.1,1,13.5c-0.31,0.62-0.31,1.38,0,2C2.73,20.9,7,24,12,24s9.27-3.1,11-8.5c0.31-0.62,0.31-1.38,0-2C21.27,8.1,17,5,12,5z", "fill": "var(--eic-global-on-surface)" } }, { type: "path", attrs: { "d": "M12,14m-3,0a3,3 0 1,0 6,0a3,3 0 1,0 -6,0", "fill": "var(--eic-global-on-secondary)" } }, { type: "path", attrs: { "d": "M1,13.5 C2.73,8.1 7,5 12,5 C17,5 21.27,8.1 23,13.5 Q17,12 12,12 Q7,12 1,13.5 Z", "fill": "var(--eic-global-surface-variant)" } } ] }, eyeInTheCloudHover: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { "d": "M12,5C7,5,2.73,8.1,1,13.5c-0.31,0.62-0.31,1.38,0,2C2.73,20.9,7,24,12,24s9.27-3.1,11-8.5c0.31-0.62,0.31-1.38,0-2C21.27,8.1,17,5,12,5z", "fill": "var(--eic-global-on-surface)" } }, { type: "path", attrs: { "d": "M12,14m-4,0a4,4 0 1,0 8,0a4,4 0 1,0 -8,0", "fill": "var(--eic-global-on-secondary)" } } ] }, eyeInTheCloudActive: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { "d": "M12,5C7,5,2.73,8.1,1,13.5c-0.31,0.62-0.31,1.38,0,2C2.73,20.9,7,24,12,24s9.27-3.1,11-8.5c0.31-0.62,0.31-1.38,0-2C21.27,8.1,17,5,12,5z", "fill": "var(--eic-global-on-surface)" } }, { type: "path", attrs: { "d": "M12,14m-5,0a5,5 0 1,0 10,0a5,5 0 1,0 -10,0", "fill": "var(--eic-global-primary)" } } ] }, eyeModalClosed: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { "d": "M12,6C7,6,2.73,9.1,1,14.5c-0.31,0.62-0.31,1.38,0,2C2.73,21.9,7,25,12,25s9.27-3.1,11-8.5c0.31-0.62,0.31-1.38,0-2C21.27,9.1,17,6,12,6z", "fill": "var(--eic-global-surface)", "stroke": "var(--eic-global-outline)", "stroke-width": "0.3" } }, { type: "path", attrs: { "d": "M1,14.5 C5,12 19,12 23,14.5 C19,17 5,17 1,14.5 Z", "fill": "var(--eic-global-surface-variant)" } } ] }, close: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z", fill: "currentColor" } } ] }, bolt: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M7 2v11h3v9l7-12h-4l4-8H7z", fill: "currentColor" } } ] }, edit: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z", fill: "currentColor" } } ] }, reset: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z", fill: "currentColor" } } ] }, save: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm2 16H5V5h11.17L19 7.83V19zm-7-7c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zM6 6h9v4H6z", fill: "currentColor" } } ] }, cancel: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z", fill: "currentColor" } } ] }, tune: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z", fill: "currentColor" } } ] }, delete: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z", fill: "currentColor" } } ] }, arrow_upward: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z", fill: "currentColor" } } ] }, arrow_downward: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z", fill: "currentColor" } } ] }, removed: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M0 0h24v24H0V0z", fill: "none" } }, { type: "path", attrs: { d: "M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5C21.27 7.61 17 4.5 12 4.5zm0 10c-2.48 0-4.5-2.02-4.5-4.5S9.52 5.5 12 5.5s4.5 2.02 4.5 4.5-2.02 4.5-4.5 4.5zm0-7c-1.38 0-2.5 1.12-2.5 2.5s1.12 2.5 2.5 2.5 2.5-1.12 2.5-2.5-1.12-2.5-2.5-2.5z", fill: "currentColor" } } ] }, vibe: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M12,3.5c-4.7,0-8.5,3.8-8.5,8.5s3.8,8.5,8.5,8.5s8.5-3.8,8.5-8.5S16.7,3.5,12,3.5z", fill: "none", stroke: "currentColor", "stroke-width": 1.5 } }, { type: "path", attrs: { d: "M12,7.5c-2.5,0-4.5,2-4.5,4.5s2,4.5,4.5,4.5s4.5-2,4.5-4.5S14.5,7.5,12,7.5z M12,14.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5S13.4,14.5,12,14.5z", fill: "currentColor" } }, { type: "path", attrs: { d: "M4.5,9L3,10.5 M6,6L4.5,7.5 M9,4.5L7.5,6 M20,10.5L21,9 M19.5,7.5L18,6 M16.5,6L15,4.5 M4.5,15L3,13.5 M6,18L4.5,16.5 M9,19.5L7.5,18 M20,13.5L21,15 M19.5,16.5L18,18 M16.5,18L15,19.5", fill: "none", stroke: "currentColor", "stroke-width": 1.5 } } ] }, person: { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M12,4c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S14.2,4,12,4z", fill: "currentColor" } }, { type: "path", attrs: { d: "M18,20c0-3.3-2.7-6-6-6s-6,2.7-6,6", fill: "none", stroke: "currentColor", "stroke-width": 2 } } ] } }, getIcon(iconNameOrData) { if ("object" == typeof iconNameOrData && null !== iconNameOrData) { return iconNameOrData; } if ("string" == typeof iconNameOrData) { const iconData = this.defaults[iconNameOrData]; if (!iconData) { return null; } else { return iconData; } } return null; }, createSvgElement: function(iconNameOrData, options = {}) { const iconData = "string" == typeof iconNameOrData ? this.getIcon(iconNameOrData) : iconNameOrData; if (!iconData) { return null; } if ("string" != typeof iconData.viewBox || !Array.isArray(iconData.elements)) { return null; } try { const ns = "http://www.w3.org/2000/svg"; const svg = document.createElementNS(ns, "svg"); svg.setAttribute("viewBox", iconData.viewBox); if ("background" !== options.mode) { svg.setAttribute("width", options.width || iconData.width || "24px"); svg.setAttribute("height", options.height || iconData.height || "24px"); } svg.setAttribute("fill", options.fill || "currentColor"); if (options.preserveAspectRatio) { svg.setAttribute("preserveAspectRatio", options.preserveAspectRatio); } if (options.className) { svg.setAttribute("class", options.className); } if (options.stroke) { svg.setAttribute("stroke", options.stroke); } if (options.strokeWidth) { svg.setAttribute("stroke-width", options.strokeWidth); } iconData.elements.forEach((elData => { if (!elData || "string" != typeof elData.type || "object" != typeof elData.attrs) { return; } const element = document.createElementNS(ns, elData.type); Object.entries(elData.attrs).forEach((([attr, value]) => { element.setAttribute(attr, value); })); svg.appendChild(element); })); return svg; } catch (e) { return null; } }, createAiGeneratedSvg: function(svgData) { if (!svgData || "object" != typeof svgData || !svgData.viewBox || !Array.isArray(svgData.elements)) { return null; } const svgElement = this.createSvgElement(svgData); if (!svgElement) { return null; } else { return svgElement; } }, inject: function(element, iconNameOrData, options = {}) { const iconData = this.getIcon(iconNameOrData); if (iconData) { try { const svgElement = this.createSvgElement(iconData, options); if (!svgElement) { throw new Error("Failed to create SVG element"); } for (;element.firstChild; ) { element.removeChild(element.firstChild); } element.appendChild(svgElement); } catch (e) {} } } }; window.EIC_Icons_Personal = { buttonStates: { Default: { name: "Shutter_Default (Closed)", viewBox: "0 0 24 24", elements: [ { type: "rect", attrs: { "x": "3", "y": "3", "width": "18", "height": "18", "rx": "3", "fill": "var(--eic-global-surface-variant)", "stroke": "var(--eic-global-outline-variant)", "stroke-width": "1" } }, { type: "circle", attrs: { "cx": "12", "cy": "12", "r": "5.5", "fill": "var(--eic-global-outline)" } }, { type: "path", attrs: { "d": "M12,6.5 L12,17.5 M8,8 L16,16 M8,16 L16,8", "stroke": "var(--eic-global-surface-variant)", "stroke-width": "0.75", "opacity": "0.6" } }, { type: "path", attrs: { "d": "M17,7 L16,7 M17,17 L16,17 M7,7 L8,7 M7,17 L8,17", "stroke": "var(--eic-global-outline-variant)", "stroke-width": "0.5", "stroke-linecap": "round", "opacity": "0.5" } } ] }, Hover: { name: "Shutter_Hover (Open Pupil)", viewBox: "0 0 24 24", elements: [ { type: "rect", attrs: { "x": "3", "y": "3", "width": "18", "height": "18", "rx": "3", "fill": "var(--eic-global-surface-variant)", "stroke": "var(--eic-global-primary)", "stroke-width": "1.25" } }, { type: "circle", attrs: { "cx": "12", "cy": "12", "r": "5.5", "fill": "var(--eic-global-background)" } }, { type: "circle", attrs: { "cx": "12", "cy": "12", "r": "2.5", "fill": "var(--eic-global-primary)" } }, { type: "circle", attrs: { "cx": "10.8", "cy": "10.8", "r": "0.8", "fill": "var(--eic-global-on-primary)", "opacity": "0.7" } }, { type: "path", attrs: { "d": "M18,6 L15.5,6 M18,8.5 L18,6 M6,6 L8.5,6 M6,8.5 L6,6 M18,18 L15.5,18 M18,15.5 L18,18 M6,18 L8.5,18 M6,15.5 L6,18", "stroke": "var(--eic-global-primary)", "stroke-width": "0.75", "stroke-linecap": "round" } } ] }, Active: { name: "Shutter_Active (Eye Inside)", viewBox: "0 0 24 24", elements: [ { type: "rect", attrs: { "x": "2.5", "y": "2.5", "width": "19", "height": "19", "rx": "3.5", "fill": "var(--eic-global-primary-container)", "stroke": "var(--eic-global-tertiary)", "stroke-width": "1.5" } }, { type: "circle", attrs: { "cx": "12", "cy": "12", "r": "6", "fill": "var(--eic-global-surface)" } }, { type: "circle", attrs: { "cx": "12", "cy": "12", "r": "3.5", "fill": "var(--eic-global-tertiary)" } }, { type: "circle", attrs: { "cx": "12", "cy": "12", "r": "1.5", "fill": "var(--eic-global-on-tertiary)" } }, { type: "circle", attrs: { "cx": "10.5", "cy": "10.5", "r": "1", "fill": "var(--eic-global-on-primary)", "opacity": "0.8" } }, { type: "path", attrs: { "d": "M19,5 L17,5 L17,7 M5,5 L7,5 L7,7 M19,19 L17,19 L17,17 M5,19 L7,19 L7,17", "fill": "none", "stroke": "var(--eic-global-tertiary)", "stroke-width": "1", "stroke-linecap": "square" } } ] } } }; window.EIC_Icons_DOS = { buttonStates: { Default: { viewBox: "0 0 24 24", elements: [ { type: "rect", attrs: { x: "2", y: "4", width: "20", height: "16", rx: "1", fill: "var(--eic-global-surface-variant)", stroke: "var(--eic-global-outline)", "stroke-width": "1" } }, { type: "rect", attrs: { x: "4", y: "6", width: "16", height: "12", fill: "var(--eic-global-surface)" } }, { type: "rect", attrs: { x: "9", y: "8", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } }, { type: "rect", attrs: { x: "13", y: "9", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } }, { type: "rect", attrs: { x: "10", y: "10", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } }, { type: "rect", attrs: { x: "14", y: "11", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } }, { type: "rect", attrs: { x: "8", y: "12", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } }, { type: "rect", attrs: { x: "16", y: "13", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } }, { type: "rect", attrs: { x: "11", y: "14", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } } ] }, Hover: { viewBox: "0 0 24 24", elements: [ { type: "rect", attrs: { x: "2", y: "4", width: "20", height: "16", rx: "1", fill: "var(--eic-global-surface-variant)", stroke: "var(--eic-global-primary)", "stroke-width": "1.5" } }, { type: "rect", attrs: { x: "4", y: "6", width: "16", height: "12", fill: "var(--eic-global-surface)" } }, { type: "rect", attrs: { x: "9", y: "9", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "10", y: "9", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "11", y: "9", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "12", y: "9", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "13", y: "9", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "14", y: "9", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "8", y: "10", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "15", y: "10", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "8", y: "11", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "15", y: "11", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "9", y: "12", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "10", y: "12", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "11", y: "12", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "12", y: "12", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "13", y: "12", width: "1", height: "1", fill: "var(--eic-global-primary)" } }, { type: "rect", attrs: { x: "14", y: "12", width: "1", height: "1", fill: "var(--eic-global-primary)" } } ] }, Active: { viewBox: "0 0 24 24", elements: [ { type: "rect", attrs: { x: "2", y: "4", width: "20", height: "16", rx: "1", fill: "var(--eic-global-surface-variant)", stroke: "var(--eic-global-tertiary)", "stroke-width": "2" } }, { type: "rect", attrs: { x: "4", y: "6", width: "16", height: "12", fill: "var(--eic-global-surface)" } }, { type: "rect", attrs: { x: "9", y: "9", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "10", y: "8", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "11", y: "8", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "12", y: "8", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "13", y: "8", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "14", y: "9", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "15", y: "10", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "15", y: "11", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "14", y: "12", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "13", y: "13", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "12", y: "13", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "11", y: "13", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "10", y: "13", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "9", y: "12", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "8", y: "11", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "8", y: "10", width: "1", height: "1", fill: "var(--eic-global-tertiary)" } }, { type: "rect", attrs: { x: "11", y: "10", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } }, { type: "rect", attrs: { x: "12", y: "10", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } }, { type: "rect", attrs: { x: "11", y: "11", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } }, { type: "rect", attrs: { x: "12", y: "11", width: "1", height: "1", fill: "var(--eic-global-on-surface-variant)" } } ] } } }; window.EIC_Icons_Nature = { buttonStates: { Default: { viewBox: "0 0 24 24", elements: [ { type: "rect", attrs: { x: "0", y: "0", width: "24", height: "12", fill: "var(--eic-global-secondary)" } }, { type: "rect", attrs: { x: "0", y: "12", width: "24", height: "12", fill: "var(--eic-global-surface-variant)" } }, { type: "path", attrs: { d: "M8,12 a4,4 0 0,1 8,0", fill: "var(--eic-global-primary)", stroke: "var(--eic-global-on-primary)", "stroke-width": "0.5" } }, { type: "line", attrs: { x1: "0", y1: "12", x2: "24", y2: "12", stroke: "var(--eic-global-outline)", "stroke-width": "1" } } ] }, Hover: { viewBox: "0 0 24 24", elements: [ { type: "rect", attrs: { x: "0", y: "0", width: "24", height: "12", fill: "var(--eic-global-secondary)" } }, { type: "rect", attrs: { x: "0", y: "12", width: "24", height: "12", fill: "var(--eic-global-surface-variant)" } }, { type: "circle", attrs: { cx: "12", cy: "10", r: "3.5", fill: "var(--eic-global-primary)" } }, { type: "circle", attrs: { cx: "12", cy: "10", r: "1.5", fill: "var(--eic-global-on-primary)" } }, { type: "line", attrs: { x1: "0", y1: "12", x2: "24", y2: "12", stroke: "var(--eic-global-outline)", "stroke-width": "1" } } ] }, Active: { viewBox: "0 0 24 24", elements: [ { type: "rect", attrs: { x: "0", y: "0", width: "24", height: "12", fill: "var(--eic-global-secondary)" } }, { type: "rect", attrs: { x: "0", y: "12", width: "24", height: "12", fill: "var(--eic-global-surface-variant)" } }, { type: "circle", attrs: { cx: "12", cy: "9", r: "4", fill: "var(--eic-global-primary)" } }, { type: "circle", attrs: { cx: "12", cy: "9", r: "2", fill: "var(--eic-global-on-primary)" } }, { type: "path", attrs: { d: "M12,3 L12,0 M12,15 L12,18 M7,4.5 L5,3 M17,4.5 L19,3 M7,13.5 L5,15 M17,13.5 L19,15", stroke: "var(--eic-global-primary)", "stroke-width": "1", "stroke-linecap": "round" } }, { type: "line", attrs: { x1: "0", y1: "12", x2: "24", y2: "12", stroke: "var(--eic-global-outline)", "stroke-width": "1" } } ] } } }; window.ThemeManager = { staticThemeStyleElements: { personal: null, dos: null, nature: null }, events: { THEME_CHANGED: "themeChanged" }, loadThemes() { this.staticThemeStyleElements.personal = document.getElementById("eic-theme-personal-css"); this.staticThemeStyleElements.dos = document.getElementById("eic-theme-dos-css"); this.staticThemeStyleElements.nature = document.getElementById("eic-theme-nature-css"); }, applyTheme(themeName) { const effectiveThemeName = !themeName ? "default" : themeName; const classesToRemove = Array.from(document.body.classList).filter((cls => cls.startsWith("theme-") || "eic-theme-active" === cls)); document.body.classList.remove(...classesToRemove); this.staticThemeStyleElements.personal.disabled = !0; this.staticThemeStyleElements.dos.disabled = !0; this.staticThemeStyleElements.nature.disabled = !0; let dynamicStyleTag = document.getElementById("eic-customized-palette-styles"); if (dynamicStyleTag) { dynamicStyleTag.disabled = !0; } if (effectiveThemeName && "default" !== effectiveThemeName) { document.body.classList.add("eic-theme-active"); document.body.classList.add(`theme-${effectiveThemeName}-applied`); const customProfileIsActive = window.State.settings.isCustomProfileActive; if ("personal" === effectiveThemeName && customProfileIsActive) { if (!dynamicStyleTag) { dynamicStyleTag = document.createElement("style"); dynamicStyleTag.id = "eic-customized-palette-styles"; document.head.appendChild(dynamicStyleTag); } let cssPaletteText = `body.eic-theme-active.theme-personal-applied {\n`; for (const [key, value] of Object.entries(window.State.settings.customProfileAssets.colorPalette)) { if (key.startsWith("--eic-global-")) { cssPaletteText += ` ${key}: ${String(value).replace("!important", "").trim()} !important;\n`; } } cssPaletteText += "}\n"; dynamicStyleTag.textContent = cssPaletteText; dynamicStyleTag.disabled = !1; } else if ("personal" === effectiveThemeName) { this.staticThemeStyleElements.personal.disabled = !1; } else if ("dos" === effectiveThemeName) { this.staticThemeStyleElements.dos.disabled = !1; } else if ("nature" === effectiveThemeName) { this.staticThemeStyleElements.nature.disabled = !1; } } if (window.State.activeTheme !== effectiveThemeName) { const previousTheme = window.State.activeTheme; window.State.activeTheme = effectiveThemeName; window.Settings.update("activeTheme", effectiveThemeName, !1); if (window.EventBus) { window.EventBus.publish(this.events.THEME_CHANGED, { previousTheme: previousTheme, newTheme: effectiveThemeName }); } } }, removeActiveTheme() { this.applyTheme("default"); }, getSvgIconData(stateKey) { const activeTheme = window.State.activeTheme; const customProfileIsActive = window.State.settings.isCustomProfileActive; let iconData; if ("personal" === activeTheme) { if (customProfileIsActive) { iconData = window.State.settings.customProfileAssets[`svg${stateKey}`]; } else { iconData = window.EIC_Icons_Personal.buttonStates[stateKey]; } } else if ("dos" === activeTheme) { iconData = window.EIC_Icons_DOS.buttonStates[stateKey]; } else if ("nature" === activeTheme) { iconData = window.EIC_Icons_Nature.buttonStates[stateKey]; } else if ("default" === activeTheme) { iconData = window.Icons.defaults[`eyeInTheCloud${stateKey}`]; } else { iconData = window.Icons.defaults[`eyeInTheCloud${stateKey}`]; } return iconData; } }; window.HistoryManager = { calculateSliderFillPercentage(value, min, max) { if (max > min) { return (value - min) / (max - min) * 100; } else { return max === min && value >= min ? 100 : 0; } }, updateSliderState(slider, numTurnsValue, sliderLabel, isVibeModeActive) { const isShowingAll = window.State.settings.showAllHistory; slider.disabled = isShowingAll || isVibeModeActive; slider.style.opacity = isShowingAll || isVibeModeActive ? "0.5" : "1"; if (sliderLabel) { let labelTextContent; if (isVibeModeActive) { labelTextContent = "Exchanges Shown: "; } else { labelTextContent = "exchanges" === window.State.settings.historyViewMode ? "Exchanges Shown: " : "Turns Shown: "; } sliderLabel.textContent = labelTextContent; } if (isVibeModeActive) { numTurnsValue.textContent = "1"; } else { numTurnsValue.textContent = isShowingAll ? "All" : slider.value; } let fillPercentage; if (isVibeModeActive) { fillPercentage = this.calculateSliderFillPercentage(1, parseInt(slider.min), parseInt(slider.max)); } else if (isShowingAll) { fillPercentage = 0; } else { fillPercentage = this.calculateSliderFillPercentage(parseInt(slider.value), parseInt(slider.min), parseInt(slider.max)); } slider.style.setProperty("--_slider-fill-percent", `${fillPercentage}%`); }, applyVisibilityRules() { const visibilityPlan = this.getHistoryVisibilityPlan(); window.UI.applyChatVisibilityDOM(visibilityPlan); }, getHistoryVisibilityPlan() { const chatContainer = document.querySelector(window.Config.selectors.chatContainer); if (!chatContainer) { return new Set; } const isVibe = window.State.isVibeModeActive; let showAll, limitCount, effectiveViewMode; if (isVibe) { showAll = !1; limitCount = 1; effectiveViewMode = "exchanges"; } else { showAll = window.State.settings.showAllHistory; limitCount = window.State.settings.numTurnsToShow; effectiveViewMode = window.State.settings.historyViewMode; } const allTurns = Array.from(chatContainer.querySelectorAll(`${window.Config.selectors.userTurn}, ${window.Config.selectors.aiTurn}`)); const visibleTurnsSet = new Set; if (showAll) { allTurns.forEach((turn => visibleTurnsSet.add(turn))); } else if ("exchanges" === effectiveViewMode) { const aiTurns = Array.from(chatContainer.querySelectorAll(window.Config.selectors.aiTurn)); const recentAiTurns = aiTurns.slice(-limitCount); recentAiTurns.forEach((aiTurn => { visibleTurnsSet.add(aiTurn); let previousElement = aiTurn.previousElementSibling; for (;previousElement && !previousElement.matches(window.Config.selectors.userTurn) && !previousElement.matches(window.Config.selectors.aiTurn); ) { previousElement = previousElement.previousElementSibling; } if (previousElement && previousElement.matches(window.Config.selectors.userTurn)) { visibleTurnsSet.add(previousElement); } })); if (0 === aiTurns.length && limitCount >= 1) { const userTurns = Array.from(chatContainer.querySelectorAll(window.Config.selectors.userTurn)); if (userTurns.length > 0) { visibleTurnsSet.add(userTurns[userTurns.length - 1]); } } } else { const recentTurns = allTurns.slice(-limitCount); recentTurns.forEach((turn => visibleTurnsSet.add(turn))); } return visibleTurnsSet; }, createHistoryPanel(panelElement) { if (!panelElement) { return; } for (;panelElement.firstChild; ) { panelElement.removeChild(panelElement.firstChild); } const DOM = window.DOM; const historyFieldset = DOM.createElement("fieldset", { className: "popup-section" }); const showAllToggle = DOM.createToggle("show-all-history-toggle", "Show All History", window.State.settings.showAllHistory, (checked => { window.Settings.update("showAllHistory", checked); window.HistoryManager.applyVisibilityRules(); window.HistoryManager.updateHistoryControlsState(); })); showAllToggle.addEventListener("mouseover", (() => window.Popup?.updateTooltip("Toggle between showing all history or limiting it."))); showAllToggle.addEventListener("mouseout", (() => window.Popup?.updateTooltip())); historyFieldset.appendChild(showAllToggle); const sliderContainer = DOM.createElement("div", { className: "slider-container" }); const sliderLabel = DOM.createElement("label", { htmlFor: "num-turns-slider" }); const labelTextSpan = DOM.createElement("span", { textContent: "Currently Showing: " }); const valueSpan = DOM.createElement("span", { id: "num-turns-value" }); sliderLabel.appendChild(labelTextSpan); sliderLabel.appendChild(valueSpan); sliderContainer.appendChild(sliderLabel); const slider = DOM.createElement("input", { id: "num-turns-slider", type: "range", min: "1", max: "10", value: window.State.settings.numTurnsToShow, events: { input: e => { if (!window.State.settings.showAllHistory) { const value = parseInt(e.target.value); window.Settings.update("numTurnsToShow", value); this.updateSliderState(e.target, document.getElementById("num-turns-value"), document.querySelector('label[for="num-turns-slider"] span:first-child'), window.State.isVibeModeActive); window.HistoryManager.applyVisibilityRules(); } } } }); sliderContainer.appendChild(slider); historyFieldset.appendChild(sliderContainer); this.updateSliderState(slider, valueSpan, labelTextSpan, window.State.isVibeModeActive); const viewModeToggle = DOM.createToggle("history-view-mode-toggle", "View as Exchanges", "exchanges" === window.State.settings.historyViewMode, (checked => { window.Settings.update("historyViewMode", checked ? "exchanges" : "turns"); window.HistoryManager.applyVisibilityRules(); window.HistoryManager.updateHistoryControlsState(); })); viewModeToggle.addEventListener("mouseover", (() => { const currentMode = window.State.settings.historyViewMode; const tooltipText = "exchanges" === currentMode ? "Currently viewing history as conversational exchanges" : "Switch to view history as conversational exchanges"; window.Popup?.updateTooltip(tooltipText); })); viewModeToggle.addEventListener("mouseout", (() => window.Popup?.updateTooltip())); historyFieldset.appendChild(viewModeToggle); panelElement.appendChild(historyFieldset); }, updateHistoryControlsState() { const showAllToggle = document.getElementById("show-all-history-toggle"); const slider = document.getElementById("num-turns-slider"); const numTurnsValue = document.getElementById("num-turns-value"); const viewModeToggle = document.getElementById("history-view-mode-toggle"); const sliderLabelTextSpan = document.querySelector('label[for="num-turns-slider"] > span:first-child'); const isShowAll = window.State.settings.showAllHistory; const isVibe = window.State.isVibeModeActive; if (showAllToggle) { showAllToggle.checked = isShowAll; showAllToggle.disabled = isVibe; showAllToggle.style.opacity = isVibe ? "0.5" : "1"; if (showAllToggle.parentElement && "LABEL" === showAllToggle.parentElement.tagName) { showAllToggle.parentElement.style.opacity = isVibe ? "0.7" : "1"; } else if (showAllToggle.closest(".toggle-setting")) { showAllToggle.closest(".toggle-setting").style.opacity = isVibe ? "0.7" : "1"; } } if (viewModeToggle) { viewModeToggle.checked = "exchanges" === window.State.settings.historyViewMode; viewModeToggle.disabled = isVibe || isShowAll; viewModeToggle.style.opacity = isVibe || isShowAll ? "0.5" : "1"; if (viewModeToggle.parentElement && "LABEL" === viewModeToggle.parentElement.tagName) { viewModeToggle.parentElement.style.opacity = isVibe || isShowAll ? "0.7" : "1"; } else if (viewModeToggle.closest(".toggle-setting")) { viewModeToggle.closest(".toggle-setting").style.opacity = isVibe || isShowAll ? "0.7" : "1"; } } if (slider && numTurnsValue) { this.updateSliderState(slider, numTurnsValue, sliderLabelTextSpan, isVibe); } }, updateSliderMax(newMaxFromHistory) { const slider = document.getElementById("num-turns-slider"); const numTurnsValue = document.getElementById("num-turns-value"); const sliderLabel = document.querySelector('label[for="num-turns-slider"] span:first-child'); const newMax = Math.min(parseInt(newMaxFromHistory), 10); if (parseInt(slider.max) !== newMax) { slider.max = newMax; } slider.value = Math.min(window.State.settings.numTurnsToShow, newMax); this.updateSliderState(slider, numTurnsValue, sliderLabel, window.State.isVibeModeActive); }, initialize() {} }; window.UI = { init() { window.EventBus.subscribe(window.ThemeManager.events.THEME_CHANGED, (data => { this.updateThemeRelatedUI(data); })); }, updateThemeRelatedUI(data) { this._updateColorBasedElements(); this._updateIconsAndSVGs(); this._updateComponentSpecificThemeElements(); this._notifyComponentsOfThemeChange(); }, _updateColorBasedElements() { this.applyLayoutRules(); this.updateHeadingText(); this.updatePromptChipsVisibility(); this.updateTurnFooterVisibility(); this.updateInputPlaceholder(); }, _updateIconsAndSVGs() { window.EICButtonManager.update(); }, _updateComponentSpecificThemeElements() { if (window.ModalEye && window.ModalEye.updateThemeVisuals) { window.ModalEye.updateThemeVisuals(); } }, _notifyComponentsOfThemeChange() { if (window.Popup && window.State.popupElement?.classList.contains("visible")) { window.Popup.updateUIState(); } }, updateInterface() { this.updateThemeRelatedUI({ previousTheme: "default", newTheme: window.State.activeTheme }); }, updateHeadingText() { const heading = document.querySelector(window.Config.selectors.siteHeading); if (heading && window.State?.settings) { heading.textContent = window.State.settings.headingText; } }, updatePromptChipsVisibility() { const chips = document.querySelector(window.Config.selectors.promptChipsContainer); if (chips && window.State?.settings) { chips.style.display = window.State.isVibeModeActive || window.State.settings.hidePromptChips ? "none" : ""; } }, updateInputPlaceholder() { const overlay = document.querySelector(window.Config.selectors.inputPlaceholderOverlay); if (overlay) { overlay.textContent = "If I tried to write a million words a day..."; } }, updateTurnFooterVisibility() { if (!window.State?.settings) { return; } const footers = document.querySelectorAll(window.Config.selectors.chatTurnFooter); if (0 === footers.length) { return; } const shouldHide = window.State.isVibeModeActive || window.State.settings.hideFeedbackButtons; footers.forEach((footer => { footer.style.display = shouldHide ? "none" : ""; })); }, applyLayoutRules() { const layoutContainer = document.querySelector(window.Config.selectors.overallLayout); if (!layoutContainer || !window.State?.settings) { return; } const shouldHideLeftSidebar = window.State.isVibeModeActive ? !0 : window.State.settings.hideLeftSidebar; const shouldHideRightSidebar = window.State.isVibeModeActive ? !0 : window.State.settings.hideRightSidebar; const shouldHideHeader = window.State.isVibeModeActive ? !0 : window.State.settings.hideHeader; const shouldHideToolbar = window.State.isVibeModeActive ? !0 : window.State.settings.hideToolbar; const leftSidebarElement = document.querySelector(window.Config.selectors.leftSidebar); const rightSidebarElement = document.querySelector(window.Config.selectors.rightSidebar); if (leftSidebarElement) { leftSidebarElement.style.display = shouldHideLeftSidebar ? "none" : ""; } if (rightSidebarElement) { rightSidebarElement.style.display = shouldHideRightSidebar ? "none" : ""; } layoutContainer.classList.remove(`${window.Config.classes.layoutHide}-sidebars`); layoutContainer.classList.toggle(`${window.Config.classes.layoutHide}-header`, shouldHideHeader); layoutContainer.classList.toggle(`${window.Config.classes.layoutHide}-toolbar`, shouldHideToolbar); }, applyChatVisibilityDOM(visibleElementsSet) { const chatContainer = document.querySelector(window.Config.selectors.chatContainer); if (!chatContainer) { return; } const allTurns = Array.from(chatContainer.querySelectorAll(`${window.Config.selectors.userTurn}, ${window.Config.selectors.aiTurn}`)); let localDidHideSomething = !1; allTurns.forEach((turn => { const shouldBeVisible = visibleElementsSet.has(turn); const targetDisplay = shouldBeVisible ? "" : "none"; if (turn.style.display !== targetDisplay) { turn.style.display = targetDisplay; } if (!shouldBeVisible) { localDidHideSomething = !0; } })); if (window.State.isCurrentlyHidden !== localDidHideSomething) { window.State.isCurrentlyHidden = localDidHideSomething; if (window.EICButtonManager && "function" == typeof window.EICButtonManager.update) { window.EICButtonManager.update(); } } } }; window.promptcomposer = { modalElement: null, modalTextarea: null, modalContent: null, triggerButton: null, persistentModalText: "", isInitialized: !1, placeholderText: [ "Shortcuts:", "Ctrl+Shift+Enter (send)", "Alt+1…0 (insert snippet)", "Alt+M (more snippets)", "Tab/Shift+Tab (move focus)", "Esc (close composer)" ].join("\n"), clearButton: null, addButton: null, sendButton: null, snippetToolbarElement: null, moreSnippetsTriggerButton: null, renderedSnippetButtons: [], slidePanelElement: null, isSlidePanelOpen: !1, showModalBound: null, handleEscKeyBound: null, debouncedUpdateToolbarVisibilityBound: null, closeSlidePanelOnClickOutsideBound: null, init() { if (!this.isInitialized) { this.createModal(); this.isInitialized = !0; } this.createTriggerButton(); this.showModalBound = this.showModalBound || this.showModal.bind(this); this.handleEscKeyBound = this.handleEscKeyBound || this.handleEscKey.bind(this); this.debouncedUpdateToolbarVisibilityBound = this.debouncedUpdateToolbarVisibilityBound || ((func, delay) => { let timeout; return function(...args) { const context = this; clearTimeout(timeout); timeout = setTimeout((() => func.apply(context, args)), delay); }; })(this.updateToolbarButtonVisibility?.bind(this) || (() => {}), 200); this.closeSlidePanelOnClickOutsideBound = this.closeSlidePanelOnClickOutsideBound || this.closeSlidePanelOnClickOutside?.bind(this); window.removeEventListener("resize", this.debouncedUpdateToolbarVisibilityBound); window.addEventListener("resize", this.debouncedUpdateToolbarVisibilityBound); document.removeEventListener("eic-snippets-updated", this.updateSnippetToolbar.bind(this)); document.addEventListener("eic-snippets-updated", (() => { if (this.modalElement?.classList.contains("visible")) { this.updateSnippetToolbar(); } })); }, createTriggerButton() { const buttonId = "adv-modal-trigger-btn"; const targetContainerSelector = window.Config.selectors.promptInputWrapper; const existingButton = document.getElementById(buttonId); if (!existingButton || !document.body.contains(existingButton)) { if (this.triggerButton && !document.body.contains(this.triggerButton)) { this.triggerButton = null; } if (!this.triggerButton) { const parentContainer = document.querySelector(targetContainerSelector); if (!parentContainer) { return; } const button = window.DOM.createElement("button", { id: buttonId, className: "mdc-icon-button mat-mdc-icon-button mat-unthemed mat-mdc-button-base gmat-mdc-button adv-modal-trigger eic-hidden-by-default", attributes: { "mat-icon-button": "", "aria-label": "Open Prompt Composer", "mattooltip": "Open Prompt Composer" } }); const iconSpan = window.DOM.createElement("span", { className: "material-symbols-outlined notranslate", textContent: "chat_bubble" }); button.appendChild(iconSpan); button.appendChild(window.DOM.createElement("span", { className: "mat-mdc-button-persistent-ripple mdc-icon-button__ripple" })); button.appendChild(window.DOM.createElement("span", { className: "mat-focus-indicator" })); button.appendChild(window.DOM.createElement("span", { className: "mat-mdc-button-touch-target" })); const buttonWrapper = window.DOM.createElement("div", { className: "button-wrapper" }); buttonWrapper.appendChild(button); parentContainer.appendChild(buttonWrapper); this.triggerButton = button; } } else { this.triggerButton = existingButton; existingButton.removeEventListener("click", this.showModalBound); this.showModalBound = this.showModalBound || this.showModal.bind(this); existingButton.addEventListener("click", this.showModalBound); } }, createModal() { if (document.getElementById("adv-input-modal-overlay")) { this.modalElement = document.getElementById("adv-input-modal-overlay"); this.modalContent = document.getElementById("adv-input-modal-content"); this.modalTextarea = document.getElementById("adv-input-modal-textarea"); this.clearButton = this.modalContent.querySelector(".clear-textarea-btn"); this.addButton = this.modalContent.querySelector(".add-to-input-btn"); this.sendButton = this.modalContent.querySelector(".send-prompt-btn"); this.updateSnippetToolbar(); return; } this.modalElement = window.DOM.createElement("div", { id: "adv-input-modal-overlay", className: "eic-modal-overlay", events: { click: event => { if (event.target === this.modalElement) { this.handleCancel(); } } } }); this.modalContent = window.DOM.createElement("div", { id: "adv-input-modal-content" }); this.snippetToolbarElement = this.buildAndAttachSnippetToolbar(); this.slidePanelElement = this.buildAndAttachSlidePanel(); this.modalTextarea = window.DOM.createElement("textarea", { id: "adv-input-modal-textarea", placeholder: this.placeholderText, events: { click: event => event.stopPropagation(), keydown: this.handleTextareaKeyDown.bind(this) } }); this.modalContent.appendChild(this.modalTextarea); const buttonContainer = window.DOM.createElement("div", { className: "adv-modal-buttons" }); buttonContainer.addEventListener("click", (event => event.stopPropagation())); const createModalButton = (text, className, onClick, id = null) => { const button = window.DOM.createElement("button", { textContent: text, className: className, id: id, events: { click: onClick } }); return button; }; this.clearButton = createModalButton("Clear Text", "eic-modal-button clear-textarea-btn", this.handleClearText.bind(this), "eic-composer-clear-btn"); this.addButton = createModalButton("Add to Input", "eic-modal-button add-to-input-btn", this.handleAdd.bind(this), "eic-composer-add-btn"); this.sendButton = createModalButton("Send", "eic-modal-button send-prompt-btn eic-button-primary", this.handleSend.bind(this), "eic-composer-send-btn"); this.sendButton.addEventListener("keydown", (event => { if ("Tab" === event.key && event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey) { event.preventDefault(); this.modalTextarea.focus(); } })); this.addButton.addEventListener("keydown", (event => { if (!("Tab" !== event.key || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey)) { event.preventDefault(); this.modalTextarea.focus(); } })); buttonContainer.appendChild(this.clearButton); buttonContainer.appendChild(this.addButton); buttonContainer.appendChild(this.sendButton); this.modalContent.appendChild(buttonContainer); this.modalElement.appendChild(this.modalContent); document.body.appendChild(this.modalElement); }, buildAndAttachSnippetToolbar() { const existingToolbar = document.getElementById("eic-snippet-toolbar-container"); if (existingToolbar) { existingToolbar.remove(); } this.renderedSnippetButtons = []; if (!window.State.settings.showSnippetToolbarInModal || !window.State.settings.promptSnippets || 0 === window.State.settings.promptSnippets.length) { return null; } const toolbarContainerDiv = window.DOM.createElement("div", { id: "eic-snippet-toolbar-container", className: "snippet-toolbar-container" }); const mainButtonsBarDiv = window.DOM.createElement("div", { className: "snippet-main-toolbar-bar" }); const maxButtons = window.Config?.vars?.maxRenderedToolbarSnippets || 4; const snippets = window.State.settings.promptSnippets; for (let i = 0; i < Math.min(snippets.length, maxButtons); i++) { const snippet = snippets[i]; const shortcutKey = i < 9 ? i + 1 : 9 === i ? 0 : null; const shortcutHint = null !== shortcutKey ? ` (Alt+${shortcutKey})` : ""; const button = window.DOM.createElement("button", { className: "snippet-button eic-snippet-btn-hidden", textContent: snippet.name, attributes: { "data-snippet-index": i, title: snippet.content.substring(0, 100) + (snippet.content.length > 100 ? "..." : "") + shortcutHint, "aria-label": `${snippet.name}${shortcutHint}` }, events: { click: () => this.insertSnippetContent(snippet.content) } }); this.renderedSnippetButtons.push(button); mainButtonsBarDiv.appendChild(button); } const separatorDiv = window.DOM.createElement("div", { className: "snippet-toolbar-separator" }); mainButtonsBarDiv.appendChild(separatorDiv); toolbarContainerDiv.appendChild(mainButtonsBarDiv); this.moreSnippetsTriggerButton = window.DOM.createElement("button", { className: "more-snippets-panel-trigger eic-snippet-btn-hidden", textContent: "...", attributes: { title: "More snippets (Alt+M)", "aria-label": "More snippets (Alt+M)" }, events: { click: event => this.toggleMoreSnippetsPanel(event) } }); toolbarContainerDiv.appendChild(this.moreSnippetsTriggerButton); if (this.modalContent && this.modalContent.firstChild) { this.modalContent.insertBefore(toolbarContainerDiv, this.modalContent.firstChild); } else if (this.modalContent) { this.modalContent.appendChild(toolbarContainerDiv); } this.updateToolbarButtonVisibility(); return toolbarContainerDiv; }, buildAndAttachSlidePanel() { const existingPanel = document.getElementById("eic-snippet-slide-panel"); if (existingPanel) { existingPanel.remove(); } const panel = window.DOM.createElement("div", { id: "eic-snippet-slide-panel", className: "snippet-slide-panel", attributes: { "aria-hidden": "false" } }); const panelListDiv = window.DOM.createElement("div", { className: "slide-panel-list" }); const emptyMessageDiv = window.DOM.createElement("div", { className: "slide-panel-empty-message", textContent: "Add snippets from library" }); panel.appendChild(panelListDiv); panel.appendChild(emptyMessageDiv); if (this.modalContent) { this.modalContent.appendChild(panel); } this.slidePanelElement = panel; return panel; }, populateSlidePanelContent() { if (!this.slidePanelElement) { return; } const panelList = this.slidePanelElement.querySelector(".slide-panel-list"); const emptyMessage = this.slidePanelElement.querySelector(".slide-panel-empty-message"); if (!panelList || !emptyMessage) { return; } for (;panelList.firstChild; ) { panelList.removeChild(panelList.firstChild); } const numVisible = this.renderedSnippetButtons.filter((btn => !btn.classList.contains("eic-snippet-btn-hidden"))).length; let added = 0; const snippets = window.State.settings.promptSnippets || []; for (let i = 0; i < snippets.length; i++) { if (i >= numVisible || i >= (window.Config?.vars?.maxRenderedToolbarSnippets || 4)) { const snippet = snippets[i]; const shortcutKey = i < 9 ? i + 1 : 9 === i ? 0 : null; const shortcutHint = null !== shortcutKey ? ` (Alt+${shortcutKey})` : ""; const item = document.createElement("div"); item.className = "slide-panel-snippet-item"; item.setAttribute("data-snippet-index", i); item.setAttribute("title", `${snippet.content.substring(0, 100)}${snippet.content.length > 100 ? "..." : ""}${shortcutHint}`); item.textContent = snippet.name; item.addEventListener("click", (() => { this.insertSnippetContent(snippet.content); this.toggleMoreSnippetsPanel(null, !1); })); panelList.appendChild(item); added++; } } emptyMessage.style.display = 0 === added ? "" : "none"; }, toggleMoreSnippetsPanel(event, forceState) { if (event) { event.stopPropagation(); } if (!this.slidePanelElement) { this.slidePanelElement = this.buildAndAttachSlidePanel(); } const shouldBeOpen = "boolean" == typeof forceState ? forceState : !this.isSlidePanelOpen; if (shouldBeOpen) { this.populateSlidePanelContent(); this.slidePanelElement.classList.add("visible"); this.slidePanelElement.setAttribute("aria-hidden", "false"); this.isSlidePanelOpen = !0; document.addEventListener("click", this.closeSlidePanelOnClickOutsideBound, !0); } else { this.slidePanelElement.classList.remove("visible"); this.slidePanelElement.setAttribute("aria-hidden", "true"); this.isSlidePanelOpen = !1; document.removeEventListener("click", this.closeSlidePanelOnClickOutsideBound, !0); this.modalTextarea?.focus(); } }, closeDropdownOnClickOutside(event) { const dropdown = document.getElementById("snippets-dropdown"); const moreButton = this.modalContent?.querySelector(".more-snippets-btn"); if (dropdown && dropdown.classList.contains("visible") && !dropdown.contains(event.target) && (!moreButton || !moreButton.contains(event.target))) { dropdown.classList.remove("visible"); } }, updateSnippetToolbar() { const existingToolbar = document.getElementById("snippet-toolbar-container"); if (existingToolbar) { existingToolbar.remove(); } if (window.State.settings.showSnippetToolbarInModal) { this.buildAndAttachSnippetToolbar(); } }, toggleSnippetsDropdown(event) { event.stopPropagation(); const dropdown = document.getElementById("snippets-dropdown"); if (dropdown) { dropdown.classList.toggle("visible"); } }, insertSnippetContent(content) { if (!this.modalTextarea) { return; } const startPos = this.modalTextarea.selectionStart; const endPos = this.modalTextarea.selectionEnd; const textBefore = this.modalTextarea.value.substring(0, startPos); const textAfter = this.modalTextarea.value.substring(endPos); this.modalTextarea.value = textBefore + content + textAfter; this.persistentModalText = this.modalTextarea.value; const newCursorPos = startPos + content.length; this.modalTextarea.setSelectionRange(newCursorPos, newCursorPos); this.modalTextarea.dispatchEvent(new Event("input", { bubbles: !0, cancelable: !0 })); this.modalTextarea.focus(); }, handleClearText() { if (this.modalTextarea) { this.modalTextarea.value = ""; this.persistentModalText = ""; this.modalTextarea.dispatchEvent(new Event("input", { bubbles: !0, cancelable: !0 })); this.modalTextarea.focus(); } }, showModal() { if (!this.modalElement && this.isInitialized) { this.createModal(); } else if (!this.isInitialized) { this.init(); } if (this.modalElement) { this.modalTextarea.value = this.persistentModalText; this.modalElement.classList.add("visible"); this.updateToolbarButtonVisibility(); this.modalTextarea.focus(); this.handleEscKeyBound = this.handleEscKeyBound || this.handleEscKey.bind(this); document.addEventListener("keydown", this.handleEscKeyBound); } }, hideModal() { if (this.isSlidePanelOpen) { this.toggleMoreSnippetsPanel(null, !1); } if (this.modalElement) { this.modalElement.classList.remove("visible"); } if (this.handleEscKeyBound) { document.removeEventListener("keydown", this.handleEscKeyBound); } if (this.closeSlidePanelOnClickOutsideBound) { document.removeEventListener("click", this.closeSlidePanelOnClickOutsideBound, !0); } }, handleEscKey(event) { if ("Escape" === event.key) { if (this.isSlidePanelOpen) { this.toggleMoreSnippetsPanel(null, !1); event.preventDefault(); event.stopPropagation(); return; } if (this.modalElement?.classList.contains("visible")) { this.handleCancel(); event.preventDefault(); event.stopPropagation(); } } }, handleCancel() { if (this.modalTextarea) { this.persistentModalText = this.modalTextarea.value; this.hideModal(); } }, handleAdd() { if (!this.modalTextarea) { return; } const realInput = document.querySelector(window.Config.selectors.chatInput); if (!realInput) { this.hideModal(); return; } const textToAdd = this.modalTextarea.value; this.persistentModalText = ""; this.modalTextarea.value = ""; realInput.value += (realInput.value.trim() ? "\n" : "") + textToAdd; realInput.dispatchEvent(new Event("input", { bubbles: !0, cancelable: !0 })); realInput.dispatchEvent(new Event("change", { bubbles: !0, cancelable: !0 })); this.hideModal(); }, handleSend() { if (!this.modalTextarea) { return; } const realInput = document.querySelector(window.Config.selectors.chatInput); const realRunButton = document.querySelector(window.Config.selectors.runButton); if (!realInput || !realRunButton) { this.hideModal(); return; } const textToSend = this.modalTextarea.value; if (textToSend.trim()) { realInput.value += (realInput.value.trim() ? "\n" : "") + textToSend; realInput.dispatchEvent(new Event("input", { bubbles: !0, cancelable: !0 })); realInput.dispatchEvent(new Event("change", { bubbles: !0, cancelable: !0 })); setTimeout((() => { if (realRunButton && !realRunButton.disabled) { realRunButton.click(); this.persistentModalText = ""; if (this.modalTextarea) { this.modalTextarea.value = ""; } } else { this.persistentModalText = textToSend; } this.hideModal(); }), 150); } }, toggleModalVisibility() { if (!this.modalElement && this.isInitialized) { this.createModal(); } else if (!this.isInitialized) { this.init(); } if (this.modalElement) { if (this.modalElement.classList.contains("visible")) { this.handleCancel(); } else { this.showModal(); } } }, updateToolbarButtonVisibility() { if (!this.snippetToolbarElement || !window.State.settings.showSnippetToolbarInModal) { if (this.snippetToolbarElement) { this.snippetToolbarElement.style.display = "none"; } return; } this.snippetToolbarElement.style.display = ""; const containerWidth = this.snippetToolbarElement.offsetWidth; const avgButtonWidth = window.Config?.vars?.avgSnippetButtonWidth || 80; const moreButtonWidth = window.Config?.vars?.moreSnippetsButtonWidth || 40; const totalSnippets = window.State.settings.promptSnippets.length; let availableWidthForSnippets = containerWidth; if (totalSnippets > 0) { availableWidthForSnippets -= moreButtonWidth; } let numButtonsToMakeVisible = Math.floor(availableWidthForSnippets / avgButtonWidth); numButtonsToMakeVisible = Math.min(numButtonsToMakeVisible, totalSnippets, window.Config?.vars?.maxRenderedToolbarSnippets || 4); numButtonsToMakeVisible = Math.max(numButtonsToMakeVisible, 0); for (let i = 0; i < this.renderedSnippetButtons.length; i++) { if (i < numButtonsToMakeVisible) { this.renderedSnippetButtons[i].classList.remove("eic-snippet-btn-hidden"); } else { this.renderedSnippetButtons[i].classList.add("eic-snippet-btn-hidden"); } } this.moreSnippetsTriggerButton.classList.remove("eic-snippet-btn-hidden"); if (0 === totalSnippets && this.isSlidePanelOpen) { this.toggleMoreSnippetsPanel(null, !1); } }, handleTextareaKeyDown(event) { if (!event.ctrlKey || !event.shiftKey || "Enter" !== event.key) { if (event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) { const keyNumber = parseInt(event.key); if (!isNaN(keyNumber) && keyNumber >= 0 && keyNumber <= 9) { event.preventDefault(); const snippetIndex = 0 === keyNumber ? 9 : keyNumber - 1; if (window.State.settings.promptSnippets && window.State.settings.promptSnippets.length > snippetIndex && window.State.settings.promptSnippets[snippetIndex]) { this.insertSnippetContent(window.State.settings.promptSnippets[snippetIndex].content); } return; } } if ("Tab" === event.key) { if (event.shiftKey) { if (this.addButton) { event.preventDefault(); this.addButton.focus(); } } else if (this.sendButton) { event.preventDefault(); this.sendButton.focus(); } } } else { event.preventDefault(); this.handleSend(); } } }; window.ModalEye = { _modalStateToSvgState: { "idle": "Default", "startOpening": "Default", "finishOpeningDefaultSvgFadeOut": "Default", "hoverSvgFadingIn": "Hover", "textareaFadingIn": "Hover", "awaitingInput": "Hover", "inputSentTextareaFadingOut": "Hover", "activeSvgFadingIn": "Active", "processing": "Active", "confirmationTextFadingIn": "Hover", "startClosingFromConfirmation": "Default", "startClosingFromInput": "Default", "closingToDefaultSvg": "Default", "modalZoomFadingOut": "Default" }, _currentState: "idle", _confirmationText: "", _modalElement: null, _overlayElement: null, _svgBgElement: null, _textareaElement: null, _animationDuration: 500, _shortDelay: 400, _init() { this._overlayElement = window.DOM.createElement("div", { id: window.Config.ids.aiThemeModalOverlay, className: "eic-modal-overlay" }); this._modalElement = window.DOM.createElement("div", { id: window.Config.ids.aiThemeModal, className: "eic-eye-modal" }); this._svgBgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg"); this._svgBgElement.id = window.Config.ids.aiThemeModalSvgBg; this._svgBgElement.classList.add("eic-modal-svg-background"); this._textareaElement = window.DOM.createElement("textarea", { id: window.Config.ids.aiThemeModalTextarea, className: "eic-textarea" }); this._modalElement.appendChild(this._svgBgElement); this._modalElement.appendChild(this._textareaElement); this._overlayElement.appendChild(this._modalElement); document.body.appendChild(this._overlayElement); this._overlayElement.addEventListener("click", (e => { if (e.target === this._overlayElement) { this._handleExitAttempt(); } })); document.addEventListener("keydown", (e => { if ("Escape" === e.key) { this._handleExitAttempt(); } })); this._textareaElement.addEventListener("keydown", (e => { if ("awaitingInput" === this._currentState && "Enter" === e.key && !e.shiftKey) { e.preventDefault(); this.handleInputSend(); } })); this._textareaElement.addEventListener("input", (() => { if (this._textareaElement.value.trim().startsWith("/")) { this._textareaElement.classList.add("command-mode"); } else { this._textareaElement.classList.remove("command-mode"); } })); }, _getSvgForTheme: svgState => window.ThemeManager.getSvgIconData(svgState), _renderSvg(svgData) { for (;this._svgBgElement.firstChild; ) { this._svgBgElement.removeChild(this._svgBgElement.firstChild); } const svgElement = window.Icons.createSvgElement(svgData, { mode: "background", preserveAspectRatio: "xMidYMid meet" }); this._svgBgElement.appendChild(svgElement); }, _setModalAnimation(animationClass, makeVisible) { this._modalElement.classList.remove(window.Config.classes.aiThemeModalVisible, window.Config.classes.aiThemeModalAnimateOut, "visible", "eic-modal-active-state", "eic-ai-modal-zoom-fade-in", "eic-ai-modal-zoom-fade-out"); if (animationClass) { this._modalElement.classList.add(animationClass); } else if (makeVisible) { this._modalElement.classList.add("visible"); } }, _setTextareaVisible(visible) { this._textareaElement.classList.toggle("eic-textarea-visible", visible); }, _setSvgWithFade(svgData, fadeOutFirst = !1) { if (fadeOutFirst) { this._svgBgElement.style.opacity = "0"; setTimeout((() => { this._renderSvg(svgData); this._svgBgElement.style.opacity = "1"; }), this._animationDuration / 2); } else { this._renderSvg(svgData); this._svgBgElement.style.opacity = "1"; } }, _handleExitAttempt() { if ("processing" === this._currentState) { const confirmed = confirm("Theme generation in progress. Are you sure you want to cancel?"); if (confirmed) { this.setState("startClosingFromInput"); } } else { this.setState("startClosingFromInput"); } }, setState(newState) { this._currentState = newState; switch (newState) { case "idle": this._overlayElement.classList.remove("visible"); this._setModalAnimation(null, !1); this._setTextareaVisible(!1); this._textareaElement.value = ""; this._textareaElement.readOnly = !1; this._textareaElement.disabled = !1; this._confirmationText = ""; if (window.State?.pageOverlay?.classList.contains("visible")) { window.State.pageOverlay.classList.remove("visible"); window.State.pageOverlay.style.pointerEvents = "none"; } this._svgBgElement.style.opacity = "0"; break; case "startOpening": this._overlayElement.classList.add("visible"); this._setModalAnimation(window.Config.classes.aiThemeModalVisible, !0); this._setSvgWithFade(this._getSvgForTheme("Default")); setTimeout((() => this.setState("finishOpeningDefaultSvgFadeOut")), this._animationDuration); break; case "finishOpeningDefaultSvgFadeOut": this._svgBgElement.style.opacity = "0"; setTimeout((() => this.setState("hoverSvgFadingIn")), this._shortDelay); break; case "hoverSvgFadingIn": this._setSvgWithFade(this._getSvgForTheme("Hover")); setTimeout((() => this.setState("textareaFadingIn")), this._animationDuration); break; case "textareaFadingIn": this._textareaElement.value = ""; this._textareaElement.placeholder = "Describe the theme you desire or use commands:\n\n/eye: Theme based on AI's communication style\n/i: Theme tailored to YOUR communication style\n/reset: Restore default theme settings"; this._textareaElement.readOnly = !1; this._textareaElement.disabled = !1; this._setTextareaVisible(!0); this._textareaElement.focus(); this._currentState = "awaitingInput"; break; case "inputSentTextareaFadingOut": this._setTextareaVisible(!1); this._textareaElement.disabled = !0; setTimeout((() => this.setState("activeSvgFadingIn")), this._animationDuration); break; case "activeSvgFadingIn": this._setSvgWithFade(this._getSvgForTheme("Active"), !0); setTimeout((() => this.setState("processing")), this._animationDuration); break; case "processing": window.State?.pageOverlay?.classList.add("visible"); window.State.pageOverlay.style.pointerEvents = "auto"; if (this._pendingUserInput) { window.EyeCommands.processInputAndExecute(this._pendingUserInput); this._pendingUserInput = null; } break; case "confirmationTextFadingIn": window.State?.pageOverlay?.classList.remove("visible"); window.State.pageOverlay.style.pointerEvents = "none"; this._textareaElement.value = this._confirmationText || "Theme applied successfully!"; this._textareaElement.readOnly = !0; this._textareaElement.disabled = !0; this._setTextareaVisible(!0); this._svgBgElement.style.opacity = "0"; setTimeout((() => { this._setSvgWithFade(this._getSvgForTheme("Hover")); }), this._shortDelay); break; case "startClosingFromInput": case "startClosingFromConfirmation": this._setTextareaVisible(!1); setTimeout((() => this.setState("closingToDefaultSvg")), this._animationDuration / 2); break; case "closingToDefaultSvg": this._setSvgWithFade(this._getSvgForTheme("Default"), !0); setTimeout((() => this.setState("modalZoomFadingOut")), this._animationDuration); break; case "modalZoomFadingOut": this._setModalAnimation(window.Config.classes.aiThemeModalAnimateOut, !1); setTimeout((() => this.setState("idle")), this._animationDuration); break; default: this.setState("idle"); } }, open() { if (window.State?.popupElement?.classList.contains("visible") && window.Popup?.hide) { window.Popup.hide(); } this.setState("startOpening"); }, handleInputSend() { const rawUserInput = this._textareaElement.value; const trimmedInput = rawUserInput.trim(); const commandInput = trimmedInput.toLowerCase(); if (trimmedInput) { if ("/eye" !== commandInput && "/i" !== commandInput || !(this._getChatTurnCount() < window.Config.minExchangesForProfileTheme)) { if (!commandInput.startsWith("/") || "/eye" === commandInput || "/i" === commandInput || "/reset" === commandInput) { this.setState("inputSentTextareaFadingOut"); this._pendingUserInput = rawUserInput; } else { window.NotificationManager.showNotification(`Unknown command: ${commandInput.split(" ")[0]}`); } } else { window.NotificationManager.showNotification("Chat more to unlock this insight!"); } } else { window.NotificationManager.showNotification("Please enter a theme description or command."); } }, processingComplete() { this._confirmationText = window.State.aiThemeModalConfirmationText || "Theme applied successfully!"; this.setState("confirmationTextFadingIn"); }, _getChatTurnCount() { const userTurns = document.querySelectorAll(window.Config.selectors.userTurn).length; const aiTurns = document.querySelectorAll(window.Config.selectors.aiTurn).length; return userTurns + aiTurns; }, updateThemeVisuals() { const fsmSvgState = this._modalStateToSvgState[this._currentState] || "Default"; const svgDataToRender = this._getSvgForTheme(fsmSvgState); if (svgDataToRender) { this._renderSvg(svgDataToRender); this._svgBgElement.style.opacity = "idle" === this._currentState ? "0" : "1"; } } }; window.Popup = { _personalThemeVarLabels: { "--eic-global-background": "Overall Page Background", "--eic-global-surface": "Panel & Popup Background", "--eic-global-surface-variant": "Chat Bubble & Button Background", "--eic-global-surface-variant-alt": "Modal Input Area Background", "--eic-global-on-surface": "Main Text Color", "--eic-global-on-surface-variant": "Subtle & Button Text Color", "--eic-global-primary": "Main Action & Highlight Color", "--eic-global-on-primary": "Text on Main Action/Highlights", "--eic-global-outline": "Borders & Lines", "--eic-global-outline-variant": "Subtle Lines & Dividers", "--eic-global-tertiary": "Notification & Editor Header Color", "--eic-global-on-tertiary": "Text on Notifications/Editor Headers", "--eic-global-error": "Error Message Color", "--eic-global-on-error": "Text on Error Messages", "--eic-global-font-family": "Font Style", "--eic-global-font-size": "Overall Text Size", "--eic-global-shape-radius-small": "Button Corner Rounding", "--eic-global-shape-radius-medium": "Panel & Card Corner Rounding", "--eic-global-shape-radius-large": "Large Modal Corner Rounding", "--eic-global-shadow": "Shadow Effect", "--eic-global-scrim": "Dimming Overlay (Behind Popups)", "--eic-global-modal-overlay-bg": "Modal Background Overlay", "--eic-global-secondary": "Secondary Accent Color", "--eic-global-on-secondary": "Text on Secondary Accent" }, _personalThemeVarTooltips: { "--eic-global-background": "Variable: --eic-global-background\nThe main background color of the entire AI Studio page.", "--eic-global-surface": "Variable: --eic-global-surface\nBackground for main content areas like sidebars, the main EIC settings popup, and similar panels.", "--eic-global-surface-variant": "Variable: --eic-global-surface-variant\nBackground for AI Studio chat bubbles, some EIC buttons (like theme editor controls), and hover states.", "--eic-global-surface-variant-alt": "Variable: --eic-global-surface-variant-alt\nBackground for larger text input areas within EIC modals (e.g., Input Lag Fix, Personal Theme Editor inputs).", "--eic-global-on-surface": "Variable: --eic-global-on-surface\nDefault text color on panels, popups, and chat bubbles.", "--eic-global-on-surface-variant": "Variable: --eic-global-on-surface-variant\nFor less prominent text, and text on some EIC buttons (like theme editor controls).", "--eic-global-primary": "Variable: --eic-global-primary\nImpacts: Run button, Model temperature sliders, active EIC theme buttons.", "--eic-global-on-primary": "Variable: --eic-global-on-primary\nImpacts: Text/icons inside the Run button and active EIC theme buttons.", "--eic-global-outline": "Variable: --eic-global-outline\nMain borders around input fields, panels, and dividing lines.", "--eic-global-outline-variant": "Variable: --eic-global-outline-variant\nFainter lines, like those within menus or for less distinct separation.", "--eic-global-tertiary": "Variable: --eic-global-tertiary\nImpacts: EIC notification popups, EIC Personal Theme Editor header background.", "--eic-global-on-tertiary": "Variable: --eic-global-on-tertiary\nImpacts: Text on EIC notification popups and the EIC Personal Theme Editor header.", "--eic-global-error": "Variable: --eic-global-error\nColor for error messages and warning indicators.", "--eic-global-on-error": "Variable: --eic-global-on-error\nText color on error message backgrounds.", "--eic-global-font-family": 'Variable: --eic-global-font-family\nExamples: "Arial, sans-serif", "Courier New, monospace".', "--eic-global-font-size": 'Variable: --eic-global-font-size\nExamples: "16px", "1rem", "0.9em".', "--eic-global-shape-radius-small": 'Variable: --eic-global-shape-radius-small\nExamples: "4px", "20px", "0px" (for square).', "--eic-global-shape-radius-medium": 'Variable: --eic-global-shape-radius-medium\nImpacts: Chat bubbles, EIC popups, etc. Examples: "8px", "0px".', "--eic-global-shape-radius-large": 'Variable: --eic-global-shape-radius-large\nImpacts: Larger EIC modals (e.g., Input Lag Fix editor). Examples: "12px", "0px".', "--eic-global-shadow": 'Variable: --eic-global-shadow\nDefines shadow color & properties. Example: "rgba(0,0,0,0.2) 0px 2px 5px".', "--eic-global-scrim": 'Variable: --eic-global-scrim\nColor for semi-transparent overlays that dim the main page when a popup is active. Example: "rgba(0,0,0,0.4)".', "--eic-global-modal-overlay-bg": 'Variable: --eic-global-modal-overlay-bg\nBackground for the full-screen overlay behind EIC modals (e.g., Input Lag Fix). Example: "rgba(50,50,50,0.6)".', "--eic-global-secondary": "Variable: --eic-global-secondary\nWe haven't spotted where AI Studio uses this yet! Could be used by EIC themes.", "--eic-global-on-secondary": "Variable: --eic-global-on-secondary\nText color for the Secondary Accent Color above." }, activeTab: "history", showAiThemeInputModal() { if (window.ModalEye && "function" == typeof window.ModalEye.open) { window.ModalEye.open(); } }, togglePersonalThemeEditor() { const editor = document.getElementById("eic-personal-theme-editor"); if (editor) { editor.style.display = "none" === editor.style.display || !editor.style.display ? "flex" : "none"; if ("flex" === editor.style.display) { this.loadPersonalPaletteToEditor(); } } }, loadPersonalPaletteToEditor() { const customActive = window.State.settings.isCustomProfileActive; const palette = customActive && window.State.settings.customProfileAssets.colorPalette ? window.State.settings.customProfileAssets.colorPalette : this._getComputedThemeVariables(); Object.entries(palette).forEach((([varName, value]) => { const input = document.querySelector(`#eic-personal-theme-editor input[data-varname="${varName}"]`); if (input) { input.value = value; if ("color" === input.type) { const preview = input.previousElementSibling; if (preview && preview.classList.contains("color-preview")) { preview.style.backgroundColor = value; } } } })); }, savePersonalPalette() { const editor = document.getElementById("eic-personal-theme-editor"); if (!editor) { return; } const editedColors = {}; const inputs = editor.querySelectorAll("input[data-varname]"); inputs.forEach((input => { if (input.getAttribute("data-varname").startsWith("--eic-global-")) { editedColors[input.getAttribute("data-varname")] = input.value; } })); const currentProfileActive = window.State.settings.isCustomProfileActive; if (!currentProfileActive) { if (window.EIC_Icons_Personal && window.EIC_Icons_Personal.buttonStates) { window.State.settings.customProfileAssets.svgDefault = JSON.parse(JSON.stringify(window.EIC_Icons_Personal.buttonStates.Default)); window.State.settings.customProfileAssets.svgHover = JSON.parse(JSON.stringify(window.EIC_Icons_Personal.buttonStates.Hover)); window.State.settings.customProfileAssets.svgActive = JSON.parse(JSON.stringify(window.EIC_Icons_Personal.buttonStates.Active)); } } window.State.settings.customProfileAssets.colorPalette = editedColors; window.Settings.update("customProfileAssets", window.State.settings.customProfileAssets); window.Settings.update("isCustomProfileActive", !0); if ("personal" === window.State.activeTheme && window.ThemeManager) { window.ThemeManager.applyTheme("personal"); } this.togglePersonalThemeEditor(); this.showNotification("Personal theme customized and saved!"); }, handleCancelPersonalThemeEdit() { this.togglePersonalThemeEditor(); }, resetPersonalPalette() { if (confirm("Are you sure you want to reset your personal theme to its factory default settings? This will clear any AI-generated or manually edited personal themes.")) { window.Settings.update("isCustomProfileActive", !1); if ("personal" === window.State.activeTheme && window.ThemeManager) { window.ThemeManager.applyTheme("personal"); } if ("flex" === document.getElementById("eic-personal-theme-editor")?.style.display) { this.loadPersonalPaletteToEditor(); } this.showNotification("Personal theme reset to factory defaults."); } }, showNotification(message, duration = 3e3) { const existingNotification = document.getElementById("eic-notification"); if (existingNotification) { existingNotification.remove(); } const notification = window.DOM.createElement("div", { id: "eic-notification", className: "eic-notification", textContent: message }); document.body.appendChild(notification); setTimeout((() => notification.classList.add("show")), 10); setTimeout((() => { notification.classList.remove("show"); setTimeout((() => notification.remove()), 300); }), duration); }, _ensurePageOverlay() { if (!window.State.pageOverlay || !document.body.contains(window.State.pageOverlay)) { window.State.pageOverlay = document.getElementById(window.Config.ids.pageOverlay); if (!window.State.pageOverlay) { window.State.pageOverlay = window.DOM.createElement("div", { id: window.Config.ids.pageOverlay, className: "eic-modal-overlay" }); document.body.appendChild(window.State.pageOverlay); } if (!window.State.pageOverlay._eicClickHandler) { window.State.pageOverlay.addEventListener("click", (e => { const editor = document.getElementById("eic-personal-theme-editor"); if (!editor || "flex" !== editor.style.display) { window.Popup.hide(); } else { editor.style.display = "none"; } })); window.State.pageOverlay._eicClickHandler = !0; } } window.State.pageOverlay.style.background = "transparent"; }, create() { if (document.getElementById(window.Config.ids.popup)) { return !0; } window.State.popupElement = window.DOM.createElement("div", { id: window.Config.ids.popup }); document.body.appendChild(window.State.popupElement); const headerDiv = window.DOM.createElement("div", { className: "popup-header" }); const titleDisplay = window.DOM.createElement("div", { id: "popup-editable-title", className: "popup-title popup-editable-title", textContent: window.State.settings.headingText || "Eye in the Cloud", title: "Click to edit title", tabindex: "0", events: { click: e => this.enterEditTitleMode(e.target), focus: e => this.enterEditTitleMode(e.target) } }); const closeButton = window.DOM.createElement("button", { className: "eic-button eic-button-icon-only close-popup-button", events: { click: this.hide } }); window.Icons.inject(closeButton, "close"); headerDiv.appendChild(titleDisplay); headerDiv.appendChild(closeButton); window.State.popupElement.appendChild(headerDiv); const popupTopControls = window.DOM.createElement("div", { className: "popup-top-controls" }); const vibeSection = window.DOM.createElement("div", { className: "popup-section vibe-section" }); const vibeButton = window.DOM.createElement("button", { id: "vibe-mode-toggle", className: "eic-button vibe-button", events: { click: this.toggleVibeMode.bind(this), mouseover: () => this.updateTooltip("VIBE Mode: Minimal distraction interface."), mouseout: () => this.updateTooltip() } }); window.Icons.inject(vibeButton, "bolt", { addContainerClass: !1 }); vibeButton.appendChild(window.DOM.createElement("span", { textContent: "VIBE" })); vibeSection.appendChild(vibeButton); popupTopControls.appendChild(vibeSection); const aiThemeGenButton = window.DOM.createElement("button", { id: window.Config.ids.aiThemeStudioButton, className: "eic-button ai-theme-studio-button", style: "width: 100%; justify-content: center;", events: { click: () => { this.showAiThemeInputModal(); }, mouseover: () => this.updateTooltip("Launch The Eye: AI-Powered Theme Studio to generate and customize your visual experience."), mouseout: () => this.updateTooltip() } }); const eyeButtonIconSlot = window.DOM.createElement("span", { className: "eic-button-icon-svg-slot" }); const eyeIconData = window.ThemeManager.getSvgIconData("Default"); if (eyeIconData && "function" == typeof window.Icons?.createSvgElement) { const svgElement = window.Icons.createSvgElement(eyeIconData); if (svgElement) { eyeButtonIconSlot.appendChild(svgElement); } } aiThemeGenButton.insertBefore(eyeButtonIconSlot, aiThemeGenButton.firstChild); aiThemeGenButton.appendChild(document.createTextNode("The Eye")); popupTopControls.appendChild(aiThemeGenButton); window.State.aiThemeStudioButton = aiThemeGenButton; window.State.popupElement.appendChild(popupTopControls); const contentDiv = window.DOM.createElement("div", { className: "popup-content" }); const tabButtonsContainer = window.DOM.createElement("div", { className: "eic-tab-buttons" }); const tabContentContainer = window.DOM.createElement("div", { className: "eic-tab-content-panels" }); contentDiv.appendChild(tabButtonsContainer); contentDiv.appendChild(tabContentContainer); [ { id: "history", label: "History", tooltip: "View and configure conversation history settings." }, { id: "hide", label: "Hide", tooltip: "Configure which UI elements to hide." }, { id: "themes", label: "Themes", tooltip: "Select and customize appearance themes." }, { id: "snippets", label: "Snippets", tooltip: "Manage your saved prompt snippets." } ].forEach((tabInfo => { const tabBtn = window.DOM.createElement("button", { id: `tab-btn-${tabInfo.id}`, className: "eic-tab-button", textContent: tabInfo.label, "data-tab-target": `tab-content-${tabInfo.id}`, events: { click: e => this.handleTabClick(e), mouseover: () => this.updateTooltip(tabInfo.tooltip), mouseout: () => this.updateTooltip() } }); tabButtonsContainer.appendChild(tabBtn); const tabPanel = window.DOM.createElement("div", { id: `tab-content-${tabInfo.id}`, className: "eic-tab-panel", style: "display:none;" }); tabContentContainer.appendChild(tabPanel); })); contentDiv.appendChild(tabButtonsContainer); contentDiv.appendChild(tabContentContainer); const historyPanel = tabContentContainer.querySelector("#tab-content-history"); window.HistoryManager.createHistoryPanel(historyPanel); const hidePanel = tabContentContainer.querySelector("#tab-content-hide"); const uiFieldset = window.DOM.createElement("fieldset", { className: "popup-section" }); [ { key: "hideLeftSidebar", label: "Left Sidebar", tip: "Hide the left navigation panel." }, { key: "hideRightSidebar", label: "Right Sidebar", tip: "Hide the right info panel." }, { key: "hideHeader", label: "Header", tip: "Hide the main top header." }, { key: "hideToolbar", label: "Toolbar", tip: "Hide the prompt input formatting toolbar." }, { key: "hidePromptChips", label: "Prompt Chips", tip: "Hide suggested prompt chips." }, { key: "hideFeedbackButtons", label: "Feedback Buttons", tip: "Hide thumbs up/down on chat turns." } ].forEach((item => { const toggle = window.DOM.createToggle(`${item.key}-toggle`, item.label, window.State.settings[item.key], (checked => window.Settings.update(item.key, checked))); toggle.addEventListener("mouseover", (() => this.updateTooltip(item.tip))); toggle.addEventListener("mouseout", (() => this.updateTooltip())); uiFieldset.appendChild(toggle); })); hidePanel.appendChild(uiFieldset); const themesPanel = tabContentContainer.querySelector("#tab-content-themes"); const themeSection = window.DOM.createElement("fieldset", { className: "popup-section theme-section" }); const themeButtonsContainer = window.DOM.createElement("div", { className: "theme-buttons-container" }); [ { name: "dos", iconKey: "dosDefault", tip: "Apply DOS-style retro theme." }, { name: "nature", iconKey: "natureDefault", tip: "Apply nature-inspired theme." }, { name: "personal", iconKey: "personalDefault", tip: "Apply and customize your personal theme." } ].forEach((theme => { const themeButton = window.DOM.createElement("button", { className: "eic-button eic-button-icon-only theme-select-button", id: `theme-btn-${theme.name}`, events: { click: () => this.handleThemeButtonClick(theme.name), mouseover: () => this.updateTooltip(theme.tip), mouseout: () => this.updateTooltip() } }); themeButtonsContainer.appendChild(themeButton); })); themeSection.appendChild(themeButtonsContainer); const personalThemeContainer = window.DOM.createElement("div", { id: "personal-theme-container", className: "personal-theme-container", style: "display: none;" }); const personalThemeHeader = window.DOM.createElement("div", { className: "personal-theme-header" }); personalThemeHeader.textContent = "Personal Theme Controls"; personalThemeContainer.appendChild(personalThemeHeader); const personalThemeControls = window.DOM.createElement("div", { className: "personal-theme-controls" }); const editColorsButton = window.DOM.createElement("button", { className: "eic-button edit-colors-button", textContent: "Edit Colors", events: { click: () => this.togglePersonalThemeEditor() } }); const resetButton = window.DOM.createElement("button", { className: "eic-button reset-theme-button", textContent: "Reset", events: { click: () => this.resetPersonalPalette() } }); personalThemeControls.appendChild(editColorsButton); personalThemeControls.appendChild(resetButton); personalThemeContainer.appendChild(personalThemeControls); themeSection.appendChild(personalThemeContainer); themesPanel.appendChild(themeSection); const tooltipArea = window.DOM.createElement("div", { id: "eic-tooltip-area", className: "eic-tooltip-area" }); window.State.popupElement.appendChild(tooltipArea); window.State.popupElement.appendChild(contentDiv); window.State.popupElement.appendChild(tooltipArea); this.createPersonalThemeEditorModal(); this.updateUIState(); return !0; }, createPersonalThemeEditorModal() { if (document.getElementById("eic-personal-theme-editor")) { return; } const editorModal = window.DOM.createElement("div", { id: "eic-personal-theme-editor", className: "eic-personal-theme-editor", style: "display:none; flex-direction:column;" }); const editorHeader = window.DOM.createElement("div", { className: "editor-header" }); editorHeader.appendChild(window.DOM.createElement("h3", { textContent: "Personal Theme Editor" })); const editorCloseBtn = window.DOM.createElement("button", { className: "eic-button eic-button-icon-only editor-close-btn", events: { click: () => this.togglePersonalThemeEditor() } }); window.Icons.inject(editorCloseBtn, "close"); editorHeader.appendChild(editorCloseBtn); editorModal.appendChild(editorHeader); const editorContent = window.DOM.createElement("div", { className: "editor-content" }); const palette = this._getComputedThemeVariables(); Object.keys(this._personalThemeVarLabels).forEach((varName => { if (!this._personalThemeVarLabels.hasOwnProperty(varName)) { return; } const value = palette[varName] || ""; const row = window.DOM.createElement("div", { className: "personal-theme-row" }); const labelText = this._personalThemeVarLabels[varName] || varName; const tooltipText = this._personalThemeVarTooltips[varName] || `CSS Variable: ${varName}`; const label = window.DOM.createElement("label", { textContent: labelText, htmlFor: `pte-input-${varName}`, title: tooltipText }); const inputContainer = window.DOM.createElement("div", { className: "color-input-container" }); const isColor = varName.includes("color") || value.startsWith("#") || value.startsWith("rgb"); if (isColor) { const colorPreview = window.DOM.createElement("div", { className: "color-preview", style: `background-color: ${value};`, "data-for": `pte-input-${varName}`, events: { click: e => document.getElementById(e.target.dataset.for)?.click() } }); inputContainer.appendChild(colorPreview); } const input = window.DOM.createElement("input", { id: `pte-input-${varName}`, className: "personal-theme-input", type: isColor ? "color" : "text", value: value, "data-varname": varName, events: { input: e => { if (isColor) { const preview = e.target.previousElementSibling; if (preview && preview.classList.contains("color-preview")) { preview.style.backgroundColor = e.target.value; } } } } }); inputContainer.appendChild(input); row.appendChild(label); row.appendChild(inputContainer); editorContent.appendChild(row); })); editorModal.appendChild(editorContent); const editorFooter = window.DOM.createElement("div", { className: "editor-footer" }); const cancelBtn = window.DOM.createElement("button", { id: "cancel-personal-theme-btn", className: "eic-button eic-button-secondary", events: { click: () => this.handleCancelPersonalThemeEdit() } }); window.Icons.inject(cancelBtn, "cancel", { addContainerClass: !1 }); cancelBtn.appendChild(document.createTextNode(" Cancel")); const saveBtn = window.DOM.createElement("button", { id: "save-personal-palette-btn", className: "eic-button eic-button-primary", events: { click: () => this.savePersonalPalette() } }); window.Icons.inject(saveBtn, "save", { addContainerClass: !1 }); saveBtn.appendChild(document.createTextNode(" Save")); editorFooter.appendChild(cancelBtn); editorFooter.appendChild(saveBtn); editorModal.appendChild(editorFooter); document.body.appendChild(editorModal); }, enterEditTitleMode(displayElement) { if (!displayElement || "INPUT" === displayElement.tagName) { return; } const currentText = displayElement.textContent; const headerDiv = displayElement.parentNode; const inputField = window.DOM.createElement("input", { type: "text", id: "popup-title-input", className: "popup-title popup-title-input", value: currentText, "data-original-value": currentText, events: { blur: e => this.exitEditTitleMode(e.target), keydown: e => { if ("Enter" === e.key) { e.target.blur(); } else if ("Escape" === e.key) { this.exitEditTitleMode(e.target, !1); } } } }); headerDiv.replaceChild(inputField, displayElement); inputField.focus(); inputField.select(); }, exitEditTitleMode(inputField, shouldSave = !0) { if (!inputField || "INPUT" !== inputField.tagName) { return; } const headerDiv = inputField.parentNode; let finalValue = inputField.getAttribute("data-original-value"); if (shouldSave) { const newValue = inputField.value.trim(); if (newValue && newValue !== finalValue) { window.Settings.update("headingText", newValue); finalValue = newValue; } } if (!finalValue) { finalValue = "Eye in the Cloud"; } const titleDisplay = window.DOM.createElement("div", { id: "popup-editable-title", className: "popup-title popup-editable-title", textContent: finalValue, title: "Click to edit title", tabindex: "0", events: { click: e => this.enterEditTitleMode(e.target), focus: e => this.enterEditTitleMode(e.target) } }); if (headerDiv && inputField.parentNode === headerDiv) { headerDiv.replaceChild(titleDisplay, inputField); } }, show() { if (!window.State.popupElement || !document.body.contains(window.State.popupElement)) { return; } this.updateUIState(); window.State.popupElement.classList.add("visible"); const activeTabButton = window.State.popupElement.querySelector(".eic-tab-button.active"); if (!activeTabButton) { const tabId = window.State.settings.popupActiveTab || this.activeTab; const defaultTabButton = window.State.popupElement.querySelector(`[data-tab-target="tab-content-${tabId}"]`); if (defaultTabButton) { this.handleTabClick({ currentTarget: defaultTabButton }); } } this._ensurePageOverlay(); if (window.State.pageOverlay) { window.State.pageOverlay.classList.add("visible"); } }, hide() { if (window.State.popupElement) { window.State.popupElement.classList.remove("visible"); } if (window.State.pageOverlay) { window.State.pageOverlay.classList.remove("visible"); } const pte = document.getElementById("eic-personal-theme-editor"); if (pte) { pte.style.display = "none"; } window.Settings.save(); }, toggle(event) { if (event) { event.stopPropagation(); } if (window.State.popupElement) { if (!window.State.popupElement.classList.contains("visible")) { this.show(); } else { this.hide(); } } }, toggleVibeMode() { window.State.isVibeModeActive = !window.State.isVibeModeActive; window.Settings.update("vibeModeActive", window.State.isVibeModeActive); window.EICButtonManager.update(); }, handleThemeButtonClick(themeName) { if (window.State.activeTheme === themeName) { window.ThemeManager.removeActiveTheme(); } else { window.ThemeManager.applyTheme(themeName); } }, updateUIState() { if (!window.State.popupElement) { return; } const vibeButton = document.getElementById("vibe-mode-toggle"); if (vibeButton) { if (window.State.isVibeModeActive) { vibeButton.classList.add("active"); vibeButton.removeAttribute("title"); } else { vibeButton.classList.remove("active"); vibeButton.removeAttribute("title"); } } window.HistoryManager.updateHistoryControlsState(); const hidePanel = document.getElementById("tab-content-hide"); if (hidePanel) { const toggles = hidePanel.querySelectorAll('input[type="checkbox"]'); toggles.forEach((toggle => { toggle.disabled = !!window.State.isVibeModeActive; toggle.parentElement.style.opacity = window.State.isVibeModeActive ? "0.5" : "1"; })); } const tabButtons = window.State.popupElement.querySelectorAll(".eic-tab-button"); const tabPanels = window.State.popupElement.querySelectorAll(".eic-tab-panel"); tabButtons.forEach((btn => { if (btn.dataset.tabTarget === `tab-content-${this.activeTab}`) { btn.classList.add("active"); } else { btn.classList.remove("active"); } })); tabPanels.forEach((panel => { if (panel.id === `tab-content-${this.activeTab}`) { panel.style.display = "block"; } else { panel.style.display = "none"; } })); this._updateThemeButtonsState(); this._updatePopupTitleAndIcons(); }, _updateThemeButtonsState() { const themeButtons = window.State.popupElement.querySelectorAll(".theme-select-button"); const personalThemeContainer = document.getElementById("personal-theme-container"); themeButtons.forEach((btn => { const themeName = btn.id.replace("theme-btn-", ""); const currentActiveTheme = window.State.activeTheme; window.State.activeTheme = themeName; const iconData = window.ThemeManager.getSvgIconData("Default"); window.State.activeTheme = currentActiveTheme; if (iconData && "function" == typeof window.Icons?.createSvgElement) { for (;btn.firstChild && !(btn.firstChild instanceof Text); ) { btn.removeChild(btn.firstChild); } const svgIcon = window.Icons.createSvgElement(iconData); if (btn.firstChild && btn.firstChild instanceof Text) { btn.insertBefore(svgIcon, btn.firstChild); } else { btn.appendChild(svgIcon); } } if (themeName === window.State.settings.activeTheme) { btn.classList.add("active"); } else { btn.classList.remove("active"); } })); if (personalThemeContainer) { personalThemeContainer.style.display = "personal" === window.State.settings.activeTheme ? "block" : "none"; } }, _updatePopupTitleAndIcons() { const titleDisplay = document.getElementById("popup-editable-title"); if (titleDisplay && titleDisplay.textContent !== window.State.settings.headingText) { titleDisplay.textContent = window.State.settings.headingText || "Eye in the Cloud"; } if (window.State.aiThemeStudioButton) { const eyeButtonIconSlot = window.State.aiThemeStudioButton.querySelector(".eic-button-icon-svg-slot"); if (eyeButtonIconSlot) { const eyeIconData = window.ThemeManager.getSvgIconData("Default"); if (eyeIconData) { for (;eyeButtonIconSlot.firstChild; ) { eyeButtonIconSlot.removeChild(eyeButtonIconSlot.firstChild); } const eyeIconSvg = window.Icons.createSvgElement(eyeIconData); eyeButtonIconSlot.appendChild(eyeIconSvg); } } } }, handleTabClick(event) { const targetButton = event.currentTarget; const targetPanelId = targetButton.getAttribute("data-tab-target"); const isCurrentlyActive = targetButton.classList.contains("active"); if (isCurrentlyActive) { targetButton.classList.remove("active"); const targetPanel = document.getElementById(targetPanelId); if (targetPanel) { targetPanel.style.display = "none"; targetPanel.classList.remove("active-panel"); } return; } if ("tab-content-history" === targetPanelId) {} const tabButtons = window.State.popupElement.querySelectorAll(".eic-tab-button"); tabButtons.forEach((btn => btn.classList.remove("active"))); targetButton.classList.add("active"); const tabPanels = window.State.popupElement.querySelectorAll(".eic-tab-panel"); tabPanels.forEach((panel => { panel.style.display = "none"; panel.classList.remove("active-panel"); })); const targetPanel = document.getElementById(targetPanelId); if (targetPanel) { targetPanel.style.display = "block"; targetPanel.classList.add("active-panel"); if ("tab-content-snippets" === targetPanelId) { if (window.Snippets && window.Snippets.createSnippetsPanel) { window.Snippets.createSnippetsPanel(); } } } try { const storeValue = isCurrentlyActive ? "default" : targetPanelId.replace("tab-content-", ""); window.Settings.update("popupActiveTab", storeValue); } catch (e) {} this.activeTab = isCurrentlyActive ? "default" : targetPanelId.replace("tab-content-", ""); this.updateUIState(); }, showAiThemeInputModal() { if (window.ModalEye && "function" == typeof window.ModalEye.open) { window.ModalEye.open(); } }, updateTooltip(message) { const tooltipArea = document.getElementById("eic-tooltip-area"); if (tooltipArea) { if ("string" == typeof message && message.trim()) { tooltipArea.textContent = message; } else { tooltipArea.textContent = "Hover over an item for details."; } } }, _getComputedThemeVariables() { const computedVariables = {}; Object.keys(this._personalThemeVarLabels).forEach((varName => { if (varName.startsWith("--eic-global-")) { const value = getComputedStyle(document.body).getPropertyValue(varName).trim(); if (value) { computedVariables[varName] = value; } } })); return computedVariables; } }; document.addEventListener("DOMContentLoaded", (() => {})); window.EyeBot = { init() { document.addEventListener("eic:geminiThemeDataReceived", (event => { if (event.detail && event.detail.rawText) { this.processReceivedThemeData(event.detail.rawText); } })); }, submitPreparedPromptToAI: function(promptString) { const realInput = document.querySelector(window.Config.selectors.chatInput); const realRunButton = document.querySelector(window.Config.selectors.runButton); if (realInput && realRunButton) { const aiSelector = window.Config.selectors.aiTurn; const currentAiTurns = document.querySelectorAll(aiSelector); window.State.waitingForThemeAiTurnAfter = currentAiTurns.length; realInput.value = promptString; realInput.dispatchEvent(new Event("input", { bubbles: !0, cancelable: !0 })); realInput.dispatchEvent(new Event("change", { bubbles: !0, cancelable: !0 })); setTimeout((() => { realRunButton.click(); if (window.ModalEye && window.ModalEye.setState) { window.ModalEye.setState("processing"); } window.NotificationManager.showNotification("Your request has been sent to the Eye...", 3e3); }), 150); } }, processReceivedThemeData(rawText) { window.NotificationManager.showNotification("The Eye is looking for a theme pattern...", 3e3); let processedText = rawText.trim(); try { const parsedJson = JSON.parse(processedText); this.processAndStoreGeneratedTheme(parsedJson); this.cleanupAiTurns(); } catch (e) { this.cleanupAiTurns(); window.State.aiThemeModalConfirmationText = "The Eye gazed into the void, but found only chaos. Nothing has been applied."; window.ModalEye.processingComplete(); } }, processAndStoreGeneratedTheme(generatedData) { const {colorPalette: colorPalette, svgDefault: svgDefault, svgHover: svgHover, svgActive: svgActive, confirmationMessage: confirmationMessage} = generatedData; const themeColors = {}; for (const [key, value] of Object.entries(colorPalette || {})) { if (key.startsWith("--eic-global-") && "string" == typeof value && value.trim().length > 0) { themeColors[key] = value.trim(); } } const finalSvgDefault = null === svgDefault || this.isValidSvgData(svgDefault) ? svgDefault : null; const finalSvgHover = null === svgHover || this.isValidSvgData(svgHover) ? svgHover : null; const finalSvgActive = null === svgActive || this.isValidSvgData(svgActive) ? svgActive : null; const finalConfirmationMessage = "string" == typeof confirmationMessage ? confirmationMessage : "Theme processed by The Eye!"; window.State.settings.customProfileAssets.colorPalette = themeColors; window.State.settings.customProfileAssets.svgDefault = finalSvgDefault; window.State.settings.customProfileAssets.svgHover = finalSvgHover; window.State.settings.customProfileAssets.svgActive = finalSvgActive; window.Settings.update("customProfileAssets", window.State.settings.customProfileAssets); window.Settings.update("isCustomProfileActive", !0); window.ThemeManager.applyTheme("personal"); window.State.aiThemeModalConfirmationText = finalConfirmationMessage; window.ModalEye.processingComplete(); }, isValidSvgData: svgData => svgData && "object" == typeof svgData && "0 0 24 24" === svgData.viewBox && Array.isArray(svgData.elements), resetPersonalThemeToDefaults() { window.Settings.resetToDefaults(); window.ThemeManager.applyTheme("personal"); window.NotificationManager.showNotification("Personal theme reset to factory defaults.", 3e3); }, cleanupAiTurns() { window.NotificationManager.showNotification("Starting cleanup of the received code...", 3e3); const turnsGeneratedByThemeBot = null !== window.State.waitingForThemeAiTurnAfter ? (() => { const aiSelector = window.Config.selectors.aiTurn; const aiTurns = document.querySelectorAll(aiSelector); const currentCount = aiTurns.length; const startIdx = window.State.waitingForThemeAiTurnAfter; return "number" == typeof startIdx && startIdx >= 0 && currentCount > startIdx ? currentCount - startIdx : 0; })() : 0; if (turnsGeneratedByThemeBot > 0) { this.deleteLastAiTurns(turnsGeneratedByThemeBot); } window.State.waitingForThemeAiTurnAfter = null; }, async deleteLastAiTurns(countToDelete) { try { const chatContainer = document.querySelector(window.Config.selectors.chatContainer); const aiTurns = Array.from(chatContainer.querySelectorAll(window.Config.selectors.aiTurn)); const turnsToDelete = aiTurns.slice(-countToDelete); for (const turnElement of turnsToDelete.reverse()) { await this.deleteSingleTurn(turnElement); } const userTurn = chatContainer.querySelector(".user"); if (userTurn) { await this.deleteSingleTurn(userTurn); } window.NotificationManager.showNotification("Cleanup complete. The Eye has processed your request.", 3e3); } catch (err) {} }, async deleteSingleTurn(turnElement) { const moreBtn = turnElement.querySelector(window.Config.selectors.aiTurnMoreOptionsButton); moreBtn.click(); await new Promise((resolve => setTimeout(resolve, 350))); const menuItems = Array.from(document.querySelectorAll(window.Config.selectors.aiTurnContextMenuItems)); let deleteBtn = null; for (const item of menuItems) { const itemText = item.textContent?.toLowerCase() || ""; const iconText = item.querySelector(".material-symbols-outlined, .material-icons")?.textContent?.toLowerCase() || ""; if (itemText.includes(window.Config.textStrings.deleteActionMenuItemText) || iconText.includes(window.Config.textStrings.deleteActionMenuItemText)) { deleteBtn = item; break; } } deleteBtn.click(); await new Promise((resolve => setTimeout(resolve, 700))); } }; window.EICButtonManager = { scriptToggleButton: null, currentMainButtonState: "default", hitboxElement: null, updateHitboxPositionCallback: null, aiThemeStudioButton: null, create() { if (!this.scriptToggleButton || !document.body.contains(this.scriptToggleButton)) { this.scriptToggleButton = window.DOM.createElement("button", { id: window.Config.ids.scriptButton, title: "Eye in the Cloud Controls", className: "eic-button eic-button-icon-only" }); document.body.appendChild(this.scriptToggleButton); this.createOrUpdateHitbox(); this.positionButton(); this.updateMainButtonVisual(); } }, createOrUpdateHitbox() { if (this.scriptToggleButton) { if (!this.hitboxElement) { this.hitboxElement = document.createElement("div"); this.hitboxElement.id = "eic-main-button-hitbox"; this.hitboxElement.addEventListener("click", (e => { e.preventDefault(); e.stopPropagation(); window.Popup.toggle(e); })); this.hitboxElement.addEventListener("mouseover", (() => { if ("active" !== this.currentMainButtonState || !window.State.isVibeModeActive) { this.currentMainButtonState = "hover"; this.updateMainButtonVisual(); } })); this.hitboxElement.addEventListener("mouseout", (() => { this.currentMainButtonState = window.State.isVibeModeActive ? "active" : "default"; this.updateMainButtonVisual(); })); document.body.appendChild(this.hitboxElement); } this.updateHitboxPositionCallback = () => { if (!this.scriptToggleButton || !this.hitboxElement || !document.body.contains(this.hitboxElement)) { return; } const rect = this.scriptToggleButton.getBoundingClientRect(); const padding = 0; Object.assign(this.hitboxElement.style, { position: "fixed", top: `${rect.top - padding}px`, left: `${rect.left - padding}px`, width: `${rect.width + 2 * padding}px`, height: `${rect.height + 2 * padding}px`, zIndex: "10002", cursor: "pointer", pointerEvents: "auto" }); }; this.updateHitboxPositionCallback(); } }, updateMainButtonVisual() { if (!this.scriptToggleButton) { this.scriptToggleButton = document.getElementById(window.Config.ids.scriptButton); if (!this.scriptToggleButton) { return; } } let svgStateToFetch = "Default"; if (window.State.isVibeModeActive) { svgStateToFetch = "Active"; } else { svgStateToFetch = "active" === this.currentMainButtonState ? "Active" : "hover" === this.currentMainButtonState ? "Hover" : "Default"; } if (![ "Default", "Hover", "Active" ].includes(svgStateToFetch) && !window.State.isVibeModeActive) { svgStateToFetch = "Default"; } let elementToRender = null; const themeSvgData = window.ThemeManager.getSvgIconData(svgStateToFetch); if (themeSvgData) { const createdElement = window.Icons.createSvgElement(themeSvgData); if (createdElement) { elementToRender = createdElement; } } if (!elementToRender) { let fallbackSvgData = null; if (window.Icons && window.Icons.defaults) { if (window.Icons.defaults.buttonStates && window.Icons.defaults.buttonStates[svgStateToFetch]) { fallbackSvgData = window.Icons.defaults.buttonStates[svgStateToFetch]; } else if (window.Icons.defaults.eyeInTheCloudDefault) { fallbackSvgData = window.Icons.defaults.eyeInTheCloudDefault; } } if (fallbackSvgData) { const fallbackElement = window.Icons.createSvgElement(fallbackSvgData); if (fallbackElement) { elementToRender = fallbackElement; } } } if (elementToRender) { this._applySvgToButton(this.scriptToggleButton, elementToRender); } else { this._clearButtonIcon(this.scriptToggleButton); } }, updateAiThemeStudioButtonVisual() { if (!this.aiThemeStudioButton) { this.aiThemeStudioButton = document.getElementById(window.Config.ids.aiThemeStudioButton); if (!this.aiThemeStudioButton) { return; } } const svgData = window.ThemeManager.getSvgIconData("Default"); if (svgData) { const svgElementToApply = window.Icons.createSvgElement(svgData); if (svgElementToApply) { let iconSlot = this.aiThemeStudioButton.querySelector(".eic-button-icon-svg-slot"); if (!iconSlot) { iconSlot = document.createElement("span"); iconSlot.className = "eic-button-icon-svg-slot"; this.aiThemeStudioButton.insertBefore(iconSlot, this.aiThemeStudioButton.firstChild); } for (;iconSlot.firstChild; ) { iconSlot.removeChild(iconSlot.firstChild); } svgElementToApply.classList.add("eic-button-icon-svg"); iconSlot.appendChild(svgElementToApply); } } }, update() { if (!this.scriptToggleButton) { this.scriptToggleButton = document.getElementById(window.Config.ids.scriptButton); if (!this.scriptToggleButton) { return; } } this._updateButtonVisuals(); this._updateButtonPosition(); }, _clearButtonIcon(buttonElement) { if (!buttonElement) { return; } const childrenSnapshot = Array.from(buttonElement.childNodes); childrenSnapshot.forEach((child => { buttonElement.removeChild(child); })); }, _updateButtonVisuals() { this.updateMainButtonVisual(); this.updateAiThemeStudioButtonVisual(); }, _updateButtonPosition() { const vibeStateString = String(window.State.isVibeModeActive); if (this.scriptToggleButton.dataset.lastVibeState !== vibeStateString) { this.positionButton(); this.scriptToggleButton.dataset.lastVibeState = vibeStateString; } }, _applySvgToButton(buttonElement, svgElement) { const childrenSnapshot = Array.from(buttonElement.childNodes); if (childrenSnapshot.length > 0) { childrenSnapshot.forEach((child => { buttonElement.removeChild(child); })); } buttonElement.appendChild(svgElement); }, positionButton() { if (this.scriptToggleButton) { this.scriptToggleButton.style.setProperty("position", "fixed", "important"); this.scriptToggleButton.style.top = "2%"; this.scriptToggleButton.style.left = "50%"; this.scriptToggleButton.style.transform = "translateX(-50%)"; this.updateHitboxPositionCallback(); } }, destroy() { if (this.scriptToggleButton && document.body.contains(this.scriptToggleButton)) { document.body.removeChild(this.scriptToggleButton); } if (this.hitboxElement && document.body.contains(this.hitboxElement)) { document.body.removeChild(this.hitboxElement); } this.scriptToggleButton = null; this.hitboxElement = null; } }; window.ElementWatcher = { observer: null, debounceTimer: null, _hasStarted: !1, uiUpdateFunctions: { layout: () => window.UI?.applyLayoutRules(), heading: () => window.UI?.updateHeadingText(), promptChips: () => window.UI?.updatePromptChipsVisibility(), turnFooters: () => window.UI?.updateTurnFooterVisibility(), placeholder: () => window.UI?.updateInputPlaceholder() }, logClipboardContent: content => content, attemptClipboardCopyAndRead(button) { return new Promise(((resolve, reject) => { try { button.click(); setTimeout((() => { navigator.clipboard.readText().then((text => { resolve(this.logClipboardContent(text)); })).catch((err => { reject(err); })); }), 100); } catch (err) { reject(err); } })); }, processPotentialThemeTurn(turnElement) { if (!turnElement) { return; } const codeBlocks = turnElement.querySelectorAll("pre > code"); if (codeBlocks && 0 !== codeBlocks.length) { codeBlocks.forEach((async (codeBlock, index) => { try { const preElement = codeBlock.closest("pre"); if (!preElement) { return; } const copyButton = preElement.querySelector('button[aria-label="Copy code"], button.copy-button'); if (!copyButton) { return; } this.attemptClipboardCopyAndRead(copyButton).then((clipboardContent => { if (clipboardContent.includes(".dark-theme") || clipboardContent.includes(":root") || clipboardContent.includes("--background") || clipboardContent.includes("@media")) { const themeEvent = new CustomEvent("eic-theme-generated", { detail: { content: clipboardContent } }); document.dispatchEvent(themeEvent); window.Popup?.showNotification("Theme CSS detected! Processing...", 3e3); } })).catch((err => {})); } catch (error) {} })); } }, processAiTurnForThemeData(aiTurnElement) { const codeBlocks = aiTurnElement.querySelectorAll(window.Config.selectors.aiTurnCodeBlock); if (0 === codeBlocks.length) { return; } const lastCodeBlock = codeBlocks[codeBlocks.length - 1]; let codeContent = lastCodeBlock.textContent || ""; const mightBeThemeData = codeContent.includes("--eic-") || codeContent.includes(":root") || codeContent.includes(".dark-theme") || codeContent.startsWith("{") && codeContent.includes(":") || codeContent.includes('"') && codeContent.includes("}") || codeContent.includes("svgDefault") || codeContent.includes("svgHover") || codeContent.includes("svgActive"); if (!mightBeThemeData) { return; } const themeDataEvent = new CustomEvent("eic:geminiThemeDataReceived", { detail: { rawText: codeContent } }); document.dispatchEvent(themeDataEvent); }, handleDomChange(mutations = []) { if (!window.State || !window.Config?.selectors?.aiTurn) { return; } if (null !== window.State.waitingForThemeAiTurnAfter) { const aiSelector = window.Config.selectors.aiTurn; const currentAiTurns = document.querySelectorAll(aiSelector); const currentCount = currentAiTurns.length; const startIdx = window.State.waitingForThemeAiTurnAfter; const runBtn = document.querySelector(window.Config.selectors.runButton); const isLoading = runBtn && ("stop" === runBtn.textContent.trim().toLowerCase() || runBtn.className.includes("stoppable")); if (isLoading) { return; } if (currentCount <= startIdx) { return; } const newTurns = []; for (let i = startIdx; i < currentCount; i++) { newTurns.push(currentAiTurns[i]); } for (const turn of newTurns) { if (!turn) { continue; } const codeBlocks = turn.querySelectorAll(window.Config.selectors.aiTurnCodeBlock); if (codeBlocks.length > 0) { this.processAiTurnForThemeData(turn); } } window.State.waitingForThemeAiTurnAfter = null; } window.promptcomposer.init(); try { const triggerButton = document.getElementById("adv-modal-trigger-btn"); if (triggerButton) { triggerButton.classList.add("eic-visible"); triggerButton.classList.remove("eic-hidden-by-default"); const buttonWrapper = triggerButton.closest(".button-wrapper"); const parentContainer = buttonWrapper?.parentElement; if (buttonWrapper && parentContainer && parentContainer.children[0] !== buttonWrapper) { parentContainer.insertBefore(buttonWrapper, parentContainer.firstChild); } } else { window.promptcomposer.init(); } } catch (error) {} window.UI.applyLayoutRules(); window.UI.updateHeadingText(); window.UI.updatePromptChipsVisibility(); window.UI.updateTurnFooterVisibility(); window.UI.updateInputPlaceholder(); window.HistoryManager.applyVisibilityRules(); if (window.State.popupElement?.classList.contains("visible")) { try { const chatContainerForSlider = document.querySelector(window.Config.selectors.chatContainer); if (chatContainerForSlider) { const aiTurns = chatContainerForSlider.querySelectorAll(window.Config.selectors.aiTurn); const maxExchanges = aiTurns.length > 0 ? aiTurns.length : 1; window.HistoryManager.updateSliderMax(maxExchanges); } } catch (error) {} } try { const disclaimerSpan = document.querySelector(window.Config.selectors.siteDisclaimerText); if (disclaimerSpan) { const newDisclaimerText = "This reality is for testing only. No production use."; if (disclaimerSpan.textContent.trim() !== newDisclaimerText) { disclaimerSpan.textContent = newDisclaimerText; } } } catch (error) {} }, start() { if (!window.__EIC_WATCHER_STARTED) { window.__EIC_WATCHER_STARTED = !0; if (!this._hasStarted) { this._hasStarted = !0; this.observer = new MutationObserver((mutations => { clearTimeout(this.debounceTimer); this.debounceTimer = setTimeout((() => { this.handleDomChange(mutations); }), 250); })); this.observer.observe(document.body, { childList: !0, subtree: !0 }); this.handleDomChange([]); } } }, stop() { if (this.observer) { this.observer.disconnect(); this.observer = null; } if (this.debounceTimer) { clearTimeout(this.debounceTimer); this.debounceTimer = null; } this._hasStarted = !1; } }; window.Snippets = { init() { this.createSnippetsPanel(); document.addEventListener("eic-snippets-updated", (() => { this.renderSnippetList(); })); }, createSnippetsPanel() { const tabContentSnippetsPanel = document.getElementById("tab-content-snippets"); if (!tabContentSnippetsPanel) { return; } for (;tabContentSnippetsPanel.firstChild; ) { tabContentSnippetsPanel.removeChild(tabContentSnippetsPanel.firstChild); } const toggleContainer = window.DOM.createToggle("show-snippet-toolbar-toggle", "Show Snippet Toolbar in Prompt Composer", window.State.settings.showSnippetToolbarInModal, (checked => { window.Settings.update("showSnippetToolbarInModal", checked); })); const toggleInput = toggleContainer.querySelector('input[type="checkbox"]'); if (toggleInput) { toggleInput.checked = !!window.State.settings.showSnippetToolbarInModal; } toggleContainer.addEventListener("mouseover", (() => window.Popup.updateTooltip("Control visibility of snippet toolbar in the Prompt Composer modal"))); toggleContainer.addEventListener("mouseout", (() => window.Popup.updateTooltip())); tabContentSnippetsPanel.appendChild(toggleContainer); const snippetsContainer = window.DOM.createElement("div", { className: "snippet-list-area", id: "snippet-list-area" }); tabContentSnippetsPanel.appendChild(snippetsContainer); const addSnippetButton = window.DOM.createElement("button", { className: "add-snippet-btn", textContent: "+ Add Snippet", events: { click: () => this.openSnippetForm(), mouseover: () => window.Popup.updateTooltip("Create a new reusable snippet"), mouseout: () => window.Popup.updateTooltip() } }); tabContentSnippetsPanel.appendChild(addSnippetButton); this.renderSnippetList(); }, renderSnippetList() { const snippetList = document.getElementById("snippet-list-area"); if (!snippetList) { return; } for (;snippetList.firstChild; ) { snippetList.removeChild(snippetList.firstChild); } const snippets = window.State.settings.promptSnippets || []; if (0 !== snippets.length) { snippets.forEach(((snippet, index) => { const snippetItem = this.createSnippetListItem(snippet, index); snippetList.appendChild(snippetItem); })); } else { const emptyMessage = window.DOM.createElement("div", { style: "padding: 20px; text-align: center; color: var(--eic-global-on-surface-variant);", textContent: "No snippets yet. Add your first one!" }); snippetList.appendChild(emptyMessage); } }, createSnippetListItem(snippet, index) { const item = window.DOM.createElement("div", { className: "snippet-list-item", events: { mouseover: () => window.Popup.updateTooltip(snippet.content), mouseout: () => window.Popup.updateTooltip() } }); const snippetName = window.DOM.createElement("div", { className: "snippet-name", textContent: snippet.name }); const actionButtons = window.DOM.createElement("div", { className: "snippet-actions" }); const editButton = window.DOM.createElement("button", { className: "snippet-action-btn", events: { click: () => this.openSnippetForm(snippet, index), mouseover: () => window.Popup?.updateTooltip?.("Edit this snippet"), mouseout: () => window.Popup?.updateTooltip?.() } }); window.Icons.inject(editButton, { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z", fill: "currentColor" } } ] }); const deleteButton = window.DOM.createElement("button", { className: "snippet-action-btn", events: { click: () => this.deleteSnippet(index), mouseover: () => window.Popup?.updateTooltip?.("Delete this snippet"), mouseout: () => window.Popup?.updateTooltip?.() } }); window.Icons.inject(deleteButton, { viewBox: "0 0 24 24", elements: [ { type: "path", attrs: { d: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z", fill: "currentColor" } } ] }); const moveUpButton = window.DOM.createElement("button", { className: "snippet-action-btn", events: { click: () => this.moveSnippet(index, index - 1), mouseover: () => window.Popup?.updateTooltip?.("Move this snippet up"), mouseout: () => window.Popup?.updateTooltip?.() } }); window.Icons.inject(moveUpButton, "arrow_upward"); if (0 === index) { moveUpButton.disabled = !0; moveUpButton.style.opacity = "0.5"; } const moveDownButton = window.DOM.createElement("button", { className: "snippet-action-btn", events: { click: () => this.moveSnippet(index, index + 1), mouseover: () => window.Popup?.updateTooltip?.("Move this snippet down"), mouseout: () => window.Popup?.updateTooltip?.() } }); window.Icons.inject(moveDownButton, "arrow_downward"); const snippets = window.State.settings.promptSnippets || []; if (index === snippets.length - 1) { moveDownButton.disabled = !0; moveDownButton.style.opacity = "0.5"; } actionButtons.appendChild(moveUpButton); actionButtons.appendChild(moveDownButton); actionButtons.appendChild(editButton); actionButtons.appendChild(deleteButton); item.appendChild(snippetName); item.appendChild(actionButtons); return item; }, moveSnippet(fromIndex, toIndex) { const snippets = window.State.settings.promptSnippets || []; if (toIndex < 0 || toIndex >= snippets.length) { return; } const snippet = snippets[fromIndex]; snippets.splice(fromIndex, 1); snippets.splice(toIndex, 0, snippet); window.Settings.update("promptSnippets", [ ...snippets ]); this.renderSnippetList(); }, deleteSnippet(index) { if (!confirm("Are you sure you want to delete this snippet?")) { return; } const snippets = window.State.settings.promptSnippets || []; snippets.splice(index, 1); window.Settings.update("promptSnippets", [ ...snippets ]); this.renderSnippetList(); window.NotificationManager.showNotification("Snippet deleted"); }, openSnippetForm(snippet = null, index = null) { const existingForm = document.getElementById("snippet-form-container"); if (existingForm) { existingForm.remove(); } const isEdit = null !== snippet; const formContainer = window.DOM.createElement("div", { id: "snippet-form-container", style: "position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10002;" }); const form = window.DOM.createElement("form", { className: "snippet-form", id: "snippet-form", events: { submit: e => { e.preventDefault(); this.saveSnippet(isEdit, index); } } }); const nameField = window.DOM.createElement("div", { className: "snippet-form-field" }); const nameLabel = window.DOM.createElement("label", { htmlFor: "snippet-name-input", textContent: "Snippet Name" }); const nameInput = window.DOM.createElement("input", { id: "snippet-name-input", type: "text", value: isEdit ? snippet.name : "", required: "required", placeholder: "Enter a name for this snippet" }); nameField.appendChild(nameLabel); nameField.appendChild(nameInput); const contentField = window.DOM.createElement("div", { className: "snippet-form-field" }); const contentLabel = window.DOM.createElement("label", { htmlFor: "snippet-content-input", textContent: "Snippet Content" }); const contentInput = window.DOM.createElement("textarea", { id: "snippet-content-input", required: "required", placeholder: "Enter the content of your snippet", value: isEdit ? snippet.content : "" }); contentField.appendChild(contentLabel); contentField.appendChild(contentInput); const buttons = window.DOM.createElement("div", { className: "snippet-form-buttons" }); const cancelButton = window.DOM.createElement("button", { type: "button", textContent: "Cancel", className: "clear-textarea-btn", events: { click: () => formContainer.remove() } }); const saveButton = window.DOM.createElement("button", { type: "submit", textContent: isEdit ? "Save Changes" : "Save Snippet", style: "background-color: var(--eic-global-primary); color: var(--eic-global-on-primary);" }); buttons.appendChild(cancelButton); buttons.appendChild(saveButton); form.appendChild(nameField); form.appendChild(contentField); form.appendChild(buttons); formContainer.appendChild(form); document.body.appendChild(formContainer); nameInput.focus(); const outsideClickHandler = e => { if (!form.contains(e.target) && document.body.contains(formContainer)) { formContainer.remove(); document.removeEventListener("click", outsideClickHandler); } }; setTimeout((() => { document.addEventListener("click", outsideClickHandler); }), 100); }, saveSnippet(isEdit, index) { const nameInput = document.getElementById("snippet-name-input"); const contentInput = document.getElementById("snippet-content-input"); if (!nameInput || !contentInput) { return; } const name = nameInput.value.trim(); const content = contentInput.value.trim(); if (!name || !content) { return; } const snippets = window.State.settings.promptSnippets || []; if (isEdit) { snippets[index] = { id: snippets[index].id, name: name, content: content }; } else { const id = Date.now().toString(36) + Math.random().toString(36).substr(2, 5); snippets.push({ id: id, name: name, content: content }); } window.Settings.update("promptSnippets", [ ...snippets ]); const formContainer = document.getElementById("snippet-form-container"); if (formContainer) { formContainer.remove(); } this.renderSnippetList(); window.NotificationManager.showNotification(isEdit ? "Snippet updated" : "Snippet added"); }, createSnippetButton(snippet) { return window.DOM.createElement("button", { className: "eic-button eic-button-icon-only snippet-button", textContent: snippet.label, events: { click: () => { this.insertSnippet(snippet); }, mouseover: () => window.Popup?.updateTooltip?.(`Insert snippet: ${snippet.label}`), mouseout: () => window.Popup?.updateTooltip?.() } }); }, createSnippetInput() { return window.DOM.createElement("input", { className: "eic-input snippet-input", type: "text", placeholder: "Enter snippet text...", events: { input: event => { this.handleSnippetInput(event.target.value); } } }); } }; window.Snippets.initialize = function() { window.Snippets.init(); window.State.settings.promptSnippets; }; window.PromptTemplates = {}; !function(PT) { try { const rawJsonString = GM_getResourceText("PROMPT_TEMPLATES"); if ("string" != typeof rawJsonString || "" === rawJsonString.trim()) { return; } const templates = JSON.parse(rawJsonString); function buildFinalPrompt(masterTemplateArray, taskInstructionsArray, userTriggerInput) { const masterTemplateString = masterTemplateArray.join("\n"); const taskInstructionsString = taskInstructionsArray.join("\n"); let finalPrompt = masterTemplateString.replace("{{SPECIFIC_ANALYSIS_AND_CONCEPTUALIZATION_TASK}}", taskInstructionsString); finalPrompt = finalPrompt.replace(/\{\{USER_TRIGGER_INPUT\}\}/g, userTriggerInput); return finalPrompt; } PT.buildUserThemePrompt = function(userThemeDescription) { return buildFinalPrompt(templates.master_theme_prompt_template, templates.user_theme_task, userThemeDescription); }; PT.buildEyeThemePrompt = function(triggerCommand) { return buildFinalPrompt(templates.master_theme_prompt_template, templates.eye_theme_task, triggerCommand); }; PT.buildIThemePrompt = function(triggerCommand) { return buildFinalPrompt(templates.master_theme_prompt_template, templates.i_theme_task, triggerCommand); }; } catch (e) { return; } }(window.PromptTemplates); window.EyeCommands = { resetSettingsToDefault: async function() { await window.Settings.resetToDefaults(); }, processInputAndExecute: async function(rawUserInput) { let finalPromptString = null; try { const commandInput = rawUserInput.trim().toLowerCase(); const fullInputText = rawUserInput.trim(); if ("/reset" === commandInput) { await this.resetSettingsToDefault(); window.State.aiThemeModalConfirmationText = "All settings have been reset to defaults."; window.ModalEye.processingComplete(); } else if ("/eye" === commandInput) { window.commandType = "/eye command"; finalPromptString = window.PromptTemplates.buildEyeThemePrompt(fullInputText); window.EyeBot.submitPreparedPromptToAI(finalPromptString); } else if ("/i" === commandInput) { window.commandType = "/i command"; finalPromptString = window.PromptTemplates.buildIThemePrompt(fullInputText); window.EyeBot.submitPreparedPromptToAI(finalPromptString); } else { window.commandType = "theme_description"; finalPromptString = window.PromptTemplates.buildUserThemePrompt(rawUserInput); window.EyeBot.submitPreparedPromptToAI(finalPromptString); } } catch (error) { window.State.aiThemeModalConfirmationText = `Error processing command: ${error.message}`; window.ModalEye.processingComplete(); } } }; window.App = { async init() { await window.Settings.load(); if (window.State.settings.vibeModeActive) { window.State.isVibeModeActive = !0; } const injectCss = (resourceName, styleId) => { const cssText = GM_getResourceText(resourceName); const styleEl = GM_addStyle(cssText); if (styleId) { styleEl.id = styleId; } if (styleId) { styleEl.disabled = !0; } }; GM_addStyle(GM_getResourceText("MAIN_CSS")); GM_addStyle(GM_getResourceText("POPUP_CSS")); GM_addStyle(GM_getResourceText("SNIPPETS_CSS")); GM_addStyle(GM_getResourceText("EYE_MODAL_CSS")); GM_addStyle(GM_getResourceText("PROMPT_COMPOSER_CSS")); GM_addStyle(GM_getResourceText("GOOGLE_OVERRIDES_CSS")); GM_addStyle(GM_getResourceText("THEME_TEMPLATE_CSS")); injectCss("PERSONAL_THEME_CSS", "eic-theme-personal-css"); injectCss("DOS_THEME_CSS", "eic-theme-dos-css"); injectCss("NATURE_THEME_CSS", "eic-theme-nature-css"); window.Styles.addCoreStyles(); window.UI.init(); window.Popup.create(); GM_registerMenuCommand("Adv. Control Settings (AI Studio)", window.Popup.toggle); window.ThemeManager.loadThemes(); window.ModalEye._init(); window.ThemeManager.applyTheme(window.State.settings.activeTheme); window.EICButtonManager.create(); window.EyeBot.init(); window.Snippets.initialize(); window.ElementWatcher.start(); window.HistoryManager.initialize(); window.HistoryManager.applyVisibilityRules(); window.UI.applyLayoutRules(); }, initializeProgressively() { const layoutContainer = document.querySelector(window.Config.selectors.overallLayout); if (layoutContainer && !layoutContainer.dataset.eicLayoutRulesApplied) { window.UI.applyLayoutRules(); layoutContainer.dataset.eicLayoutRulesApplied = "true"; } } }; if ("complete" === document.readyState || "interactive" === document.readyState) { window.App.init(); } else { document.addEventListener("DOMContentLoaded", (() => window.App.init())); } }();