您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Defaults Google searches to AI Mode, selects 2.5 Pro, and adds a floating button to switch back to Web Search.
当前为
// ==UserScript== // @name Google AI - Default to AI Mode & 2.5 Pro (Floating UI) // @namespace http://tampermonkey.net/ // @version 4.1 // @description Defaults Google searches to AI Mode, selects 2.5 Pro, and adds a floating button to switch back to Web Search. // @author JP - Discord: @Organism // @match https://www.google.com/search* // @grant GM_addStyle // @run-at document-start // ==/UserScript== (function() { 'use strict'; // --- Part 1: Redirect Logic (with loop prevention) --- const url = new URL(window.location.href); if (sessionStorage.getItem('forceWebSearch') === 'true') { sessionStorage.removeItem('forceWebSearch'); } else { if (url.searchParams.has('q') && url.searchParams.get('udm') !== '50') { url.searchParams.set('udm', '50'); window.location.href = url.toString(); return; } } // --- Part 2: AI Mode Page Setup --- function setupAiPage() { // This is the proven logic for selecting the model. It runs first. function setupModelSelector() { const TOGGLE_BUTTON_XPATH = "//div[contains(@class, 'tk4Ybd') and .//span[starts-with(text(),'AI Mode')]]"; const PRO_MODEL_ITEM_XPATH = "//g-menu-item[.//span[text()='2.5 Pro']]"; function findElement(xpath) { return document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; } const observer = new MutationObserver((mutations, obs) => { const proMenuItem = findElement(PRO_MODEL_ITEM_XPATH); if (proMenuItem) { if (proMenuItem.getAttribute('aria-checked') === 'false') { proMenuItem.click(); } obs.disconnect(); return; } const toggleButton = findElement(TOGGLE_BUTTON_XPATH); if (toggleButton) { toggleButton.click(); } }); observer.observe(document.body, { childList: true, subtree: true }); } // This function creates and injects the floating button UI. function createFloatingButton() { if (document.getElementById('web-search-flt-btn')) return; // Use GM_addStyle to inject CSS for the button. GM_addStyle(` #web-search-flt-container { position: fixed; bottom: 20px; right: 20px; z-index: 9999; user-select: none; } #web-search-flt-btn { background-color: rgba(30, 30, 30, 0.85); color: white; border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 8px; padding: 10px 16px; font-family: "Google Sans", Roboto, Arial, sans-serif; font-size: 14px; font-weight: 500; cursor: grab; backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); transition: background-color 0.2s; } #web-search-flt-btn:hover { background-color: rgba(50, 50, 50, 0.9); } #web-search-flt-btn:active { cursor: grabbing; background-color: rgba(0, 0, 0, 0.9); } `); const container = document.createElement('div'); container.id = 'web-search-flt-container'; const button = document.createElement('button'); button.id = 'web-search-flt-btn'; button.textContent = 'Web Search'; container.appendChild(button); document.body.appendChild(container); // --- Click and Drag Logic --- let isDragging = false; let offsetX, offsetY; let clickThreshold = 5; // Pixels a user can move mouse before it's a drag let movedDistance = 0; const onPointerDown = (e) => { isDragging = true; movedDistance = 0; const rect = container.getBoundingClientRect(); const pointerX = e.clientX || e.touches[0].clientX; const pointerY = e.clientY || e.touches[0].clientY; offsetX = pointerX - rect.left; offsetY = pointerY - rect.top; button.style.cursor = 'grabbing'; }; const onPointerMove = (e) => { if (!isDragging) return; e.preventDefault(); const pointerX = e.clientX || e.touches[0].clientX; const pointerY = e.clientY || e.touches[0].clientY; let newX = pointerX - offsetX; let newY = pointerY - offsetY; movedDistance += Math.abs(newX - container.offsetLeft) + Math.abs(newY - container.offsetTop); container.style.left = `${newX}px`; container.style.top = `${newY}px`; container.style.right = 'auto'; container.style.bottom = 'auto'; }; const onPointerUp = (e) => { isDragging = false; button.style.cursor = 'grab'; // If the mouse moved less than the threshold, treat it as a click. if (movedDistance < clickThreshold) { sessionStorage.setItem('forceWebSearch', 'true'); const currentUrl = new URL(window.location.href); currentUrl.searchParams.delete('udm'); window.location.href = currentUrl.toString(); } }; // Mouse events button.addEventListener('mousedown', onPointerDown); document.addEventListener('mousemove', onPointerMove); document.addEventListener('mouseup', onPointerUp); // Touch events button.addEventListener('touchstart', onPointerDown, { passive: false }); document.addEventListener('touchmove', onPointerMove, { passive: false }); document.addEventListener('touchend', onPointerUp); } // Run the functions. setupModelSelector(); createFloatingButton(); } // --- Part 3: Execution --- if (url.searchParams.get('udm') === '50') { document.addEventListener('DOMContentLoaded', setupAiPage); } })();