Greasy Fork

Greasy Fork is available in English.

Xbox Wishlist Sale Items Only

Display sale items with sorting options (discount, price, rating) and toggle sort order

当前为 2024-12-18 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Xbox Wishlist Sale Items Only
// @namespace    http://tampermonkey.net/
// @version      3
// @description  Display sale items with sorting options (discount, price, rating) and toggle sort order
// @match        https://www.xbox.com/*/wishlist
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    let currentSortKey = 'discountPercentage';
    let sortOrder = 'desc';

    const getWishlistData = () => {
        try {
            const script = [...document.scripts].find(s => s.innerText.includes('window.__PRELOADED_STATE__'));
            const dataMatch = script?.innerText.match(/window\.__PRELOADED_STATE__\s*=\s*(\{.*\})\s*;/);
            return dataMatch ? Object.values(JSON.parse(dataMatch[1]).core2?.products?.productSummaries || {}) : [];
        } catch {
            console.error("Error retrieving wishlist data");
            return [];
        }
    };

    const injectStyles = () => {
        const css = `
            body {
                background-color: #121212;
                color: #E0E0E0;
                font-family: 'Roboto', sans-serif;
            }

            .wishlist-container {
                margin: 20px auto;
                padding: 20px;
                background: #1E1E1E;
                border: 2px solid #333;
                border-radius: 12px;
                box-shadow: 0 4px 10px rgba(0, 0, 0, 0.6);
                max-width: 95%;
            }

            .wishlist-title {
                text-align: center;
                font-size: 24px;
                font-weight: bold;
                margin-bottom: 20px;
                color: #E0E0E0;
                text-transform: uppercase;
                border-bottom: 2px solid #333;
                padding-bottom: 10px;
            }

            .wishlist-grid {
                display: grid;
                gap: 5px;
                grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
                padding: 0;
            }

            .custom-card {
                position: relative;
                background: #2A2A2A;
                border-radius: 12px;
                overflow: hidden;
                box-shadow: 0 4px 6px rgba(0, 0, 0, 0.5);
                border: 1px solid transparent;
                transition: transform 0.3s, box-shadow 0.3s;
            }

            .custom-card img {
                width: 100%;
                height: 256px;
            }

            .custom-card:hover {
                border:1px solid white !important;
            }


            .info {
                position: absolute;
                bottom: 0;
                left: 0;
                background: rgba(0, 0, 0, 0.8);
                width: 100%;
                display: flex;
                justify-content: space-between;
                padding: 8px 12px;
                box-sizing: border-box;
                font-size: 14px;
                color: #E0E0E0;
            }

            .price {
                color: #4CAF50;
                font-weight: bold;
            }

            .original-price {
                color: #B0BEC5;
                text-decoration: line-through;
                font-size: 12px;
            }

            .discount {
                color: #FF7043;
                font-weight: bold;
            }

            .rating {
                color: #FFD700;
                font-weight: bold;
            }

            .sort-options {
                display: flex;
                justify-content: center;
                margin-bottom: 20px;
                gap: 10px;
            }

            .sort-options select,
            .sort-options button {
                background: #2A2A2A;
                color: #E0E0E0;
                border: 1px solid #444;
                border-radius: 8px;
                padding: 10px 15px;
                font-size: 14px;
                cursor: pointer;
                transition: background 0.3s, box-shadow 0.3s;
            }

            .sort-options select:hover,
            .sort-options button:hover {
                background: #333;
                box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
            }
        `;
        const style = document.createElement('style');
        style.textContent = css;
        document.head.appendChild(style);
    };

const displayWishlist = (items) => {
    const grid = document.querySelector('.wishlist-grid');
    grid.innerHTML = '';

    items.filter(({ specificPrices }) => {
        const priceData = specificPrices?.purchaseable?.[0];
        return priceData && priceData.listPrice < priceData.msrp;
    }).sort((a, b) => {
        const getValue = (item, key) => {
            const priceData = item.specificPrices?.purchaseable?.[0] || {};
            if (key === 'discountPercentage') return priceData.discountPercentage || 0;
            if (key === 'listPrice') return priceData.listPrice || 0;
            return item.averageRating || 0;
        };
        return sortOrder === 'asc' ? getValue(a, currentSortKey) - getValue(b, currentSortKey)
                                   : getValue(b, currentSortKey) - getValue(a, currentSortKey);
    }).forEach(({ title = "Unknown", images, specificPrices, averageRating, productId }) => {
        const priceData = specificPrices?.purchaseable?.[0] || {};
        const skuId = priceData.skuId || null;
        const detailUrl = `https://www.xbox.com/en-US/games/store/${title.replace(/\s/g, '-').toLowerCase()}/${productId}/${skuId}`;

        const card = document.createElement('div');
        card.className = 'custom-card';
        card.style.cursor = 'pointer';
        card.onclick = () => window.open(detailUrl, '_blank');
        card.innerHTML = `
            <img src="${images?.poster?.url || 'https://via.placeholder.com/200x300'}" alt="${title}">
            <div class="info">
                <div>
                    <div class="price">$${priceData.listPrice?.toFixed(2) || 'N/A'}
                        <span class="original-price">${priceData.msrp ? `$${priceData.msrp.toFixed(2)}` : ''}</span>
                    </div>
                    <div class="discount">${priceData.discountPercentage ? `${priceData.discountPercentage.toFixed(0)}% OFF` : ''}</div>
                </div>
                <div class="rating">★ ${averageRating?.toFixed(1) || 'N/A'}</div>
            </div>
        `;
        grid.appendChild(card);
    });
};

    const addSortOptions = (wishlistData) => {
        const container = document.querySelector('.wishlist-container');
        const sortDiv = document.createElement('div');
        sortDiv.className = 'sort-options';
        sortDiv.innerHTML = `
            <select id="sort-select">
                <option value="discountPercentage">Sort by: Discount</option>
                <option value="listPrice">Sort by: Price</option>
                <option value="averageRating">Sort by: Rating</option>
            </select>
            <button id="toggle-order">Sort: Descending</button>
        `;
        container.insertBefore(sortDiv, container.querySelector('.wishlist-grid'));

        document.getElementById('sort-select').addEventListener('change', (e) => {
            currentSortKey = e.target.value;
            displayWishlist(wishlistData);
        });

        document.getElementById('toggle-order').addEventListener('click', () => {
            sortOrder = sortOrder === 'asc' ? 'desc' : 'asc';
            document.getElementById('toggle-order').textContent = `Sort: ${sortOrder === 'asc' ? 'Ascending' : 'Descending'}`;
            displayWishlist(wishlistData);
        });
    };

    const init = () => {
        injectStyles();

        const container = document.querySelector('.WishlistPage-module__wishListForm___p6wOx');
        if (!container) return console.error("Wishlist container not found");

        container.classList.add('wishlist-container');
        container.innerHTML = `
            <div class="wishlist-title">My Wishlist</div>
            <div class="wishlist-grid"></div>
        `;

        const wishlistData = getWishlistData();
        addSortOptions(wishlistData);
        displayWishlist(wishlistData);
    };

    window.addEventListener('load', init);
})();