XButtonx

calc umur, auto reload, hapus Ads, darkmode

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         XButtonx
// @namespace    http://tampermonkey.net/
// @version      1.6
// @description  calc umur, auto reload, hapus Ads, darkmode
// @author       xkhd
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // --- Floating main button ---
    const floatingBtn = document.createElement('div');
    floatingBtn.style.cssText = `
        position: fixed; bottom: 60px; right: 60px;
        width: 60px; height: 60px; border-radius: 50%;
        overflow: hidden; z-index: 9999; cursor: pointer;
        border: 3px solid #007bff; background: #fff;
        display: flex; align-items: center; justify-content: center;
        transition: transform 0.3s ease; box-shadow: 0 4px 8px rgba(0,0,0,0.3);
    `;
    const iconImg = document.createElement('img');
    iconImg.src = 'https://lh3.googleusercontent.com/a/AGNmyxaEnKjzfKogUt2-V-11G5OAQMl0OZKBz7562IzJ=s96-c';
    iconImg.style.cssText = 'width: 100%; height: 100%; object-fit: cover; border-radius: 50%;';
    floatingBtn.appendChild(iconImg);
    document.body.appendChild(floatingBtn);

    // --- Button container (positioned relative to floating button center) ---
    const btnContainer = document.createElement('div');
    // offset to align with floatingBtn center (floatingBtn bottom/right are 60px)
    btnContainer.style.cssText = `
        position: fixed; bottom: 90px; right: 90px;
        width: 0; height: 0; z-index: 9998; pointer-events: none;
    `;
    document.body.appendChild(btnContainer);

    const menuButtons = [];

    // --- Helper: create tooltip element for a button ---
    function makeTooltip(text) {
        const tip = document.createElement('div');
        tip.textContent = text;
        tip.style.cssText = `
            position: absolute;
            bottom: 130%;
            left: 50%;
            transform: translateX(-50%);
            white-space: nowrap;
            padding: 6px 8px;
            background: rgba(0,0,0,0.85);
            color: #fff;
            font-size: 12px;
            border-radius: 6px;
            box-shadow: 0 4px 10px rgba(0,0,0,0.25);
            pointer-events: none;
            opacity: 0;
            transition: opacity 0.18s ease, transform 0.18s ease;
            transform-origin: bottom center;
            z-index: 10001;
        `;
        return tip;
    }

    // --- SVG icons (inline) ---
    const SVG = {
        calc: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                <rect x="3" y="3" width="18" height="18" rx="2" stroke="lime" stroke-width="1.6" fill="#ffffff"/>
                <path d="M7 7h10M7 11h10M7 15h10" stroke="lime" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
               </svg>`,
        reload: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                    <path d="M21 12a9 9 0 10-2.6 6.1L21 21v-4.1" stroke="blue" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
                 </svg>`,
        removeAds: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                      <circle cx="12" cy="12" r="8" stroke="red" stroke-width="1.6" fill="#ffffff"/>
                      <path d="M8 8l8 8M16 8l-8 8" stroke="red" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
                   </svg>`,
        dark: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                 <path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" stroke="orange" stroke-width="1.4" fill="#ffffff"/>
               </svg>`
    };

    // --- Create a menu button with SVG and tooltip text ---
    function createIconButton(svgHTML, tooltipText, callback) {
        const btn = document.createElement('button');
        btn.innerHTML = svgHTML;
        btn.setAttribute('aria-label', tooltipText);
        btn.style.cssText = `
            position: absolute;
            width: 36px; height: 36px; /* rectangle-ish for nicer alignment */
            display:flex; align-items:center; justify-content:center;
            transform: translate(0px, 0px);
            opacity: 0;
            transition: transform 0.38s cubic-bezier(.2,.9,.2,1), opacity 0.28s ease;
            pointer-events: auto;
            background: transparent;
            border: 2px solid #007bff;
            border-radius: 8px;
            padding: 6px;
            font-size: 13px;
            cursor: pointer;
            box-shadow: 0 2px 6px rgba(0,0,0,0.18);
        `;

        // tooltip
        const tip = makeTooltip(tooltipText);
        btn.appendChild(tip);

        // mouse handlers (use dataset tx,ty that will be set later)
        btn.addEventListener('mouseenter', () => {
            const tx = parseFloat(btn.dataset.tx || 0);
            const ty = parseFloat(btn.dataset.ty || 0);
            btn.style.transform = `translate(${tx}px, ${ty}px) scale(1.08)`;
            btn.style.boxShadow = '0 6px 18px rgba(0,0,0,0.28)';
            tip.style.opacity = '1';
            tip.style.transform = 'translateX(-50%) translateY(-6px)';
        });
        btn.addEventListener('mouseleave', () => {
            const tx = parseFloat(btn.dataset.tx || 0);
            const ty = parseFloat(btn.dataset.ty || 0);
            btn.style.transform = `translate(${tx}px, ${ty}px) scale(1)`;
            btn.style.boxShadow = '0 2px 6px rgba(0,0,0,0.18)';
            tip.style.opacity = '0';
            tip.style.transform = 'translateX(-50%) translateY(0)';
        });

        btn.addEventListener('click', (e) => {
            e.stopPropagation(); // avoid closing menu if needed
            callback && callback(e);
        });

        btnContainer.appendChild(btn);
        menuButtons.push(btn);
        return btn;
    }

    // --- Kalkulator Umur (statis) ---
    function showAgeCalculator() {
        const container = document.createElement('div');
        container.style.cssText = `
            all: initial;
            font-family: Arial, sans-serif;
            font-size: 14px;
            position: fixed; top: 50%; left: 50%;
            transform: translate(-50%, -50%);
            background: #ffffff;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 8px 30px rgba(0,0,0,0.25);
            z-index: 10000; min-width: 300px;
            color: #000000;
        `;
        container.innerHTML = `
            <h3 style="margin:0 0 10px 0; font-size:16px; font-weight:700; color:#222;">Kalkulator Umur</h3>
            <label style="display:block; margin-bottom:6px; color:#333;">Tanggal Lahir:</label>
            <input type="date" id="birthDate" style="padding:8px; width:100%; margin-bottom:12px; border:1px solid #ddd; border-radius:6px;">
            <label style="display:block; margin-bottom:6px; color:#333;">Tanggal Acuan:</label>
            <input type="date" id="refDate" value="${new Date().toISOString().split('T')[0]}" style="padding:8px; width:100%; margin-bottom:12px; border:1px solid #ddd; border-radius:6px;">
            <div style="display:flex; gap:10px; justify-content:space-between; margin-top:8px;">
                <button id="calcBtn" style="flex:1; background:#007bff; color:#fff; padding:8px; border:none; border-radius:6px; cursor:pointer;">Hitung</button>
                <button id="closeBtn" style="flex:1; background:#6c757d; color:#fff; padding:8px; border:none; border-radius:6px; cursor:pointer;">Tutup</button>
            </div>
            <div id="result" style="margin-top:14px; font-weight:700; color:#222;"></div>
        `;

        document.body.appendChild(container);

        container.querySelector('#closeBtn').onclick = () => container.remove();
        container.querySelector('#calcBtn').onclick = () => {
            const birthVal = container.querySelector('#birthDate').value;
            const refVal = container.querySelector('#refDate').value;
            const birth = birthVal ? new Date(birthVal) : NaN;
            const ref = refVal ? new Date(refVal) : NaN;
            if (isNaN(birth) || isNaN(ref)) {
                alert("Mohon masukkan kedua tanggal.");
                return;
            }
            if (ref < birth) {
                alert("Tanggal acuan tidak boleh sebelum tanggal lahir.");
                return;
            }
            const age = calcAge(birth, ref);
            container.querySelector('#result').textContent =
                `${age.years} tahun, ${age.months} bulan, ${age.days} hari`;
        };
    }

    function calcAge(birth, ref) {
        let years = ref.getFullYear() - birth.getFullYear();
        let months = ref.getMonth() - birth.getMonth();
        let days = ref.getDate() - birth.getDate();

        if (days < 0) {
            months--;
            const prevMonth = new Date(ref.getFullYear(), ref.getMonth(), 0);
            days += prevMonth.getDate();
        }
        if (months < 0) {
            years--;
            months += 12;
        }
        return { years, months, days };
    }

    // --- Placeholder Auto Reload ---
    function showAutoReloadPopup() {
        // Example implementation: simple popup with interval in minutes (you can extend)
        const container = document.createElement('div');
        container.style.cssText = `
            all: initial;
            font-family: Arial, sans-serif;
            font-size: 14px;
            position: fixed; top: 50%; left: 50%;
            transform: translate(-50%, -50%);
            background: #fff;
            padding: 16px;
            border-radius: 10px;
            box-shadow: 0 8px 30px rgba(0,0,0,0.25);
            z-index: 10000; min-width: 280px;
            color: #000;
        `;
        container.innerHTML = `
            <h3 style="margin:0 0 10px 0; font-size:16px; color:#222;">Auto Reload</h3>
            <label style="display:block; margin-bottom:6px;">Interval (menit)</label>
            <input id="reloadMin" type="number" min="1" placeholder="Menit" style="width:100%; padding:8px; border:1px solid #ddd; border-radius:6px;">
            <div style="display:flex; gap:8px; margin-top:10px;">
                <button id="startReload" style="flex:1; background:#007bff; color:#fff; padding:8px; border:none; border-radius:6px; cursor:pointer;">Mulai</button>
                <button id="stopReload" style="flex:1; background:#6c757d; color:#fff; padding:8px; border:none; border-radius:6px; cursor:pointer;">Berhenti</button>
            </div>
            <div style="display:flex; justify-content:flex-end; margin-top:10px;">
                <button id="closeReload" style="background:transparent; border:none; color:#007bff; cursor:pointer;">Tutup</button>
            </div>
        `;
        document.body.appendChild(container);

        let intervalRef = null;
        container.querySelector('#startReload').onclick = () => {
            const m = parseInt(container.querySelector('#reloadMin').value, 10);
            if (isNaN(m) || m <= 0) {
                alert('Masukkan interval (menit) yang valid.');
                return;
            }
            if (intervalRef) clearInterval(intervalRef);
            intervalRef = setInterval(() => location.reload(), m * 60 * 1000);
            alert(`Auto reload setiap ${m} menit diaktifkan.`);
        };
        container.querySelector('#stopReload').onclick = () => {
            if (intervalRef) {
                clearInterval(intervalRef);
                intervalRef = null;
                alert('Auto reload dihentikan.');
            } else alert('Auto reload belum aktif.');
        };
        container.querySelector('#closeReload').onclick = () => container.remove();
    }

    // --- Remove Ads ---
    function removeAds() {
        const selectors = [
            '[id^="ad"]','[class*="ad"]','[id*="banner"]','[class*="banner"]',
            '[class*="promo"]','[class*="sponsored"]','[class*="ads"]',
            '[id*="popup"]','[class*="popup"]','[class*="overlay"]'
        ];
        selectors.forEach(sel => document.querySelectorAll(sel).forEach(el => el.style.display = 'none'));
        alert('Berhasil menyembunyikan elemen yang berlabel iklan (metode heuristik).');
    }

    // --- Dark Mode toggle (kept global) ---
    const darkStyle = document.createElement('style');
    darkStyle.textContent = `
        body.dark-mode, body.dark-mode * {
            background-color: #111 !important;
            color: #ddd !important;
            border-color: #333 !important;
        }
    `;
    document.head.appendChild(darkStyle);

    if (localStorage.getItem('darkModeEnabled') === 'true') {
        document.body.classList.add('dark-mode');
    }
    function toggleDarkMode() {
        document.body.classList.toggle('dark-mode');
        localStorage.setItem('darkModeEnabled', document.body.classList.contains('dark-mode'));
    }

    // --- Add icon buttons (SVG icons + tooltip text + callbacks) ---
    createIconButton(SVG.calc, 'Kalkulator Umur', showAgeCalculator);
    createIconButton(SVG.reload, 'Auto Reload', showAutoReloadPopup);
    createIconButton(SVG.removeAds, 'Hapus Iklan', removeAds);
    createIconButton(SVG.dark, 'Dark Mode', toggleDarkMode);

    // --- Quarter-circle animation logic ---
    let menuOpen = false;
    floatingBtn.addEventListener('click', () => {
        menuOpen = !menuOpen;
        const total = menuButtons.length;
        const radius = 120; // jarak tombol dari pusat
        const startAngle = -90; // degrees (top)
        const endAngle = -180; // degrees (left)
        const step = (endAngle - startAngle) / Math.max(1, (total - 1));

        menuButtons.forEach((btn, i) => {
            if (menuOpen) {
                const angleDeg = startAngle + step * i;
                const angle = angleDeg * (Math.PI / 180);
                const x = Math.cos(angle) * radius;
                const y = Math.sin(angle) * radius;
                // store translation so hover can reapply scale without losing coords
                btn.dataset.tx = x.toFixed(2);
                btn.dataset.ty = y.toFixed(2);
                // small staggered delay for nicer effect
                btn.style.transitionDelay = `${i * 0.03}s`;
                // move and show
                btn.style.transform = `translate(${x}px, ${y}px) scale(1)`;
                btn.style.opacity = '1';
            } else {
                btn.style.transitionDelay = `${(menuButtons.length - 1 - i) * 0.02}s`;
                btn.dataset.tx = 0;
                btn.dataset.ty = 0;
                btn.style.transform = `translate(0px, 0px) scale(1)`;
                btn.style.opacity = '0';
            }
        });

        floatingBtn.style.transform = menuOpen ? 'rotate(45deg)' : 'rotate(0deg)';
    });

    // --- Close menu when clicking outside ---
    document.addEventListener('click', (e) => {
        if (!menuOpen) return;
        if (floatingBtn.contains(e.target)) return;
        // if clicked a menu button, keep menu open (optional). We'll close for simplicity.
        menuOpen = false;
        menuButtons.forEach((btn, i) => {
            btn.style.transitionDelay = `${(menuButtons.length - 1 - i) * 0.02}s`;
            btn.dataset.tx = 0;
            btn.dataset.ty = 0;
            btn.style.transform = `translate(0px, 0px) scale(1)`;
            btn.style.opacity = '0';
        });
        floatingBtn.style.transform = 'rotate(0deg)';
    });

    // --- Prevent accidental selection when double-clicking ---
    floatingBtn.addEventListener('mousedown', (e) => e.preventDefault());

})();