WhatsApp Right-Click Dropdown Menu

Opens the options menu of a message on right-click in WhatsApp Web, replacing normal right click behavior.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         WhatsApp Right-Click Dropdown Menu
// @namespace    https://web.whatsapp.com/
// @version      1.1
// @license      CC BY-NC-SA 4.0
// @description  Opens the options menu of a message on right-click in WhatsApp Web, replacing normal right click behavior.
// @author       Dan
// @match        *://web.whatsapp.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    function attachContextMenuHandler(node) {
        if (node.classList && (node.classList.contains('message-out') || node.classList.contains('message-in'))) {
            node.addEventListener('contextmenu', function(event) {
                // If the target is a link, image, or selected text, allow the default context menu
                const target = event.target;
                if (target.nodeName === 'A' || target.nodeName === 'IMG' || window.getSelection().toString().length > 0) {
                    return; // Don't prevent default behavior
                }

                event.preventDefault();

                // Try to find the contextual menu button for the message
                let menuButton = node.querySelector('._ahkm'); // Selector for the contextual menu button

                // If it's not found, try another selector (in case of changes in the structure)
                if (!menuButton) {
                    menuButton = node.querySelector('[role="button"][aria-label="Context menu"]');
                }

                if (menuButton) {
                    menuButton.click(); // Open the options menu
                }

                // Make the message blink
                blinkMessage(node);
            });
        }
    }

    function blinkMessage(node) {
        // Add the class that causes the blinking effect
        node.classList.add('blink');

        // Remove the class after a short period (blinking)
        setTimeout(function() {
            node.classList.remove('blink');
        }, 500); // The message will blink for 500ms
    }

    // CSS style for blinking
    const style = document.createElement('style');
    style.innerHTML = `
        .blink {
            animation: blink 0.5s alternate;
        }

        @keyframes blink {
            0% {
                opacity: 1;
            }
            50% {
                opacity: 0;
            }
            100% {
                opacity: 1;
            }
        }
    `;
    document.head.appendChild(style);

    // Observe the chat container for new messages
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            mutation.addedNodes.forEach(node => {
                if (node.nodeType === 1) { // Ensure it's an element
                    attachContextMenuHandler(node);
                    node.querySelectorAll('.message-out, .message-in').forEach(attachContextMenuHandler);
                }
            });
        });
    });

    observer.observe(document.body, { childList: true, subtree: true });
})();