Friends List & AutoDarts Enhancements

Manage friends list with drag, resize, and a direct game link

当前为 2025-01-28 提交的版本,查看 最新版本

// ==UserScript==
// @name         Friends List & AutoDarts Enhancements
// @namespace    Owl
// @version      3.9
// @description  Manage friends list with drag, resize, and a direct game link
// @match        https://play.autodarts.io/*
// @run-at       document-idle
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    console.log("[Friends List Script] Starting...");

    let friendsList = JSON.parse(localStorage.getItem('friendsList')) || [];

    function saveFriendsList() {
        localStorage.setItem('friendsList', JSON.stringify(friendsList));
    }

    // Popup variables
    let popupVisible = false;
    let popupContainer = null;

    // Menu item ID
    const MENU_ITEM_ID = 'autodarts-friendslist-menu-item';

    // --------------------------------------------------
    // A) DRAG LOGIC
    // --------------------------------------------------
    let isDragging = false;
    let offsetX = 0;
    let offsetY = 0;
    let hasConvertedCenter = false;

    function onDragMouseDown(e) {
        e.preventDefault();
        if (!hasConvertedCenter) {
            convertCenterToAbsolutePosition(popupContainer);
            hasConvertedCenter = true;
        }
        isDragging = true;
        offsetX = popupContainer.offsetLeft - e.clientX;
        offsetY = popupContainer.offsetTop - e.clientY;
    }

    function onDragMouseMove(e) {
        if (!isDragging) return;
        e.preventDefault();
        const newLeft = e.clientX + offsetX;
        const newTop = e.clientY + offsetY;
        popupContainer.style.left = newLeft + 'px';
        popupContainer.style.top = newTop + 'px';
    }

    function onDragMouseUp() {
        isDragging = false;
    }

    function convertCenterToAbsolutePosition(elem) {
        const rect = elem.getBoundingClientRect();
        elem.style.left = rect.left + 'px';
        elem.style.top = rect.top + 'px';
        elem.style.transform = 'none';
    }

    // --------------------------------------------------
    // B) CREATE POPUP
    // --------------------------------------------------
    function createPopup() {
        if (popupContainer) return;

        popupContainer = document.createElement('div');
        popupContainer.id = 'autodarts-friendslist-popup';

        Object.assign(popupContainer.style, {
            position: 'fixed',
            left: '50%',
            top: '50%',
            transform: 'translate(-50%, -50%)',
            padding: '20px',
            backgroundColor: '#FFEB3B', // Yellow color for Friends list
            color: '#1A202C',
            border: '1px solid #FF9800',
            borderRadius: '8px',
            boxShadow: '0 0 10px rgba(0,0,0,0.5)',
            zIndex: '99999',
            fontFamily: 'sans-serif',
            width: 'auto',
            minWidth: '300px',
            maxWidth: '80vw',
            maxHeight: '80vh',
            overflowY: 'auto',
            display: 'none',
            resize: 'both',
            overflow: 'auto'
        });

        // Drag bar
        const dragBar = document.createElement('div');
        dragBar.style.height = '20px';
        dragBar.style.cursor = 'move';
        dragBar.style.marginBottom = '10px';
        popupContainer.appendChild(dragBar);

        // Close "X" button
        const closeXButton = document.createElement('button');
        closeXButton.textContent = '×';
        Object.assign(closeXButton.style, {
            position: 'absolute',
            top: '4px',
            right: '8px',
            background: 'transparent',
            border: 'none',
            color: '#1A202C',
            fontSize: '20px',
            lineHeight: '20px',
            cursor: 'pointer'
        });
        closeXButton.addEventListener('click', () => {
            togglePopup(false);
        });
        popupContainer.appendChild(closeXButton);

        // Title
        const title = document.createElement('h2');
        title.textContent = 'Freundesliste';
        title.style.marginTop = '0';
        title.style.fontSize = '1.4rem';
        title.style.fontWeight = 'bold';
        popupContainer.appendChild(title);

        // Input area for name and board ID
        const inputWrapper = document.createElement('div');
        inputWrapper.style.display = 'flex';
        inputWrapper.style.marginBottom = '10px';
        popupContainer.appendChild(inputWrapper);

        const nameInput = document.createElement('input');
        nameInput.type = 'text';
        nameInput.placeholder = 'Name des Freundes';
        Object.assign(nameInput.style, {
            flex: '1',
            marginRight: '5px',
            padding: '4px 8px'
        });
        inputWrapper.appendChild(nameInput);

        const boardIdInput = document.createElement('input');
        boardIdInput.type = 'text';
        boardIdInput.placeholder = 'Board ID des Freundes';
        Object.assign(boardIdInput.style, {
            flex: '1',
            marginRight: '5px',
            padding: '4px 8px'
        });
        inputWrapper.appendChild(boardIdInput);

        const addButton = document.createElement('button');
        addButton.textContent = 'Freund Hinzufügen';
        Object.assign(addButton.style, {
            padding: '4px 8px',
            cursor: 'pointer',
            backgroundColor: '#FF9800',
            color: '#fff',
            border: 'none',
            borderRadius: '4px'
        });
        inputWrapper.appendChild(addButton);

        // UL list
        const listElement = document.createElement('ul');
        listElement.style.listStyle = 'none';
        listElement.style.paddingLeft = '0';
        popupContainer.appendChild(listElement);

        // Add function for name and board ID
        function addFriend() {
            const name = nameInput.value.trim();
            const boardId = boardIdInput.value.trim();
            if (name && boardId) {
                const friend = { name, boardId };
                if (!friendsList.some(f => f.name === name && f.boardId === boardId)) {
                    friendsList.push(friend);
                    saveFriendsList();
                    updateList(listElement);
                }
                nameInput.value = '';
                boardIdInput.value = '';
            }
        }
        addButton.addEventListener('click', addFriend);
        nameInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter') {
                e.preventDefault();
                addFriend();
            }
        });

        // Show the list initially
        updateList(listElement);

        // Add a button to access the game
        const gameLinkButton = document.createElement('button');
        gameLinkButton.textContent = 'Zum Spiel';
        Object.assign(gameLinkButton.style, {
            padding: '4px 8px',
            cursor: 'pointer',
            backgroundColor: '#2D3748',
            color: '#fff',
            border: 'none',
            borderRadius: '4px',
            marginTop: '10px'
        });
        gameLinkButton.addEventListener('click', () => {
            window.location.href = 'https://play.autodarts.io/boards/bc4e64af-b60b-42b2-8420-1982eb2c3ac6/follow';
        });
        popupContainer.appendChild(gameLinkButton);

        document.body.appendChild(popupContainer);

        // Register drag events
        dragBar.addEventListener('mousedown', onDragMouseDown);
        document.addEventListener('mousemove', onDragMouseMove);
        document.addEventListener('mouseup', onDragMouseUp);
    }

    // ---- REMOVE FRIEND (with confirmation) ----
    function removeFriend(name, boardId, listElement) {
        const confirmed = confirm(`Bist du sicher, dass du ${name} mit Board ID ${boardId} entfernen möchtest?`);
        if (confirmed) {
            friendsList = friendsList.filter(friend => friend.name !== name || friend.boardId !== boardId);
            saveFriendsList();
            updateList(listElement);
        }
    }

    function updateList(listElement) {
        listElement.innerHTML = '';
        friendsList.forEach(friend => {
            const li = document.createElement('li');
            li.textContent = `${friend.name} (Board ID: ${friend.boardId})`;
            Object.assign(li.style, {
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'space-between',
                padding: '4px 0'
            });

            const removeBtn = document.createElement('button');
            removeBtn.textContent = 'X';
            Object.assign(removeBtn.style, {
                marginLeft: '10px',
                backgroundColor: '#C53030',
                color: '#fff',
                border: 'none',
                borderRadius: '4px',
                padding: '2px 8px',
                cursor: 'pointer'
            });

            removeBtn.addEventListener('click', () => {
                removeFriend(friend.name, friend.boardId, listElement);
            });

            li.appendChild(removeBtn);
            listElement.appendChild(li);
        });
    }

    function togglePopup(forceOpen) {
        if (!popupContainer) {
            createPopup();
        }
        popupVisible = (typeof forceOpen === 'boolean') ? forceOpen : !popupVisible;
        popupContainer.style.display = popupVisible ? 'block' : 'none';
    }

    // --------------------------------------------------
    // MENU ITEM
    // --------------------------------------------------
    function addFriendsListMenuItem(menuContainer) {
        let friendsListLink = document.getElementById(MENU_ITEM_ID);
        if (!friendsListLink) {
            friendsListLink = document.createElement('a');
            friendsListLink.id = MENU_ITEM_ID;
            friendsListLink.textContent = 'Freundesliste';
            friendsListLink.className = 'chakra-button css-1nal3hj';
            friendsListLink.style.cursor = 'pointer';

            menuContainer.appendChild(friendsListLink);
            friendsListLink.addEventListener('click', () => {
                togglePopup();
            });
        }
    }

    // --------------------------------------------------
    // MUTATIONOBSERVER MIT DEBOUNCE
    // --------------------------------------------------
    let checkTimeout = null;
    function triggerCheckWithDebounce() {
        if (checkTimeout) {
            clearTimeout(checkTimeout);
        }
        checkTimeout = setTimeout(() => {
            checkTimeout = null;
        }, 300);
    }

    const observer = new MutationObserver(() => {
        triggerCheckWithDebounce();
    });
    observer.observe(document.body, { childList: true, subtree: true });

    // --------------------------------------------------
    // MENU FIND + ADD
    // --------------------------------------------------
    const intervalId = setInterval(() => {
        const menuContainer = [...document.querySelectorAll('div.chakra-stack')]
            .find(div => div.querySelector('a[href="/"]') && div.querySelector('a[href="/lobbies"]'));

        if (menuContainer) {
            addFriendsListMenuItem(menuContainer);
            clearInterval(intervalId);
        }
    }, 1000);

    // Start
    updateList();
})();

QingJ © 2025

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