您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
当 AI Studio 页面加载时,自动关闭设置面板以节省页面空间。顺带一提,这个脚本是 Gemini 在 AI Studio 中编写的。
// ==UserScript== // @name Automatically Close Google AI Studio Settings Panel // @name:zh-CN 自动关闭 Google AI Studio 设置面板 // @namespace Violentmonkey Scripts // @match https://aistudio.google.com/* // @grant GM_addStyle // @run-at document-start // @version 1.1.20250413 // @author plasma-green & Gemini 2.5 Pro Preview 03-25 // @description When the AI Studio page loads, the settings panel is automatically closed to save page space. By the way, this script was written by Gemini in AI Studio. // @description:zh-CN 当 AI Studio 页面加载时,自动关闭设置面板以节省页面空间。顺带一提,这个脚本是 Gemini 在 AI Studio 中编写的。 // @license AGPL-3.0 // ==/UserScript== (function() { 'use strict'; // --- 配置 --- const buttonSelector = 'button[aria-label="Close run settings panel"]'; // 目标按钮的选择器 const logPrefix = '[AutoClick RunSettings] '; // 日志前缀,方便调试 const clickDelay = 1200; // 延迟时间 (毫秒),2000ms = 2秒 console.log(logPrefix + '脚本启动,开始监控按钮: ' + buttonSelector + ',延迟 ' + (clickDelay / 1000) + ' 秒'); // 使用 WeakMap 来跟踪哪些按钮已经有待处理的点击计时器 // WeakMap 的好处是当按钮元素从 DOM 中移除并被垃圾回收时,对应的条目也会自动移除,避免内存泄漏。 const pendingClickTimeouts = new WeakMap(); // --- 实际执行点击操作的函数 --- function performActualClick(button) { try { console.log(logPrefix + '执行点击...'); // 尝试 dispatchEvent (无 view) const event = new MouseEvent('click', { bubbles: true, cancelable: true }); if (button.dispatchEvent(event)) { console.log(logPrefix + 'dispatchEvent(click) 成功。'); return true; } else { console.log(logPrefix + 'dispatchEvent(click) 执行但可能被取消。'); return true; // 认为已尝试 } } catch (dispatchError) { console.warn(logPrefix + 'dispatchEvent 点击失败:', dispatchError); console.log(logPrefix + '尝试回退到 button.click()...'); try { button.click(); // 回退 console.log(logPrefix + 'button.click() 成功。'); return true; } catch (clickError) { console.error(logPrefix + 'button.click() 也失败:', clickError); return false; } } } // --- 检查按钮状态并计划(或取消)延迟点击 --- function scheduleOrCancelClick(button) { // 检查按钮当前是否可见且可交互 const isButtonClickable = button && document.body.contains(button) && button.offsetParent !== null && !button.disabled; if (isButtonClickable) { // 如果按钮可点击,并且 *没有* 正在等待的计时器 if (!pendingClickTimeouts.has(button)) { console.log(logPrefix + '检测到可点击按钮,将在 ' + (clickDelay / 1000) + ' 秒后点击...'); const timeoutId = setTimeout(() => { // --- Timeout 回调 --- // 再次检查按钮状态,确保在延迟期间它没有消失或变得不可点击 if (button && document.body.contains(button) && button.offsetParent !== null && !button.disabled) { console.log(logPrefix + '延迟时间到,按钮仍然可点击。'); performActualClick(button); } else { console.log(logPrefix + '延迟时间到,但按钮已不可点击,取消本次点击。'); } // 无论是否点击,都要从 WeakMap 中移除记录,允许下次重新调度 pendingClickTimeouts.delete(button); // --- Timeout 回调结束 --- }, clickDelay); // 将计时器 ID 存入 WeakMap,标记这个按钮正在等待点击 pendingClickTimeouts.set(button, timeoutId); } else { // console.log(logPrefix + '按钮已在等待点击计时中,忽略本次检测。'); // 可选调试日志 } } else { // 如果按钮变得不可点击 (隐藏、禁用、移除) 并且 *有* 正在等待的计时器 if (pendingClickTimeouts.has(button)) { console.log(logPrefix + '按钮变得不可点击,取消之前计划的延迟点击。'); clearTimeout(pendingClickTimeouts.get(button)); // 清除计时器 pendingClickTimeouts.delete(button); // 从 WeakMap 中移除记录 } } } // --- MutationObserver 回调 --- const observerCallback = (mutationsList, observer) => { // 简单起见,每次DOM变化都重新查找按钮并评估状态 // 优化:可以只检查与 buttonSelector 相关的变化,但通常 querySelector 性能足够 const targetButton = document.querySelector(buttonSelector); if (targetButton) { // 如果按钮存在,调用调度函数来决定是否启动或什么都不做 scheduleOrCancelClick(targetButton); } else { // 如果按钮在 DOM 中找不到了,我们需要检查是否有对应的计时器需要取消 // (注意:如果按钮实例还在内存中且在WeakMap里,下面的逻辑可能不完美, // 但通常按钮不存在于DOM时,scheduleOrCancelClick(null)不会执行, // 而如果按钮实例还在但被隐藏/禁用,scheduleOrCancelClick会处理取消) // 简单起见,依赖 scheduleOrCancelClick 在按钮不可见时处理取消。 // console.log(logPrefix + '未找到目标按钮。'); } // --- 更精细的检查(可选)--- // 如果性能有问题,可以像之前版本那样检查 mutationsList // 但需要在找到按钮或按钮消失时都调用 scheduleOrCancelClick /* for (const mutation of mutationsList) { // ... 检查添加、移除、属性变化 ... if (/* 按钮出现或变得可点击 * /) { const button = mutation.target or found button; scheduleOrCancelClick(button); } else if (/* 按钮消失或变得不可点击 * /) { const button = mutation.target or previously known button; // 需要一种方法获取到旧按钮的引用来取消计时器 // 这使得简单地每次重新 querySelector 更方便 } } */ }; // --- 创建并配置观察器 --- const observer = new MutationObserver(observerCallback); const observerConfig = { childList: true, subtree: true, attributes: true, // 监控属性变化也很重要,因为按钮可能通过 disabled 或 style/class 变化 attributeFilter: ['disabled', 'class', 'style'] // 可以限定关心的属性 }; // --- 初始化脚本 --- function initialize() { if (document.body) { console.log(logPrefix + 'DOM 已准备好,执行首次检查并启动 MutationObserver...'); const initialButton = document.querySelector(buttonSelector); if (initialButton) { scheduleOrCancelClick(initialButton); // 初始检查也走调度逻辑 } observer.observe(document.body, observerConfig); console.log(logPrefix + 'MutationObserver 已启动。'); } else { requestAnimationFrame(initialize); } } // --- 启动逻辑 --- if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize); } else { initialize(); } // --- 清理 --- window.addEventListener('unload', () => { if (observer) { observer.disconnect(); console.log(logPrefix + '页面卸载,MutationObserver 已断开。'); } // 清理所有可能存在的待处理计时器 // 遍历当前页面上所有匹配的按钮来查找并清除计时器 document.querySelectorAll(buttonSelector).forEach(button => { if (pendingClickTimeouts.has(button)) { clearTimeout(pendingClickTimeouts.get(button)); pendingClickTimeouts.delete(button); console.log(logPrefix + '页面卸载,清除了一个待处理的点击计时器。'); } }); }); GM_addStyle(` /* 隐藏不需要的元素 */ .header-container, .placeholder-overlay.ng-star-inserted { display: none !important; }`); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址