Automates clicking chat turn options and delete buttons in Gemini.
目前為
// ==UserScript==
// @name Google AI Studio | Clear Chat Button
// @namespace http://violentmonkey.net/
// @version 1.0
// @description Automates clicking chat turn options and delete buttons in Gemini.
// @author Vibecoded by Piknockyou
// @match https://aistudio.google.com/prompts*
// @icon https://www.google.com/s2/favicons?sz=64&domain=aistudio.google.com
// @grant GM_addStyle
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
console.log('[Gemini Chat Cleaner] Script loaded and starting...');
console.log('[Gemini Chat Cleaner] Current URL:', window.location.href);
//================================================================================
// CONFIGURATION - All settings, selectors, and values that might need to be changed.
//================================================================================
const CHAT_TURN_OPTIONS_SELECTOR = 'ms-chat-turn-options span[class="material-symbols-outlined notranslate ms-button-icon-symbol ng-star-inserted"]';
const DELETE_BUTTON_MENU_SELECTOR = 'div.mat-mdc-menu-content > button:first-of-type';
const DELETE_BUTTON_TEXT = "delete Delete";
//================================================================================
// STYLES - CSS for the toolbar button (minimal, uses existing toolbar styles)
//================================================================================
GM_addStyle(`
#gemini-cleaner-button {
margin: 0 4px;
}
`);
//================================================================================
// HELPER FUNCTIONS - Reusable utility functions
//================================================================================
/**
* Clicks all elements matching a given CSS selector.
* @param {string} selector The CSS selector for the elements to click.
*/
function clickAllElements(selector) {
try {
const elements = document.querySelectorAll(selector);
if (elements.length === 0) {
console.warn(`[Gemini Chat Cleaner] No elements found for selector: ${selector}`);
return;
}
elements.forEach(element => {
element.click();
});
console.log(`[Gemini Chat Cleaner] Clicked ${elements.length} elements for selector: ${selector}`);
} catch (error) {
console.error(`[Gemini Chat Cleaner] Error clicking elements for selector ${selector}:`, error);
}
}
/**
* Clicks delete buttons within a menu content, identified by specific text.
* @param {string} selector The CSS selector for the menu buttons.
* @param {string} text The text content to match for the delete button.
*/
function clickDeleteButtonsInMenu(selector, text) {
try {
const elements = document.querySelectorAll(selector);
if (elements.length === 0) {
console.warn(`[Gemini Chat Cleaner] No menu elements found for selector: ${selector}`);
return;
}
elements.forEach(element => {
if (element.textContent.trim() === text) {
element.click();
console.log(`[Gemini Chat Cleaner] Clicked delete button with text: "${text}"`);
}
});
} catch (error) {
console.error(`[Gemini Chat Cleaner] Error clicking delete buttons in menu for selector ${selector}:`, error);
}
}
/**
* Creates and appends a floating button to trigger the cleaning functionality.
*/
function createToolbarButton() {
console.log('[Gemini Chat Cleaner] Creating toolbar button...');
// Wait for toolbar to be available
const waitForToolbar = () => {
const toolbarRight = document.querySelector('ms-toolbar .toolbar-right');
if (!toolbarRight) {
console.log('[Gemini Chat Cleaner] Toolbar not ready, waiting...');
setTimeout(waitForToolbar, 500);
return;
}
console.log('[Gemini Chat Cleaner] Toolbar found, creating button...');
// Check if our button already exists
if (document.getElementById('gemini-cleaner-button')) {
console.log('[Gemini Chat Cleaner] Button already exists');
return;
}
const button = document.createElement('button');
button.id = 'gemini-cleaner-button';
button.title = 'Clear Chat Turns';
button.setAttribute('ms-button', '');
button.setAttribute('variant', 'icon-borderless');
button.setAttribute('mattooltip', 'Clear Chat Turns');
button.setAttribute('mattooltipposition', 'below');
button.setAttribute('iconname', 'refresh');
button.className = 'mat-mdc-tooltip-trigger ng-tns-c2648639672-5 ms-button-borderless ms-button-icon ng-star-inserted';
button.setAttribute('aria-label', 'Clear Chat Turns');
button.setAttribute('aria-disabled', 'false');
button.addEventListener('click', main);
// Create the icon span to match the toolbar style
const iconSpan = document.createElement('span');
iconSpan.className = 'material-symbols-outlined notranslate ms-button-icon-symbol ng-star-inserted';
iconSpan.setAttribute('aria-hidden', 'true');
iconSpan.textContent = 'refresh'; // Using refresh icon instead of emoji
button.appendChild(iconSpan);
// Insert before the "more_vert" button (last button in toolbar)
const moreButton = toolbarRight.querySelector('button[iconname="more_vert"]');
if (moreButton) {
toolbarRight.insertBefore(button, moreButton);
console.log('[Gemini Chat Cleaner] Button inserted before more_vert button');
} else {
toolbarRight.appendChild(button);
console.log('[Gemini Chat Cleaner] Button appended to toolbar');
}
// Verify button is in DOM
setTimeout(() => {
const addedButton = document.getElementById('gemini-cleaner-button');
if (addedButton) {
console.log('[Gemini Chat Cleaner] Button successfully added to toolbar');
} else {
console.error('[Gemini Chat Cleaner] Button not found in toolbar after append');
}
}, 100);
};
waitForToolbar();
}
//================================================================================
// MAIN EXECUTION - Core logic of the script
//================================================================================
function main() {
console.log('[Gemini Chat Cleaner] Main function triggered');
// Click all chat turn option icons
clickAllElements(CHAT_TURN_OPTIONS_SELECTOR);
// Click delete buttons in menu content
clickDeleteButtonsInMenu(DELETE_BUTTON_MENU_SELECTOR, DELETE_BUTTON_TEXT);
}
function init() {
console.log('[Gemini Chat Cleaner] Initializing...');
createToolbarButton();
// Optionally run main on load, or let the button trigger it
// main();
}
// Run the main function when the DOM is ready
// Using setTimeout to ensure all dynamic elements are loaded (can be adjusted if needed)
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
console.log('[Gemini Chat Cleaner] DOMContentLoaded event fired');
init();
});
} else {
console.log('[Gemini Chat Cleaner] DOM already loaded, initializing immediately');
init();
}
})();