HUDK - UX tweaks

Mutes downvoted items. Hide specific merchants

当前为 2022-04-18 提交的版本,查看 最新版本

// ==UserScript==
// @name         HUDK - UX tweaks
// @namespace    http://tampermonkey.net/
// @version      0.2.1
// @description  Mutes downvoted items. Hide specific merchants
// @author       thedrunkendev
// @match        https://www.hotukdeals.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=hotukdeals.com
// @run-at       document-start
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==
/* global waitForKeyElements */

(function() {
    'use strict';

    console.log("Injecting Userscript")
    let hiddenMerchants = GM_getValue("gm_hiddenmerchants") || [];
    console.log("Found hiddent merchants:", hiddenMerchants)

    // Hide downvoted
    waitForKeyElements(".vote-box > .bg--color-grey .icon--minus", (el) => {
        console.log(el)
        el.closest(".threadGrid").style.opacity = 0.5;
    }, false, 1_000);

    // Add a hide merchant button
    waitForKeyElements("button.cept-off", (el) => {
        const merchant = el.closest(".threadGrid").querySelector(".cept-merchant-name");
        const merchantIsHidden = hiddenMerchants.includes(merchant?.innerText);
        if (merchant && merchantIsHidden){
            hideMerchant(el, merchant.innerText)
        }
        else{
            insert(el);
        }
    }, false, 1_000);

    function insert(el) {
        var textEl = document.createElement("button")
        textEl.innerText = "hide merchant";
        textEl.className = el.className.replace("cept-off", "btn btn--mode-boxSec");
        textEl.onclick = (clickedEl) => {
            const merchant = el.closest(".threadGrid").querySelector(".cept-merchant-name").innerText;

            hiddenMerchants.push(merchant);
            GM_setValue("gm_hiddenmerchants", hiddenMerchants);

            // Hide button & thread
            clickedEl.target.style.display="none";
            hideMerchant(clickedEl.target, merchant);
        };

        el.insertAdjacentElement("beforebegin", textEl);
    }

    function hideMerchant(el, merchantName){
        const thread = el.closest(".threadGrid");
        thread.style.opacity = 0.8;
        thread.style.justifyContent="space-between";
        thread.style.display="flex";
        thread.innerHTML = `<div><span class="cept-merchant-name">${merchantName}</span> is hidden.</div>`;

        var textEl = document.createElement("button")
        textEl.innerText = "Undo";
        textEl.className = el.className="btn btn--mode-boxSec";
        textEl.onclick = (clickedEl) => {
            const merchant = thread.querySelector(".cept-merchant-name").innerText;

            hiddenMerchants=hiddenMerchants.filter(x=> x!=merchant);
            console.log(hiddenMerchants)
            GM_setValue("gm_hiddenmerchants", hiddenMerchants);

            // Hide button & thread
            clickedEl.target.style.display="none";
            // TODO - show the deal?
        };
        thread.appendChild(textEl);

    }
})();




/**
 * A utility function for userscripts that detects and handles AJAXed content.
 *
 * Usage example:
 *
 *     function callback(domElement) {
 *         domElement.innerHTML = "This text inserted by waitForKeyElements().";
 *     }
 * 
 *     waitForKeyElements("div.comments", callback);
 *     // or
 *     waitForKeyElements(selectorFunction, callback);
 *
 * @param {(string|function)} selectorOrFunction - The selector string or function.
 * @param {function} callback - The callback function; takes a single DOM element as parameter.
 *                              If returns true, element will be processed again on subsequent iterations.
 * @param {boolean} [waitOnce=true] - Whether to stop after the first elements are found.
 * @param {number} [interval=300] - The time (ms) to wait between iterations.
 * @param {number} [maxIntervals=-1] - The max number of intervals to run (negative number for unlimited).
 */
function waitForKeyElements(selectorOrFunction, callback, waitOnce, interval, maxIntervals) {
	if (typeof waitOnce === "undefined") {
		waitOnce = true;
	}
	if (typeof interval === "undefined") {
		interval = 300;
	}
	if (typeof maxIntervals === "undefined") {
		maxIntervals = -1;
	}
	var targetNodes = (typeof selectorOrFunction === "function")
			? selectorOrFunction()
			: document.querySelectorAll(selectorOrFunction);

	var targetsFound = targetNodes && targetNodes.length > 0;
	if (targetsFound) {
		targetNodes.forEach(function(targetNode) {
			var attrAlreadyFound = "data-userscript-alreadyFound";
			var alreadyFound = targetNode.getAttribute(attrAlreadyFound) || false;
			if (!alreadyFound) {
				var cancelFound = callback(targetNode);
				if (cancelFound) {
					targetsFound = false;
				}
				else {
					targetNode.setAttribute(attrAlreadyFound, true);
				}
			}
		});
	}

	if (maxIntervals !== 0 && !(targetsFound && waitOnce)) {
		maxIntervals -= 1;
		setTimeout(function() {
			waitForKeyElements(selectorOrFunction, callback, waitOnce, interval, maxIntervals);
		}, interval);
	}
}