// ==UserScript==
// @name OkCupid better filtering
// @namespace http://tampermonkey.net/
// @version 20241108.3
// @description Adds filters to the discover feature
// @author You
// @match https://www.okcupid.com/home
// @match https://www.okcupid.com/discover
// @icon https://www.google.com/s2/favicons?sz=64&domain=okcupid.com
// @grant none
// @license MIT
// ==/UserScript==
const dynamicStylePrefix = `css-${window.crypto.randomUUID()}`;
const locationIcon = `<svg width="24" height="24" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39" /></svg>`;
const basicsIcon = `<svg width="24" height="24" viewBox="0 0 24 24"><path d="M17.75 12.843a5.454 5.454 0 1 1-.001 10.907 5.454 5.454 0 0 1 0-10.907zm0 1.5a3.953 3.953 0 1 0-.001 7.907 3.953 3.953 0 0 0 0-7.907zM10.431 8.55a.75.75 0 0 1 .75.75v8.885a.75.75 0 0 1-.75.75H1.547a.75.75 0 0 1-.75-.75V9.3a.75.75 0 0 1 .75-.75h8.885zm-.75 1.5H2.297v7.385h7.385V10.05zM11.42.275l9.91 2.656a.75.75 0 0 1 .336 1.255l-7.254 7.254a.75.75 0 0 1-1.255-.337l-2.655-9.91a.75.75 0 0 1 .918-.918zm.867 1.785l1.983 7.4 5.417-5.417-7.4-1.983z" fill="#1A1A1A" fill-rule="nonzero"></path></svg>`;
const looksIcon = `<svg width="24" height="24" viewBox="0 0 24 24"><path d="M12.03 7.104a3.552 3.552 0 1 1 3.552-3.543 3.543 3.543 0 0 1-3.552 3.543zm0-5.704a2.16 2.16 0 1 0 2.16 2.161 2.15 2.15 0 0 0-2.16-2.16z" fill="#191919"></path><path d="M14.376 24.01a2.059 2.059 0 0 1-1.984-1.743l-.334-2.57-.38 2.57a2.077 2.077 0 0 1-2.069 1.743 2.225 2.225 0 0 1-1.641-.705 2.207 2.207 0 0 1-.621-1.669l.62-6.946-.416.686a1.957 1.957 0 0 1-2.152.928 1.854 1.854 0 0 1-1.215-1.02 1.8 1.8 0 0 1 0-1.586l2.745-5.25a3.617 3.617 0 0 1 2.68-1.947l1.725-.25a4.48 4.48 0 0 1 1.317 0l1.734.25a3.617 3.617 0 0 1 2.7 1.948l2.726 5.212a1.855 1.855 0 0 1-1.178 2.606 1.957 1.957 0 0 1-2.152-.928l-.417-.686.621 6.918a2.27 2.27 0 0 1-2.262 2.402l-.047.037zm-2.365-9.162a.871.871 0 0 1 .872.77l.835 6.426a.668.668 0 0 0 .658.557.873.873 0 0 0 .64-.27.844.844 0 0 0 .232-.648l-.844-9.47a.788.788 0 0 1 1.465-.481l1.762 2.912a.566.566 0 0 0 .622.25.428.428 0 0 0 .278-.612L15.84 9.07a2.215 2.215 0 0 0-1.65-1.187l-1.725-.232a3.051 3.051 0 0 0-.928 0l-1.725.25A2.216 2.216 0 0 0 8.172 9.09L5.482 14.3a.427.427 0 0 0 .279.613.556.556 0 0 0 .621-.26l1.762-2.903a.788.788 0 0 1 1.465.482l-.853 9.497a.862.862 0 0 0 .533.822c.11.046.229.07.348.068a.668.668 0 0 0 .659-.566l.834-6.417a.927.927 0 0 1 .881-.788z" fill="#191919"></path></svg>`;
const backgroundIcon = `<svg width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="M12.155.016L12 .015C18.627.015 24 5.38 24 12c0 6.566-5.287 11.899-11.841 11.984a.769.769 0 0 1-.317-.001l.158.002C5.373 23.985 0 18.619 0 12 0 5.433 5.289.1 11.844.016a.764.764 0 0 1 .311 0zM6.773 12.748l-5.247.001c.344 4.855 3.996 8.797 8.718 9.592a17.025 17.025 0 0 1-3.47-9.593zm15.7.001h-5.246a17.025 17.025 0 0 1-3.47 9.591c4.721-.794 8.373-4.736 8.717-9.591zm-6.748 0h-7.45A15.543 15.543 0 0 0 12 22.13a15.54 15.54 0 0 0 3.725-9.383zm-5.481-11.09l-.191.034c-4.63.867-8.188 4.768-8.527 9.557h5.247a17.027 17.027 0 0 1 3.47-9.591zm1.756.21l-.253.303a15.537 15.537 0 0 0-3.472 9.078h7.45a15.535 15.535 0 0 0-3.472-9.078L12 1.869zm1.755-.21l.137.18a17.022 17.022 0 0 1 3.335 9.411h5.247c-.344-4.855-3.996-8.798-8.719-9.591z" id="Icon/Background/24" fill="#1A1A1A" fill-rule="nonzero"></path></g></svg>`;
const lifestyleIcon = `<svg width="17" height="24" viewBox="0 0 17 24"><g fill="none" fill-rule="evenodd"><path d="M18.617.153c.305.232.383.65.196.973l-.053.078-.568.743h2.054a.75.75 0 0 1 .655 1.12l-.06.09-7.589 9.762V22.5h2.326c.416 0 .753.336.753.75 0 .385-.29.702-.665.745l-.088.005H9.422a.752.752 0 0 1-.753-.75c0-.385.29-.702.665-.745l.088-.005h2.324v-9.582L4.159 3.157a.75.75 0 0 1 .488-1.202l.107-.007L16.3 1.947 17.562.296a.755.755 0 0 1 1.055-.143zm.093 3.294h-1.664l-3.947 5.167a.755.755 0 0 1-1.055.143.748.748 0 0 1-.196-.973l.052-.078 3.253-4.259H6.289l6.21 7.99 6.211-7.99z" transform="translate(-4)" id="Icon/Lifestyle/24" fill="#1A1A1A" fill-rule="nonzero"></path></g></svg>`;
const familyIcon = `<svg width="24" height="20" viewBox="0 0 24 20"><g fill="none" fill-rule="evenodd"><path d="M17.976 2c.229 0 .445.107.587.29l5.274 6.802a.77.77 0 0 1 .164.455L24 9.57v11.66c0 .389-.282.71-.648.761L23.25 22H.75a.757.757 0 0 1-.743-.664L0 21.23V9.571l.001-.041a.79.79 0 0 1 .004-.044L0 9.571c0-.18.06-.344.16-.475l.003-.003 5.268-6.795a.737.737 0 0 1 .35-.258c.003 0 .007 0 .01-.002A.699.699 0 0 1 6.024 2l-.062.003A.736.736 0 0 1 6.014 2h.01zM6.024 4.005L1.5 9.84v10.62h2.063v-6.921c0-.39.282-.712.648-.763l.102-.007h3.375a.76.76 0 0 1 .75.77v6.921h2.111V9.838L6.024 4.005zM22.5 10.34H12.049v10.12H22.5V10.34zM6.938 14.308H5.063v6.152h1.875v-6.152zM20.3 12.769a.76.76 0 0 1 .75.77V17a.76.76 0 0 1-.75.77h-6a.76.76 0 0 1-.75-.77V13.54a.76.76 0 0 1 .75-.77zm-3.776 1.538H15.05v1.924l1.474-.001v-1.923zm3.026 0h-1.526v1.923h1.526v-1.922zm-1.937-10.77H7.578l4.083 5.264h10.033l-4.081-5.263z" transform="translate(0 -2)" id="Icon/Family/24" fill="#1A1A1A" fill-rule="nonzero"></path></g></svg>`;
const lookingIcon = `<svg width="24" height="22" viewBox="0 0 24 22"><g fill="none" fill-rule="evenodd"><path d="M11.994 6.415l.412.007c1.898.059 3.727.552 5.499 1.51.977.524 1.95 1.221 2.932 2.098.5.467.89.858 1.255 1.27l.428.496c.41.492.814 1.052 1.213 1.68a.75.75 0 0 1 0 .804 16.127 16.127 0 0 1-1.207 1.673l-.427.495c-.247.279-.502.545-.798.834l-.476.455c-.97.866-1.943 1.562-2.919 2.086-1.9 1.027-3.864 1.52-5.912 1.517-2.053-.015-4.012-.51-5.899-1.535-.976-.525-1.948-1.22-2.93-2.095a17.247 17.247 0 0 1-1.438-1.473 15.582 15.582 0 0 1-1.459-1.955.75.75 0 0 1 0-.808 15.51 15.51 0 0 1 1.45-1.945c.432-.505.873-.952 1.458-1.494.971-.864 1.943-1.56 2.917-2.083C7.982 6.927 9.94 6.43 11.994 6.415zm.01 1.5l-.387.01c-1.668.069-3.258.504-4.811 1.347-.868.466-1.746 1.094-2.621 1.874-.446.413-.8.765-1.137 1.14l-.41.473c-.28.335-.561.708-.84 1.119.35.514.701.97 1.06 1.373.388.454.788.86 1.315 1.35.887.788 1.765 1.416 2.635 1.884 1.671.907 3.388 1.342 5.193 1.355 1.794.002 3.513-.429 5.194-1.337.868-.467 1.745-1.095 2.618-1.873.47-.44.827-.797 1.168-1.182l.381-.441c.281-.338.562-.714.842-1.13-.28-.415-.562-.793-.848-1.135l-.41-.473a17.134 17.134 0 0 0-1.12-1.131c-.885-.79-1.763-1.419-2.633-1.886-1.559-.843-3.151-1.275-4.807-1.33l-.383-.007zM12 9.162a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9zm0 1.5a3 3 0 1 0 0 6 3 3 0 0 0 0-6zm10.088-7.307a.75.75 0 0 1 1.06 1.06L20.975 6.59a.75.75 0 0 1-1.06-1.06zm-21.236 0a.75.75 0 0 1 1.06 0l2.174 2.173a.75.75 0 0 1-1.061 1.06L.852 4.416a.75.75 0 0 1 0-1.06zM12 0a.75.75 0 0 1 .75.75v3.074a.75.75 0 1 1-1.5 0V.75A.75.75 0 0 1 12 0z" id="lookingfor-eye-Icon/Looking-For/24" fill="#1A1A1A" fill-rule="nonzero"></path></g></svg>`;
const profileIDTest = /profile\/(.+)\/questions/;
const skippedIds = [];
const currentProfile = {
id: null,
username: null,
exclusions: [],
};
let debugMode = false;
let filters = {
filterLocation: [],
filterBasics: [],
filterLooks: [],
filterBackground: [],
filterLifetsyle: [],
filterFamily: [],
filterLooking: [],
};
if (localStorage.getItem('filterList') !== null && localStorage.getItem('filterList') !== '') {
filters = JSON.parse(localStorage.getItem('filterList'));
}
function updateStorage() {
// Remove empty strings.
Object.keys(filters).forEach((storageKey) => {
filters[storageKey] = filters[storageKey].filter((term) => term !== '');
});
localStorage.setItem('filterList', JSON.stringify(filters));
}
const filtersSkeleton = [
{
icon: locationIcon,
storageKey: 'filterLocation',
title: 'Location',
selector: 'div.card-content-header__location',
},
{
icon: basicsIcon,
storageKey: 'filterBasics',
title: 'Basics',
selector: 'div.matchprofile-details-section--basics div.matchprofile-details-text',
},
{
icon: looksIcon,
storageKey: 'filterLooks',
title: 'Looks',
selector: 'div.matchprofile-details-section--looks div.matchprofile-details-text',
},
{
icon: backgroundIcon,
storageKey: 'filterBackground',
title: 'Background',
selector: 'div.matchprofile-details-section--background div.matchprofile-details-text',
},
{
icon: lifestyleIcon,
storageKey: 'filterLifetsyle',
title: 'Lifestyle',
selector: 'div.matchprofile-details-section--lifestyle div.matchprofile-details-text',
},
{
icon: familyIcon,
storageKey: 'filterFamily',
title: 'Family',
selector: 'div.matchprofile-details-section--family div.matchprofile-details-text',
},
{
icon: lookingIcon,
storageKey: 'filterLooking',
title: 'Loooking for',
selector: 'div.matchprofile-details-section--wiw div.matchprofile-details-text',
},
];
function buildFilterHTML() {
const htmlArray = filtersSkeleton.map((filter) => {
const listElements = filters[filter.storageKey].map((el) => {
return `<li class="${dynamicStylePrefix}exclusion" data-key="${filter.storageKey}" data-value="${el}">${el}</li>`;
}).join(`\n`);
return `
<div class="${dynamicStylePrefix}filter-item">
<div class="${dynamicStylePrefix}filter-addition">
<div title="${filter.title}">${filter.icon}</div>
<div><input type="text" id="${dynamicStylePrefix}${filter.storageKey}" data-key="${filter.storageKey}" /></div>
</div>
<ul class="${dynamicStylePrefix}exclusion-list">
${listElements}
</ul>
</div>\n`;
});
return htmlArray.join(`\n`);
}
function toggleFeature() {
const toggleElement = document.getElementById(`${dynamicStylePrefix}button-base-root`);
const toggleTrack = document.getElementById(`${dynamicStylePrefix}track`);
// Local storage saves only strings.
const filtersEnabled = localStorage.getItem('filtersEnabled') === 'true';
if (filtersEnabled) {
// Turn off the filter.
toggleElement.classList.remove('checked');
toggleTrack.classList.remove('checked');
} else {
// Turn on the filter.
toggleElement.classList.add('checked');
toggleTrack.classList.add('checked');
}
console.debug(`[user script] Setting the filtersEnabled value to ${!filtersEnabled}.`);
localStorage.setItem('filtersEnabled', !filtersEnabled);
}
function bindFilterListItem(el) {
el.addEventListener('click', () => {
const value = el.innerText;
const storageKey = el.getAttribute('data-key');
console.debug(`[user script] The user wants to remove this value. ${value}`);
filters[storageKey] = filters[storageKey].filter((item) => item !== value);
updateStorage();
el.remove();
});
}
function bindFilterItem(el) {
const inputField = el.querySelector('input');
const listElement = el.querySelector('ul');
const storageKey = inputField.getAttribute('data-key');
inputField.addEventListener('keyup', ({ target, key, keyCode }) => {
const searchTerm = target.value.trim().toLowerCase();
if (searchTerm !== '' && (key === 'Enter' || keyCode === 13) && !filters[storageKey].includes(searchTerm)) {
const newListItem = document.createElement('li');
newListItem.innerHTML = searchTerm;
newListItem.setAttribute('data-key', storageKey);
newListItem.setAttribute('data-value', searchTerm);
bindFilterListItem(newListItem);
listElement.insertAdjacentElement('beforeend', newListItem);
inputField.value = null;
filters[storageKey].push(searchTerm);
updateStorage();
}
});
}
let profileLoop = null;
function getProfileID() {
let matchButton = document.querySelector('[data-cy="discover.userCardMatchPercentage"]');
if (matchButton) {
const { href } = matchButton;
const matches = href.match(profileIDTest);
if (matches !== null) {
return matches[1];
}
}
return 'unknown';
};
function getProfileUsername() {
const headerElement = document.querySelector('div.card-content-header__name-container h2');
if (headerElement) {
return headerElement.innerHTML;
}
return 'unknown';
}
function compileExclusions() {
// Reset the found exclusions list.
currentProfile.exclusions = [];
filtersSkeleton.forEach((filter) => {
// Are there any exlusions set for this category?
if (filters[filter.storageKey].length === 0) {
return false;
}
const detailElement = document.querySelector(filter.selector);
if (!detailElement) {
return false;
}
detailElement.innerText.split('|').forEach((detail) => {
const profileDetail = detail.trim().toLowerCase();
filters[filter.storageKey].forEach((filterTerm) => {
const exclusionListItem = document.querySelector(`li[data-value="${filterTerm}"]`);
exclusionListItem.classList.remove('found');
if (filterTerm !== '' && (profileDetail.includes(filterTerm) || profileDetail === filterTerm)) {
exclusionListItem.classList.add('found');
currentProfile.exclusions.push(profileDetail);
}
});
});
});
}
let passing = false;
function pass() {
const clickEvent = new Event('click');
const blockButton = document.getElementById('user-script-block');
const passButton = document.querySelector('button.dt-action-buttons-button.pass');
const notificationElement = document.getElementById(`${dynamicStylePrefix}notification`);
// The page has not yet loaded enough to have rendered the elements we need.
if (!passButton || !notificationElement) {
console.debug(`[user script] [${currentProfile.id}] Waiting for elements.`);
setTimeout(() => pass, 100);
}
const { id } = currentProfile;
if (blockButton) {
console.debug(`[user script] [${currentProfile.id}] Blocking profile.`);
blockButton.dispatchEvent(clickEvent);
} else {
console.debug(`[user script] [${currentProfile.id}] Passing on profile.`);
passButton.dispatchEvent(clickEvent);
}
skippedIds.push(id);
setTimeout(() => {
// The profile still hasn't changed.
if (id === currentProfile.id) {
pass();
}
}, 2000);
}
function checkProfileLoop() {
clearInterval(profileLoop);
const notificationElement = document.getElementById(`${dynamicStylePrefix}notification`);
const debugSpanID = document.getElementById(`${dynamicStylePrefix}debug-id`);
const debugSpanUsername = document.getElementById(`${dynamicStylePrefix}debug-username`);
const debugSpanExclusions = document.getElementById(`${dynamicStylePrefix}debug-exclusions`);
profileLoop = setInterval(() => {
const profileId = getProfileID();
const username = getProfileUsername();
compileExclusions();
const hasExclusion = currentProfile.exclusions.length > 0;
// The profile has changed.
if (profileId !== currentProfile.id) {
console.debug(`[user script] [${profileId}] Found a new profile.`);
passing = false;
if (hasExclusion) {
console.debug(`[user script] [${profileId}] This profile contains ${currentProfile.exclusions.length} exclusions.`);
}
}
// Update the current profile.
currentProfile.id = profileId;
currentProfile.username = username;
debugSpanUsername.innerHTML = username;
debugSpanID.innerHTML = profileId;
debugSpanExclusions.innerHTML = !hasExclusion ? '' : currentProfile.exclusions.join('<br />');
notificationElement.style.display = hasExclusion ? 'flex' : 'none';
if (!skippedIds.includes(profileId) && hasExclusion) {
if (localStorage.getItem('filtersEnabled') === 'true') {
console.debug(`[user script] [${currentProfile.id}] Setting this profile to be passed.`);
passing = true;
pass();
}
}
}, 500);
}
function initialize(detailsTopElement) {
console.debug('[user script] Initializing the detail filter.');
const debugContainer = document.createElement('div');
debugContainer.classList.add(`${dynamicStylePrefix}hidden`);
debugContainer.classList.add(`${dynamicStylePrefix}debug-container`);
debugContainer.innerHTML = `<h3 class="dt-section-title">Debug</h3>
<div class="dt-section-content">
<div>
<span>id</span>
<span id="${dynamicStylePrefix}debug-id"></span>
</div>
<div>
<span>username</span>
<span id="${dynamicStylePrefix}debug-username"></span>
</div>
<div style="margin-top: 1em;">
<span>exclusions</span>
<br>
<span id="${dynamicStylePrefix}debug-exclusions"></span>
<div>
</div>`;
document.querySelector('body').insertAdjacentElement('beforeend', debugContainer);
const enabled = localStorage.getItem('filtersEnabled') === 'true';
const filterContainer = document.createElement('div');
filterContainer.classList.add('dt-section');
filterContainer.innerHTML = `
<h3 class="dt-section-title">Filters</h3>
<div class="dt-section-content">
<div class="${dynamicStylePrefix}control-container">
<div style="flex-grow: 1;">
<span class="${dynamicStylePrefix}switch-root" id="${dynamicStylePrefix}switch-root">
<span class="${dynamicStylePrefix}button-base-root ${enabled ? 'checked' : ''}" id="${dynamicStylePrefix}button-base-root">
<input class="${dynamicStylePrefix}input-toggle" />
<span class="${dynamicStylePrefix}thumb"></span>
<span class="${dynamicStylePrefix}ripple"></span>
</span>
<span class="${dynamicStylePrefix}track ${enabled ? 'checked' : ''}" id="${dynamicStylePrefix}track"></span>
</span>
<span id="${dynamicStylePrefix}toggle-label">Automatically pass</span>
</div>
<div id="${dynamicStylePrefix}notification">This profile contains an exclusion.</div>
<div class="${dynamicStylePrefix}icon-button" id="${dynamicStylePrefix}icon-button">
<svg><path d="M10 18h4v-2h-4zM3 6v2h18V6zm3 7h12v-2H6z" /></svg>
</div>
<div class="${dynamicStylePrefix}icon-button" id="${dynamicStylePrefix}icon-button-debug">
<svg viewBox="0 0 24 24"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5s-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20zm-6 8h-4v-2h4zm0-4h-4v-2h4z"></path></svg>
</div>
</div>
<div class="${dynamicStylePrefix}filter-container" id="${dynamicStylePrefix}filter-container">
<p>
Profiles containing any of these exclusions will be passed. All exclusions are case-insensitive.
If you are also using the <a href="https://greasyfork.org/en/scripts/504158-okcupid-more-effective-pass">more effective pass</a>
script then the profiles will instead be blocked.
</p>
<div class="${dynamicStylePrefix}filter-list">
${buildFilterHTML()}
</div>
</div>
</div>
`;
detailsTopElement.insertAdjacentElement('afterend', filterContainer);
const toggleElement = document.getElementById(`${dynamicStylePrefix}switch-root`);
toggleElement.addEventListener('click', toggleFeature);
const showFiltersButton = document.getElementById(`${dynamicStylePrefix}icon-button`);
const showDebugButton = document.getElementById(`${dynamicStylePrefix}icon-button-debug`);
const filterContainerElement = document.getElementById(`${dynamicStylePrefix}filter-container`);
showFiltersButton.addEventListener('click', () => {
const display = filterContainerElement.style.display === 'none' || filterContainerElement.style.display === '' ? 'flex' : 'none';
filterContainerElement.style.display = display;
});
showDebugButton.addEventListener('click', () => {
debugContainer.classList.toggle(`${dynamicStylePrefix}hidden`);
});
[...document.querySelectorAll(`div.${dynamicStylePrefix}filter-item`)].forEach(bindFilterItem);
// Bind the existing list items that were loaded from local storage.
[...document.querySelectorAll(`ul.${dynamicStylePrefix}exclusion-list li`)].forEach(bindFilterListItem);
checkProfileLoop();
}
const styleString = `
div.${dynamicStylePrefix}control-container {
display: flex;
alignItems: center;
}
span.${dynamicStylePrefix}switch-root {
display: inline-flex;
width: 58px;
height: 38px;
overflow: hidden;
padding: 12px;
box-sizing: border-box;
position: relative;
flex-shrink: 0;
z-index: 0;
vertical-align: middle;
}
span.${dynamicStylePrefix}button-base-root {
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
background-color: transparent;
outline: 0px;
border: 0px;
margin: 0px;
cursor: pointer;
user-select: none;
vertical-align: middle;
appearance: none;
text-decoration: none;
padding: 9px;
border-radius: 50%;
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
color: rgb(255, 255, 255);
transition: left 150ms cubic-bezier(0.4, 0, 0.2, 1), transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
}
span.${dynamicStylePrefix}button-base-root.checked {
color: rgb(25, 118, 210);
transform: translateX(20px);
}
span.${dynamicStylePrefix}button-base-root:hover {
background-color: rgba(0, 0, 0, 0.04);
}
input.${dynamicStylePrefix}input-toggle {
left: -100%;
width: 300%;
cursor: inherit;
position: absolute;
opacity: 0;
width: 100%;
height: 100%;
top: 0;
left: 0;
margin: 0;
padding: 0;
z-index: 1;
}
span.${dynamicStylePrefix}thumb {
box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 1px -1px, rgba(0, 0, 0, 0.14) 0px 1px 1px 0px, rgba(0, 0, 0, 0.12) 0px 1px 3px 0px;
background-color: currentcolor;
width: 20px;
height: 20px;
border-radius: 50%;
}
span.${dynamicStylePrefix}ripple {
overflow: hidden;
pointer-events: none;
position: absolute;
z-index: 0;
inset: 0px;
border-radius: inherit;
}
span.${dynamicStylePrefix}track {
height: 100%;
width: 100%;
border-radius: 7px;
z-index: -1;
transition: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1), background-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
background-color: rgb(0, 0, 0);
opacity: 0.38;
}
span.${dynamicStylePrefix}track.checked {
background-color: rgb(25, 118, 210);
}
div.${dynamicStylePrefix}icon-button {
width: 32px;
height: 32px;
border: 1px solid silver;
cursor: pointer;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
}
div.${dynamicStylePrefix}icon-button:hover {
background-color: rgb(246 246 246);
}
div.${dynamicStylePrefix}icon-button:hover svg {
fill: rgb(25, 118, 210);
}
div.${dynamicStylePrefix}icon-button svg {
width: 24px;
height: 24px;
}
div.${dynamicStylePrefix}filter-container {
display: none;
flex-direction: column;
gap: 1em;
border-top: 1px solid black;
padding: 1em;
margin-top: 1em;
}
div.${dynamicStylePrefix}filter-list {
display: flex;
flex-basis: auto;
justify-content: center;
gap: 1em;
flex-wrap: wrap;
}
div.${dynamicStylePrefix}filter-item {
display: flex;
flex-direction: column;
gap: 0.5em;
border: 1px solid grey;
border-radius: 4px;
width: 260px;
height: 200px;
padding: 3px;
}
div.${dynamicStylePrefix}filter-addition {
display: flex;
gap: 2px;
align-items: center;
border-bottom: 1px dashed black;
}
div.${dynamicStylePrefix}filter-addition svg {
width: 32px;
height: 32px;
}
div.${dynamicStylePrefix}filter-addition input {
width: 100%;
}
ul.${dynamicStylePrefix}exclusion-list {
list-style: none;
overflow: scroll;
}
ul.${dynamicStylePrefix}exclusion-list li {
cursor: pointer;
}
ul.${dynamicStylePrefix}exclusion-list li:hover {
text-decoration: line-through;
background-color: rgb(246 246 246);
}
div#${dynamicStylePrefix}notification {
display: none;
flex-grow: 1;
font-style: italic;
color: red;
}
li.${dynamicStylePrefix}exclusion.found {
color: red;
}
.${dynamicStylePrefix}hidden {
display: none !important;
}
div.${dynamicStylePrefix}debug-container {
display: flex;
flex-direction: column;
position: fixed;
bottom: 1em;
left: 1em;
width: 300px;
}
div.${dynamicStylePrefix}debug-container .dt-section-content {
background-color: rgb(255 255 255 / 70%);
display: flex;
flex-direction: column;
}
div#${dynamicStylePrefix}icon-button-debug {
margin-left: 1em;
}
`;
(function() {
'use strict';
const sheet = new CSSStyleSheet();
sheet.replaceSync(styleString);
console.debug(`[user scripts] Adding ${sheet.rules.length} new CSS rules.`);
document.adoptedStyleSheets.push(sheet);
let detailsTopElement = null;
setInterval(() => {
if (detailsTopElement === null || !document.body.contains(detailsTopElement)) {
detailsTopElement = document.querySelector('div.desktop-dt-top');
// The details container now exists. Create our custom elements.
if (detailsTopElement !== null) {
initialize(detailsTopElement);
}
}
}, 100);
})();