Greasy Fork

Greasy Fork is available in English.

Claude.ai | Remove active (current) chat by CTRL+SHIFT+BACKSPACE

Delete active chat in Claude.ai sidebar using Ctrl+Shift+Backspace

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Claude.ai | Remove active (current) chat by CTRL+SHIFT+BACKSPACE
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Delete active chat in Claude.ai sidebar using Ctrl+Shift+Backspace
// @author       Saymonn
// @match        https://claude.ai/chat*
// @icon         https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQO8QnSw5ArwqF8PsafiMQ3EsH0Xr9LFLgNpwutam6-FN7UhoQvXeyqIHyNvj907vU5BKU&usqp=CAU
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const CONFIG = {
        AUTO_CONFIRM: false,
        WAIT_TIME: 200,
        TIMEOUT: 3000
    };

    const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

    const waitForElement = (selector, timeout = CONFIG.TIMEOUT) => {
        return new Promise((resolve, reject) => {
            const element = document.querySelector(selector);
            if (element) return resolve(element);

            const observer = new MutationObserver(() => {
                const element = document.querySelector(selector);
                if (element) {
                    observer.disconnect();
                    resolve(element);
                }
            });

            observer.observe(document.body, { childList: true, subtree: true });
            setTimeout(() => {
                observer.disconnect();
                reject(new Error('Timeout'));
            }, timeout);
        });
    };

    const simulateClick = element => {
        if (!element) return false;

        const rect = element.getBoundingClientRect();
        const x = rect.left + rect.width / 2;
        const y = rect.top + rect.height / 2;

        [
            new PointerEvent('pointerdown', { bubbles: true, pointerId: 1, clientX: x, clientY: y, button: 0 }),
            new MouseEvent('mousedown', { bubbles: true, clientX: x, clientY: y, button: 0 }),
            new PointerEvent('pointerup', { bubbles: true, pointerId: 1, clientX: x, clientY: y, button: 0 }),
            new MouseEvent('mouseup', { bubbles: true, clientX: x, clientY: y, button: 0 }),
            new MouseEvent('click', { bubbles: true, clientX: x, clientY: y, button: 0 })
        ].forEach(event => element.dispatchEvent(event));

        return true;
    };

    const findActiveMenuButton = () => {
        const selectors = [
            'li a.\\!bg-bg-300',
            'li a[aria-current="page"]',
            'li a[class*="bg-accent"]',
            'li a[class*="active"]'
        ];

        for (const selector of selectors) {
            const activeChat = document.querySelector(selector);
            if (activeChat) {
                const container = activeChat.closest('div.group');
                const menuButton = container?.querySelector('button[aria-haspopup="menu"]');
                if (menuButton) return menuButton;
            }
        }

        const allLinks = document.querySelectorAll('nav li a[href*="/chat"]');
        for (const link of allLinks) {
            if (link.getAttribute('href') === window.location.pathname ||
                link.classList.contains('!bg-bg-300')) {
                const container = link.closest('div.group');
                const menuButton = container?.querySelector('button[aria-haspopup="menu"]');
                if (menuButton) return menuButton;
            }
        }

        return null;
    };

    const findDeleteButton = () => {
        const selectors = [
            '[data-testid="delete-chat-trigger"]',
            '[data-testid*="delete"]',
            'button[aria-label*="Delete"]',
            'button[aria-label*="delete"]',
            '[role="menuitem"]'
        ];

        for (const selector of selectors) {
            const elements = document.querySelectorAll(selector);
            for (const element of elements) {
                const text = element.textContent?.toLowerCase() || '';
                const label = element.getAttribute('aria-label')?.toLowerCase() || '';
                if (text.includes('delete') || label.includes('delete')) {
                    return element;
                }
            }
        }

        return null;
    };

    const deleteActiveChat = async () => {
        try {
            const menuButton = findActiveMenuButton();
            if (!menuButton) return;

            simulateClick(menuButton);
            await wait(CONFIG.WAIT_TIME);

            let deleteButton = findDeleteButton();
            if (!deleteButton) {
                simulateClick(menuButton);
                await wait(CONFIG.WAIT_TIME);
                deleteButton = findDeleteButton();
            }

            if (!deleteButton) return;

            deleteButton.click();

            if (CONFIG.AUTO_CONFIRM) {
                try {
                    const confirmButton = await waitForElement('[data-testid="delete-modal-confirm"]');
                    confirmButton.click();
                } catch {
                    const fallbackButton = document.querySelector('button[data-testid="delete-modal-confirm"]');
                    if (fallbackButton) fallbackButton.click();
                }
            }
        } catch (error) {
        }
    };

    document.addEventListener('keydown', event => {
        if (event.ctrlKey && event.shiftKey && event.code === 'Backspace') {
            event.preventDefault();
            deleteActiveChat();
        }
    });

})();