// ==UserScript== // @name Hide Seen Rows // @namespace http://tampermonkey.net/ // @version 0.31 // @description Remember and hide unique rows based on URL // @author Jacob Chapman // @match *://*/* // @grant none // ==/UserScript== (function() { 'use strict'; let sliderHtml = ` <div id="hide_seen_rows" style=" position: fixed; bottom: 10px; left: 0; background: rgba(255, 255, 255, 0.8); padding: 10px; border-radius: 5px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); z-index: 1000; "> <details><summary>h</summary> <input type="range" id="timeThresholdSlider" min="0" max="300" value="0"> <span id="timeThresholdDisplay" style="width: 200px;"></span> </details> </div> `; let container = document.createElement('div'); container.innerHTML = sliderHtml; document.body.appendChild(container); document.getElementById('timeThresholdSlider').addEventListener('input', function() { let thresholdHours = getTimeThreshold(); let displayText = ''; if (thresholdHours === undefined) { displayText = 'disabled'; } else { let days = Math.floor(thresholdHours / 24); let hours = Math.floor(thresholdHours % 24); if (days > 0) { displayText += days + ' day' + (days > 1 ? 's' : ''); } if (hours > 0 || days === 0) { displayText += ' ' + hours + ' hour' + (hours > 1 ? 's' : ''); } } document.getElementById('timeThresholdDisplay').textContent = displayText; hideRows(); }); function getTimeThreshold() { let slider = document.getElementById('timeThresholdSlider'); if (slider.value === slider.max) return; let value = parseFloat(slider.value); return value } function hideRows() { let rows = getRows(); let thresholdHours = getTimeThreshold(); rows.forEach(row => { row.style.opacity = 1; let identifier = getRowIdentifier(row); if (identifier) { let storedValue = localStorage.getItem(identifier); if (storedValue) { let timestamp = parseInt(storedValue, 10); if (!isNaN(timestamp)) { let timeDifference = Date.now() - timestamp; let hoursDifference = timeDifference / (1000 * 60 * 60); if (hoursDifference > thresholdHours) { row.style.opacity = 0.5; } } } } }); } function hasAnySubstringInParamKeys(paramKeys, substrings) { for (const key of paramKeys) { for (const substring of substrings) { if (key.includes(substring)) { return true; } } } return false; } function filterHref(href) { const url = new URL(href); const relativePath = url.pathname + url.search; const paramKeys = url.searchParams.keys(); const ignoreScheme = url.protocol in ['magnet:']; const ignoreParamKeys = hasAnySubstringInParamKeys(paramKeys, ['category', 'cat']); const isLong = relativePath.length > 100; // Return false if any of the conditions are met return !(ignoreScheme || ignoreParamKeys || isLong); } function filterLinks(links) { const filteredLinks = links.entries().filter(link => filterHref(link.href)); return filteredLinks.length > 0 ? filteredLinks : links; } function getRowIdentifier(row) { let links = row.querySelectorAll('a'); if (links.length === 0) { return null; } links = filterLinks(links); return links[0]; } function findTableWithMostRows() { let tables = document.querySelectorAll('table'); let maxRows = 0; let tableWithMostRows = null; tables.forEach(table => { let rows = table.querySelectorAll('tr'); let directRows = Array.from(rows).filter(row => row.parentElement === table || (row.parentElement.tagName === 'TBODY' && row.parentElement.parentElement === table)); if (directRows.length > maxRows) { maxRows = directRows.length; tableWithMostRows = table; } }); if (maxRows == 0) { document.getElementById('hide_seen_rows').style.display = "none"; } else { document.getElementById('hide_seen_rows').style.display = "block"; } return tableWithMostRows; } function getRows() { let tableWithMostRows = findTableWithMostRows(); if (tableWithMostRows) { return tableWithMostRows.querySelectorAll('tr') } return [] } function markRowsAsSeen() { let rows = getRows(); rows.forEach(row => { let identifier = getRowIdentifier(row); if (identifier) { console.log(identifier) let storedValue = localStorage.getItem(identifier); if (!storedValue || isNaN(parseInt(storedValue, 10))) { localStorage.setItem(identifier, Date.now().toString()); } } }); } hideRows(); markRowsAsSeen(); })();