您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Clean UI with popup removal and focus mode for Gray Swan Arena with persistent state
// ==UserScript== // @name Gray Swan Arena - Focus Mode // @namespace http://tampermonkey.net/ // @version 2.1 // @license MIT // @description Clean UI with popup removal and focus mode for Gray Swan Arena with persistent state // @author KarthiDreamr // @match https://app.grayswan.ai/* // @grant GM_addStyle // @grant GM.getValue // @grant GM.setValue // @grant GM_addValueChangeListener // @grant GM_removeValueChangeListener // @homepage https://github.com/yourusername/grayswan-focus-mode // @supportURL https://github.com/yourusername/grayswan-focus-mode/issues // ==/UserScript== (async function() { 'use strict'; // ========== CONFIGURATION ========== const CONFIG = { storageKey: 'gsa_focusMode', buttonPosition: { top: '14px', left: '14px' }, animations: true, crossTabSync: true, autoApplyDelay: 100, // ms delay before applying clean mode popupCleanupInterval: 500, // ms interval for popup removal debugMode: false }; // ========== UTILITY FUNCTIONS ========== function log(...args) { if (CONFIG.debugMode) { console.log('[GSA Focus Mode]', ...args); } } function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // ========== LOAD PERSISTED STATE ========== let isFocusMode = await GM.getValue(CONFIG.storageKey, false); log('Initial state loaded:', isFocusMode); // Apply focus mode immediately if saved (prevents flicker) if (isFocusMode) { setTimeout(() => { document.body.classList.add('gsa-focus-mode'); log('Focus mode applied from storage'); }, CONFIG.autoApplyDelay); } // ========== POPUP REMOVAL SYSTEM ========== function removePopupComponents() { /* ========================================================= 1. REMOVE UI COMPONENT 1 - Success congratulations ---------------------------------------------------------*/ document.querySelectorAll('p.mb-4.text-left.text-sm').forEach(p => { if (p.textContent.includes('Congratulations - you have successfully submitted a working break')) { const container = p.closest('div.flex.w-full.flex-col'); if (container) { container.remove(); log('Removed success congratulations popup'); } } }); /* ========================================================= 2. REMOVE UI COMPONENT 2 - Prize dialog footer ---------------------------------------------------------*/ document.querySelectorAll('div[data-slot="dialog-footer"]').forEach(footer => { const t = footer.textContent || ''; if (t.includes('What prizes can I win?') && t.includes('Got it')) { footer.remove(); log('Removed prize dialog footer'); } }); /* ========================================================= 3. REMOVE UI COMPONENT 3 - Break failure dialog footer ---------------------------------------------------------*/ document.querySelectorAll('div[data-slot="dialog-footer"]').forEach(footer => { const t = footer.textContent || ''; if (t.includes('Why did my break fail?') && t.includes('Got it')) { footer.remove(); log('Removed break failure dialog footer'); } }); /* ========================================================= 4. REMOVE UI COMPONENT 4 - Dialog headers ---------------------------------------------------------*/ document.querySelectorAll('div[data-slot="dialog-header"]').forEach(header => { const t = header.textContent || ''; if (t.includes('Break Successful!') || t.includes('Break Rejected')) { header.remove(); log('Removed dialog header'); } }); } // Start popup cleanup interval setInterval(removePopupComponents, CONFIG.popupCleanupInterval); log('Popup cleanup system started'); // ========== ENHANCED CSS STYLES ========== GM_addStyle(` /* Hide header - but preserve lightbulb and its popup */ .gsa-focus-mode .bg-background.fixed.top-0:not([aria-labelledby]):not([data-tooltip]):not([role="tooltip"]) { display: none !important; } /* Hide main sidebar - but NOT the documentation sidebar */ .gsa-focus-mode #sidebar:not([aria-labelledby="behaviorDocDrawerTitle"]) { display: none !important; } .gsa-focus-mode .relative.hidden.h-full.md\\:block:not([aria-labelledby]) { display: none !important; } /* CRITICAL: Always show the lightbulb documentation sidebar */ .gsa-focus-mode aside[aria-labelledby="behaviorDocDrawerTitle"], .gsa-focus-mode aside.fixed.top-0.right-0, .gsa-focus-mode aside.__web-inspector-hide-shortcut__ { display: flex !important; visibility: visible !important; opacity: 1 !important; pointer-events: auto !important; z-index: 9999 !important; } /* EXCEPTION: Always preserve tooltip/popup/dropdown elements */ .gsa-focus-mode [data-tooltip], .gsa-focus-mode [role="tooltip"], .gsa-focus-mode [data-popover], .gsa-focus-mode [data-dropdown], .gsa-focus-mode [data-slot="tooltip"], .gsa-focus-mode [data-slot="popover"], .gsa-focus-mode [data-slot="dropdown-menu"], .gsa-focus-mode .tooltip, .gsa-focus-mode .popover, .gsa-focus-mode .dropdown-menu { display: block !important; visibility: visible !important; opacity: 1 !important; pointer-events: auto !important; } /* EXCEPTION: Lightbulb button and any trigger elements */ .gsa-focus-mode button[data-tooltip-trigger], .gsa-focus-mode button:has(svg.lucide-lightbulb), .gsa-focus-mode [id*="bits-"]:not(#gsa-focus-toggle):not(#gsa-status-indicator) { display: flex !important; visibility: visible !important; } /* Hide breadcrumb navigation */ .gsa-focus-mode nav[data-slot="breadcrumb"] { display: none !important; } /* Hide top tab navigation */ .gsa-focus-mode .scrollbar-hide.-mb-1.flex.max-w-screen { display: none !important; } /* Hide mobile menu button */ .gsa-focus-mode .md\\:hidden button[data-slot="sheet-trigger"] { display: none !important; } /* ENHANCED: Remove all padding and margins from main containers */ .gsa-focus-mode .flex.flex-1.flex-col.overflow-hidden.pt-\\[4\\.5rem\\] { padding-top: 0 !important; padding-left: 0 !important; padding-right: 0 !important; } .gsa-focus-mode .relative.mx-auto.flex.h-full.w-full.flex-1 { padding: 0 !important; margin: 0 !important; max-width: none !important; } .gsa-focus-mode .flex.md\\:h-full.md\\:w-full.md\\:gap-4 { gap: 0 !important; padding: 0 !important; } /* ENHANCED: Make chat area completely full screen */ .gsa-focus-mode .relative.flex.h-full.w-full.flex-col.gap-3 { max-width: none !important; margin: 0 !important; padding: 8px !important; gap: 8px !important; } /* ENHANCED: Remove padding from chat container */ .gsa-focus-mode .dark\\:border-border.relative.flex.min-h-0.flex-1.flex-col.overflow-hidden { margin: 0 !important; } /* ENHANCED: Optimize chat content area spacing */ .gsa-focus-mode .flex.h-full.min-h-0.flex-1.flex-col.overflow-auto { padding: 12px !important; } /* ENHANCED: Remove excessive margins from chat messages area */ .gsa-focus-mode .mx-auto.flex.h-full.w-full.max-w-prose.flex-col.items-center.justify-center.space-y-2 { max-width: none !important; margin: 0 !important; padding: 0 !important; } /* ENHANCED: Optimize input area spacing */ .gsa-focus-mode .relative.mx-auto.w-full.max-w-\\[75ch\\].shrink-0 { max-width: none !important; margin: 0 !important; padding: 8px !important; } /* ENHANCED: Remove body margins in focus mode */ .gsa-focus-mode body { margin: 0 !important; padding: 0 !important; } /* ENHANCED: Make main content container full height */ .gsa-focus-mode .flex.min-h-screen.w-full.flex-col.overflow-hidden { min-height: 100vh !important; } /* ========== ENHANCED TOGGLE BUTTON STYLES ========== */ #gsa-focus-toggle { position: fixed; top: ${CONFIG.buttonPosition.top}; left: ${CONFIG.buttonPosition.left}; z-index: 10000; background: #1a1a1a; color: #e5e5e5; border: 1px solid #333; border-radius: 20px; padding: 6px 12px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', monospace; font-size: 12px; font-weight: 500; cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,0.2); transition: all 0.2s ease; backdrop-filter: blur(8px); opacity: 0.8; user-select: none; display: flex; align-items: center; gap: 4px; } #gsa-focus-toggle:hover { background: #2a2a2a; border-color: #555; opacity: 1; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.3); } #gsa-focus-toggle.active { background: #1a1a1a; border-color: #30363d; color: #58a6ff; } #gsa-focus-toggle.active:hover { background: #2a2a2a; border-color: #58a6ff; } /* ========== STATUS INDICATOR ========== */ #gsa-status-indicator { position: fixed; top: ${CONFIG.buttonPosition.top}; left: calc(${CONFIG.buttonPosition.left} + 120px); z-index: 9999; background: rgba(0, 0, 0, 0.8); color: #fff; padding: 4px 8px; border-radius: 12px; font-size: 10px; font-family: monospace; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; backdrop-filter: blur(4px); } #gsa-status-indicator.show { opacity: 1; } #gsa-status-indicator.success { background: rgba(34, 197, 94, 0.8); } #gsa-status-indicator.sync { background: rgba(59, 130, 246, 0.8); } /* ========== ANIMATIONS ========== */ ${CONFIG.animations ? ` .gsa-focus-mode { transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } .gsa-focus-mode * { transition: all 0.2s ease; } ` : ''} /* ========== RESPONSIVE IMPROVEMENTS ========== */ @media (max-width: 768px) { #gsa-focus-toggle { top: 10px; left: 10px; padding: 5px 10px; font-size: 11px; } #gsa-status-indicator { top: 10px; left: 100px; } } `); // ========== CORE FUNCTIONALITY ========== let toggleButton; let statusIndicator; let changeListener; // Create UI elements function createUI() { // Toggle button toggleButton = document.createElement('button'); toggleButton.id = 'gsa-focus-toggle'; updateButtonText(); toggleButton.title = 'Toggle focus mode (F8 or Ctrl+Shift+F)'; // Status indicator statusIndicator = document.createElement('div'); statusIndicator.id = 'gsa-status-indicator'; statusIndicator.textContent = 'Ready'; document.body.appendChild(toggleButton); document.body.appendChild(statusIndicator); log('UI elements created'); } // Update button text and state function updateButtonText() { if (!toggleButton) return; if (isFocusMode) { toggleButton.classList.add('active'); toggleButton.innerHTML = '↩️ <span style="font-size: 10px;">Exit</span>'; } else { toggleButton.classList.remove('active'); toggleButton.innerHTML = '🎯 <span style="font-size: 10px;">Focus</span>'; } } // Show status message function showStatus(message, type = 'success', duration = 2000) { if (!statusIndicator) { log('Status indicator not ready, skipping message:', message); return; } statusIndicator.textContent = message; statusIndicator.className = `show ${type}`; setTimeout(() => { if (statusIndicator) { statusIndicator.classList.remove('show'); statusIndicator.classList.remove(type); } }, duration); } // Enhanced toggle function async function toggleFocusMode(source = 'manual') { const wasActive = isFocusMode; isFocusMode = document.body.classList.toggle('gsa-focus-mode'); // Update UI updateButtonText(); // Save state try { await GM.setValue(CONFIG.storageKey, isFocusMode); log(`Mode toggled to: ${isFocusMode ? 'ON' : 'OFF'} (source: ${source})`); if (source === 'manual') { showStatus( isFocusMode ? 'Focus Mode ON' : 'Focus Mode OFF', 'success' ); } else if (source === 'sync') { showStatus('Synced from other tab', 'sync', 1500); } } catch (error) { console.error('[GSA Focus Mode] Failed to save state:', error); showStatus('Save failed', 'error'); } } // Debounced toggle for performance const debouncedToggle = debounce(toggleFocusMode, 100); // ========== CROSS-TAB SYNCHRONIZATION ========== function setupCrossTabSync() { if (!CONFIG.crossTabSync) return; changeListener = GM_addValueChangeListener( CONFIG.storageKey, (name, oldVal, newVal, remote) => { if (!remote) return; // Ignore changes from this tab log('Received remote state change:', newVal); isFocusMode = !!newVal; // Apply state change document.body.classList.toggle('gsa-focus-mode', isFocusMode); updateButtonText(); // Show sync notification showStatus('Synced from other tab', 'sync', 1500); } ); log('Cross-tab synchronization enabled'); } // ========== KEYBOARD SHORTCUTS ========== function setupKeyboardShortcuts() { document.addEventListener('keydown', function(e) { // F8 shortcut if (e.key === 'F8') { e.preventDefault(); debouncedToggle('keyboard'); return; } // Ctrl+Shift+F shortcut if (e.ctrlKey && e.shiftKey && e.key === 'F') { e.preventDefault(); debouncedToggle('keyboard'); return; } // Escape to exit focus mode if (e.key === 'Escape' && isFocusMode) { debouncedToggle('keyboard'); return; } }); log('Keyboard shortcuts registered: F8, Ctrl+Shift+F, Escape'); } // ========== AUTO-DETECTION AND ADAPTATION ========== function adaptToPageChanges() { // Observer for dynamic content changes const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.type === 'childList' && isFocusMode) { // Re-apply focus mode classes if needed setTimeout(() => { if (!document.body.classList.contains('gsa-focus-mode')) { document.body.classList.add('gsa-focus-mode'); log('Focus mode re-applied after DOM change'); } }, 50); } }); }); observer.observe(document.body, { childList: true, subtree: true }); log('DOM observer started for dynamic content adaptation'); } // ========== INITIALIZATION ========== function initialize() { createUI(); setupCrossTabSync(); setupKeyboardShortcuts(); adaptToPageChanges(); // Button click event toggleButton.addEventListener('click', () => debouncedToggle('manual')); // Apply saved state with proper timing if (isFocusMode) { updateButtonText(); // Delay the status message to ensure UI is ready setTimeout(() => showStatus('Focus Mode restored', 'success', 1500), 100); } log('Script fully initialized'); // Delay the loaded message to ensure statusIndicator is fully ready setTimeout(() => { showStatus('GSA Focus Mode loaded', 'success', 2000); }, 200); } // ========== CLEANUP ========== window.addEventListener('beforeunload', function() { if (changeListener && CONFIG.crossTabSync) { GM_removeValueChangeListener(changeListener); log('Cleanup completed'); } }); // ========== START ========== if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize); } else { // DOM already loaded setTimeout(initialize, 100); } // Fallback initialization window.addEventListener('load', function() { if (!toggleButton) { log('Fallback initialization triggered'); initialize(); } }); log('Gray Swan Arena Focus Mode script loaded successfully'); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址