nascent / PlayStation Web Store Enhancer

// ==UserScript==
// @name         PlayStation Web Store Enhancer
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Enhance the PlayStation web store experience with a dark mode and visible titles under game tiles.
// @author       nascent & naveedgol
// @match        https://store.playstation.com/*
// @updateURL    https://openuserjs.org/meta/nascent/PlayStation_Web_Store_Enhancer.meta.js
// @downloadURL  https://openuserjs.org/install/nascent/PlayStation_Web_Store_Enhancer.user.js
// @icon         https://www.google.com/s2/favicons?sz=64&domain=playstation.com
// @copyright    nascent & naveedgol
// @license      MIT
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// ==/UserScript==

// Based on PlayStation Web Store Enhancer by naveedgol, with text contrast fix
(function() {
    'use strict';

    // Get stored settings (defaulting to "true" if they don't exist)
    const showTitles = GM_getValue("show-titles", true);
    const darkModeEnabled = GM_getValue("dark-mode", true);

    // MutationObserver to add game titles from telemetry data when "Show Titles" is enabled.
    if (showTitles) {
        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                const games = document.getElementsByClassName("ems-sdk-product-tile-link");
                for (const game of games) {
                    // If the title has already been added, skip this element.
                    if (game.childNodes.length > 2) continue;

                    // Ensure telemetry metadata exists before processing.
                    if (!game.dataset.telemetryMeta) continue;
                    let name = "";
                    try {
                        name = JSON.parse(game.dataset.telemetryMeta).name;
                    } catch(e) {
                        console.error("Error parsing telemetryMeta JSON:", e);
                        continue;
                    }

                    // Create a new DIV element to display the title.
                    const node = document.createElement("DIV");
                    node.className = "price";
                    node.style.marginTop = "5px";
                    node.textContent = name;
                    // Insert the new element before the second child.
                    game.insertBefore(node, game.childNodes[1]);
                }
            });
        });

        // Start observing the document.
        observer.observe(document, { attributes: true, subtree: true });
    }

    // If "Dark Mode" is enabled, inject the dark mode CSS.
    if (darkModeEnabled) {
        GM_addStyle(`
            /* Dark Mode Styles */
            body, .psw-root body, .tertiary-tabs {
                color: white !important;
                background-color: #000 !important;
                padding: 0 !important;
            }

            /* Price Title */
            .price, .product-detail, .ems-sdk-product-tile .price, .search-results h1, .search-results h1 em {
                color: white !important;
            }

            /* Main Store Top Nav Bar */
            #jetstream-tertiary-nav {
                background-color: black !important;
                fill: black !important;
            }

            #jetstream-tertiary-nav .tertiary-menu-cta,
            #jetstream-tertiary-nav .tertiary-tab__link,
            #jetstream-tertiary-nav .tertiary-tab__link:focus,
            #jetstream-tertiary-nav .tertiary-tab__link:hover,
            #jetstream-tertiary-nav .tertiary-tab__link:visited {
                color: white !important;
                background-color: black !important;
                fill: black !important;
            }

            [dir] #jetstream-tertiary-nav .tertiary-container:not(.tertiary-container--overflow) .tertiary-tab__link,
            [dir] #jetstream-tertiary-nav .tertiary-container:not(.tertiary-container--overflow) .tertiary-tab__link:hover,
            [dir] #jetstream-tertiary-nav .tertiary-container:not(.tertiary-container--overflow) .tertiary-tab__link:focus,
            [dir] #jetstream-tertiary-nav .tertiary-container:not(.tertiary-container--overflow) .tertiary-tab__link:visited,
            [dir] #jetstream-tertiary-nav .tertiary-container:not(.tertiary-container--overflow) .tertiary-tab__link.tertiary-tab__link--active {
                color: white !important;
                background-color: black !important;
                fill: black !important;
            }

            #jetstream-tertiary-nav {
                fill: white !important;
            }

            /* Search Bar */
            .search-text-box__input {
                background-color: black !important;
            }

            /* Fix for .psw-root .psw-c-t-1 to show white text */
            .psw-root .psw-c-t-1 {
                color: white !important;
            }
        `);
    }

    // Add menu command for toggling "Show Titles".
    GM_registerMenuCommand("Toggle Show Titles", () => {
        let current = GM_getValue("show-titles", true);
        GM_setValue("show-titles", !current);
        alert("Show Titles is now " + (!current) + ". Please refresh the page to apply changes.");
    });

    // Add menu command for toggling "Dark Mode".
    GM_registerMenuCommand("Toggle Dark Mode", () => {
        let current = GM_getValue("dark-mode", true);
        GM_setValue("dark-mode", !current);
        alert("Dark Mode is now " + (!current) + ". Please refresh the page to apply changes.");
    });
})();