您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Viva la carrots
// ==UserScript== // @name Carrot Loading Animation for Janitor AI // @namespace https://janitorai.com/ // @version 1.0.1 // @description Viva la carrots // @author IWasTheSyntaxError // @match https://janitorai.com/chats* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; const seenContainers = new WeakSet(); const carrotFrames = ['🥕', '🥕🥕', '🥕🥕🥕']; const carrotFrameInterval = 500; function createFloatingCarrotOverlay(p) { if (p.dataset.carrotOverlayAttached) return; // Find nearest non-static positioned parent let parent = p.parentElement; while (parent && getComputedStyle(parent).position === 'static') { parent = parent.parentElement; } if (!parent) return; // Ensure parent is relatively positioned for absolute overlay if (getComputedStyle(parent).position === 'static') { parent.style.position = 'relative'; } const overlay = document.createElement('div'); overlay.style.position = 'absolute'; overlay.style.pointerEvents = 'none'; overlay.style.left = `${p.offsetLeft}px`; overlay.style.top = `${p.offsetTop}px`; overlay.style.font = getComputedStyle(p).font; overlay.style.color = getComputedStyle(p).color; overlay.style.zIndex = '9999'; overlay.style.whiteSpace = 'pre'; const shadow = overlay.attachShadow({ mode: 'open' }); const span = document.createElement('span'); shadow.appendChild(span); let frameIndex = 0; const interval = setInterval(() => { if (!document.body.contains(p)) { clearInterval(interval); overlay.remove(); return; } if (!/^replying/i.test(p.innerText.trim())) { clearInterval(interval); overlay.remove(); p.removeAttribute('data-carrot-overlay-attached'); p.style.opacity = ''; return; } span.textContent = carrotFrames[frameIndex++ % carrotFrames.length]; }, carrotFrameInterval); parent.appendChild(overlay); p.dataset.carrotOverlayAttached = 'true'; p.style.opacity = '0'; // Hide the original text } function handleParagraph(p) { const text = p.innerText.trim(); if (/^replying\.*/i.test(text)) { createFloatingCarrotOverlay(p); } } function observeContainer(container) { if (seenContainers.has(container)) return; seenContainers.add(container); console.log('[CARROT] Observing container:', container); const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if (node.nodeType === 1) { if (node.tagName === 'P') { handleParagraph(node); } else { node.querySelectorAll?.('p')?.forEach(handleParagraph); } } }); if (mutation.type === 'characterData' && mutation.target.nodeType === 3) { const p = mutation.target.parentElement; if (p?.tagName === 'P') { handleParagraph(p); } } }); }); observer.observe(container, { childList: true, subtree: true, characterData: true, }); container.querySelectorAll('p').forEach(handleParagraph); } function scanAndObserve() { const containers = document.querySelectorAll('div.css-ji4crq'); const last = containers[containers.length - 1]; if (last) observeContainer(last); } scanAndObserve(); setInterval(scanAndObserve, 500); })();