Auto Scroll Chat Enhancer

Streamline your character.ai chat experience with the Auto Scroll Chat Enhancer! This script features a control panel with "Start" and "Stop" for key press simulations and an "Auto Scroll" toggle. Activate "Auto Scroll" to automatically view the latest messages, keeping you in the conversation flow seamlessly. Perfect for users seeking an efficient chatting experience.

目前為 2024-04-06 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Auto Scroll Chat Enhancer
// @namespace    http://tampermonkey.net/
// @version      2024-04-06
// @description  Streamline your character.ai chat experience with the Auto Scroll Chat Enhancer! This script features a control panel with "Start" and "Stop" for key press simulations and an "Auto Scroll" toggle. Activate "Auto Scroll" to automatically view the latest messages, keeping you in the conversation flow seamlessly. Perfect for users seeking an efficient chatting experience.
// @author       anonymous
// @match        https://character.ai/chat/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=character.ai
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 自动滚动状态变量
    let autoScrollEnabled = true;

    // 控制面板设置
    const controlPanel = document.createElement('div');
    controlPanel.style.position = 'fixed';
    controlPanel.style.top = '0';
    controlPanel.style.left = '0';
    controlPanel.style.zIndex = '10000';
    controlPanel.style.display = 'flex';
    controlPanel.style.gap = '10px'; // 按钮间距
    document.body.appendChild(controlPanel);

    const startButton = document.createElement('button');
    startButton.textContent = '开始';
    controlPanel.appendChild(startButton);

    const stopButton = document.createElement('button');
    stopButton.textContent = '停止';
    controlPanel.appendChild(stopButton);


    // 创建自动滚动控制按钮
    const autoScrollButton = document.createElement('button');
    autoScrollButton.textContent = `自动滚动: ${autoScrollEnabled ? 'on' : 'off'}`;
    controlPanel.appendChild(autoScrollButton);

    // 为自动滚动按钮添加点击事件监听器
    autoScrollButton.addEventListener('click', () => {
        autoScrollEnabled = !autoScrollEnabled; // 切换自动滚动状态
        autoScrollButton.textContent = `自动滚动: ${autoScrollEnabled ? 'on' : 'off'}`; // 更新按钮文本

        // 如果自动滚动被启用,立即执行一次滚动
        if (autoScrollEnabled) {
            Array.from(box.children).pop()?.scrollIntoView(false);
        }
    });

    // 添加样式
    const style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = `
        .swiper-no-swiping.box-item {
            background-color: var(--surface-elevation-2);
            margin: 0 5px 15px 8px;
            border-radius: 15px;
            padding: 5px 10px;
            cursor: pointer; /* 添加手形光标表示可点击 */
        }
    div[data-test-id="virtuoso-item-list"] {
        width: 50%;
        float: right;
    }
    .size-full > .items-center {
        align-items: flex-end;
    }
    aside {
        display: none;
    }
    *,
    *::before,
    *::after {
        /*         animation: none !important; */
        animation-duration: .01s !important;
        /*         transition: none !important; */
        transition-duration: .01s !important;
    }

    .tidot {
        animation: none;
    }

    .group {
        margin-right: 0;
    }

    .swiper-no-swiping.box-item > div:nth-child(3) {
        display: none;
    }
    `;
    document.head.appendChild(style);

    // 模拟按键操作
    function simulateKeyPress(keyCode) {
        let event = document.createEvent('Event');
        event.initEvent('keydown', true, false);
        event = Object.assign(event, {
            ctrlKey: false,
            metaKey: false,
            altKey: false,
            which: keyCode,
            keyCode: keyCode,
            key: keyCode === 37 ? 'ArrowLeft' : 'ArrowRight',
            code: keyCode === 37 ? 'ArrowLeft' : 'ArrowRight'
        });
        document.dispatchEvent(event);
    }

    let intervalId;

    // 点击开始按钮
    startButton.addEventListener('click', () => {
        console.log('开始模拟按键');
        start();
    });

    function start(){
        if(intervalId) clearInterval(intervalId);
        document.querySelector('textarea').focus();
        intervalId = setInterval(() => simulateKeyPress(39), 40);
    }

    // 点击停止按钮
    stopButton.addEventListener('click', () => {
        console.log('停止模拟按键');
        stop();
    });

    function stop(){
        clearInterval(intervalId);
    }

    // 显示内容的box
    const box = document.createElement('div');
    box.style.position = 'fixed';
    box.style.top = '50px';
    box.style.left = '0';
    box.style.width = '50%';
    box.style.height = '94vh';
    box.style.overflow = 'scroll';
    document.body.appendChild(box);

    let cache = '';
    // 更新box中的内容以匹配swiper-wrapper的当前状态
    function updateBoxContent() {
        const swiperWrapper = document.querySelector('.swiper-wrapper');
        if (swiperWrapper) {
            if(swiperWrapper.innerText===cache) return;
            cache = swiperWrapper.innerText;
            if(swiperWrapper.children.length<3){
                start();
            }
            box.innerHTML = ''; // 清空现有内容
            const elements = swiperWrapper.querySelectorAll('.swiper-no-swiping');
            elements.forEach((element, index) => {
                const clone = element.cloneNode(true);
                clone.classList.add('box-item');
                clone.addEventListener('dblclick', () => {
                    stop();
                    const a = Array.from(box.children).indexOf(clone);
                    const b = Array.from(swiperWrapper.children).indexOf(document.querySelector('.swiper-wrapper > .swiper-slide-active'));
                    const difference = a - b;
                    console.error(a,b)
                    if (difference < 0) {
                        for (let i = 0; i < Math.abs(difference); i++) {
                            simulateKeyPress(37); // 按下左箭头
                        }
                    } else {
                        for (let i = 0; i < difference; i++) {
                            simulateKeyPress(39); // 按下右箭头
                        }
                    }
                });
                box.appendChild(clone);
            });
            // 当自动滚动开启时,自动滚动到最新内容
            if (autoScrollEnabled) {
                Array.from(box.children).pop()?.scrollIntoView(false);
            }
        }
    }

    function setupObserver() {
        // 选择更高级别的元素作为观察目标,例如 body 或特定容器
        const container = document.body;

        let check = Date.now();
        const observer = new MutationObserver((mutations, obs) => {
            if(document.querySelector('div[role=dialog')){
                stop();
                return;
            }
            if(Date.now()-check<1000) return;
            // 每次变动时检查.swiper-wrapper是否存在
            const swiperWrapper = document.querySelector('.swiper-wrapper');
            if (swiperWrapper) {
                check = Date.now()
                updateBoxContent();
            }
        });

        // 监视元素的子元素变化
        observer.observe(container, { childList: true, subtree: true });
    }

    setupObserver();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址