Buy & Sell Shortcuts

Insert a convenient Buy button and Sell button on item menus

目前為 2025-06-09 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Buy & Sell Shortcuts
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Insert a convenient Buy button and Sell button on item menus
// @author       McPeyen
// @match        https://www.milkywayidle.com/*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // Cache to track if buttons have been inserted for the current submenu instance
    let buttonsInsertedForCurrentSubmenu = false;

    // Helper function to find a button by its text content and partial class name
    function findButtonByTextAndClass(text, partialClass, container = document) {
        const buttons = container.querySelectorAll(`.${partialClass}`);
        for (const button of buttons) {
            if (button.textContent.trim() === text) {
                return button;
            }
        }
        return null;
    }

    // Function to handle the click actions for Sell/Buy
    function handleButtonClick(buttonType) {
        console.log(`[Custom Buttons] ${buttonType} button clicked - starting sequence`);

        const viewMarketplaceButton = findButtonByTextAndClass('View Marketplace', 'Button_fullWidth__17pVU');
        if (viewMarketplaceButton) {
            console.log('[Custom Buttons] Clicking View Marketplace button');
            viewMarketplaceButton.click();

            setTimeout(() => {
                let targetButtonText;
                let targetButtonClass;

                if (buttonType === 'Sell') {
                    targetButtonText = '+ New Sell Listing';
                    targetButtonClass = 'Button_sell__3FNpM';
                } else if (buttonType === 'Buy') {
                    targetButtonText = '+ New Buy Listing';
                    targetButtonClass = 'Button_buy__3s24l';
                }

                const newListingButton = findButtonByTextAndClass(targetButtonText, targetButtonClass);

                if (newListingButton) {
                    console.log(`[Custom Buttons] Clicking ${targetButtonText} button`);
                    newListingButton.click();
                } else {
                    console.error(`[Custom Buttons] ${targetButtonText} button not found after clicking View Marketplace. Is the delay long enough?`);
                }
            }, 1000); // Increased delay slightly
        } else {
            console.error('[Custom Buttons] View Marketplace button not found when trying to simulate click sequence.');
        }
    }

    // Consolidated function to insert both Sell and Buy buttons
    function insertCustomButtons() {
        // If buttons are already inserted for this instance, or the necessary elements aren't present yet,
        // prevent re-insertion or premature insertion.
        if (buttonsInsertedForCurrentSubmenu) {
            // console.log('[Custom Buttons] Buttons already inserted for current submenu, skipping.');
            return;
        }

        const amountInputContainer = document.querySelector('.Item_amountInputContainer__1RT17');
        const viewMarketplaceButton = findButtonByTextAndClass('View Marketplace', 'Button_fullWidth__17pVU');

        // This is the crucial check: are the necessary context elements available?
        if (!amountInputContainer || !viewMarketplaceButton) {
            // console.log('[Custom Buttons] Required elements for insertion not found yet.');
            return;
        }

        // Try to find a common parent for the buttons, specifically the one containing 'View Marketplace'
        const buttonParent = viewMarketplaceButton.parentElement; // Assumes 'View Marketplace' is in a suitable parent

        if (!buttonParent) {
            console.error('[Custom Buttons] Could not find parent element for button insertion.');
            return;
        }

        console.log('[Custom Buttons] Attempting to insert custom buttons...');

        const buttonsToInsert = [
            { text: 'Sell', action: () => handleButtonClick('Sell'), className: '' },
            { text: 'Buy', action: () => handleButtonClick('Buy'), className: '' }
        ];

        let lastSibling = viewMarketplaceButton; // Start inserting after View Marketplace

        buttonsToInsert.forEach(btnConfig => {
            // Check if THIS specific button already exists in the current submenu
            const existingButton = findButtonByTextAndClass(btnConfig.text, 'Button_fullWidth__17pVU', buttonParent);

            if (!existingButton) {
                console.log(`[Custom Buttons] Creating and inserting ${btnConfig.text} button.`);
                const newButton = document.createElement('button');
                newButton.className = `Button_button__1Fe9z Button_fullWidth__17pVU ${btnConfig.className}`;
                newButton.textContent = btnConfig.text;

                // Insert new button directly after the previous button in the list, or View Marketplace
                lastSibling.insertAdjacentElement('afterend', newButton);
                newButton.addEventListener('click', btnConfig.action);

                // Update the last sibling for the next insertion
                lastSibling = newButton;
            } else {
                console.log(`[Custom Buttons] ${btnConfig.text} button already exists, skipping creation.`);
                lastSibling = existingButton; // Ensure correct placement for next button if it exists
            }
        });

        // Mark that buttons have been inserted for this instance
        buttonsInsertedForCurrentSubmenu = true;
        console.log('[Custom Buttons] Buttons insertion attempt completed. Set buttonsInsertedForCurrentSubmenu to true.');
    }

    // Create a MutationObserver to watch for changes in the DOM
    const observer = new MutationObserver((mutationsList, observer) => {
        let submenuAppeared = false;
        let submenuDisappeared = false;

        for (const mutation of mutationsList) {
            if (mutation.type === 'childList') {
                // Check if the submenu container (or a reliable parent) was added
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1 && node.matches && (node.matches('.Item_amountInputContainer__1RT17') || node.querySelector('.Item_amountInputContainer__1RT17'))) {
                        submenuAppeared = true;
                        console.log('[Custom Buttons] Submenu container detected (added node).');
                    }
                });

                // Check if the submenu container (or a reliable parent) was removed
                mutation.removedNodes.forEach(node => {
                    if (node.nodeType === 1 && node.matches && (node.matches('.Item_amountInputContainer__1RT17') || node.querySelector('.Item_amountInputContainer__1RT17'))) {
                        submenuDisappeared = true;
                        console.log('[Custom Buttons] Submenu container detected (removed node).');
                    }
                });
            }
        }

        if (submenuAppeared) {
            // Give the browser a brief moment to fully render the submenu content
            // before attempting to insert buttons. This can sometimes solve race conditions.
            setTimeout(() => {
                insertCustomButtons();
            }, 50); // Small delay
        } else if (submenuDisappeared) {
            // When the submenu disappears, reset the flag so buttons can be re-inserted next time.
            console.log('[Custom Buttons] Submenu disappeared, resetting buttonsInsertedForCurrentSubmenu flag.');
            buttonsInsertedForCurrentSubmenu = false;
        }
    });

    // Start observing the document body for additions/removals of nodes anywhere
    observer.observe(document.body, {
        childList: true, // Watch for direct children being added or removed
        subtree: true    // Watch for changes in the entire subtree of the body
    });

    // Initial check in case the submenu is already open on page load
    console.log('[Custom Buttons] Initial script run.');
    insertCustomButtons();
})();