Greasy Fork is available in English.
Hides uncommented/unliked activity on Anilist's activity feeds
当前为
// ==UserScript==
// @name Anilist: Hide Uncommented Activity
// @namespace https://github.com/SeyTi01/
// @version 1.5
// @description Hides uncommented/unliked activity on Anilist's activity feeds
// @author SeyTi01
// @match https://anilist.co/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const config = {
targetLoadCount: 2, // Number of activities to show per click on the "Load More" button
remove: {
uncommented: true, // Remove activities that have no comments
unliked: false // Remove activities that have no likes
},
runOn: {
home: true, // Run the script on the home feed
profile: true, // Run the script on user profile feeds
social: true // Run the script on social feeds
}
};
const SELECTORS = {
button: 'div.load-more',
activity: 'div.activity-entry',
replies: 'div.action.replies',
likes: 'div.action.likes'
};
const URLS = {
home: 'https://anilist.co/home',
profile: 'https://anilist.co/user/*/',
social: 'https://anilist.co/*/social'
};
let currentLoadCount = 0;
let userPressedButton = true;
let loadMoreButton;
let cancelButton;
initializeObserver();
function initializeObserver() {
if (!validateConfig(config)) {
console.error('Script disabled due to configuration errors.');
} else {
const observer = new MutationObserver(observeMutations);
observer.observe(document.body, { childList: true, subtree: true });
}
}
function observeMutations(mutations) {
for (const mutation of mutations) {
if (mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach(handleAddedNode);
}
}
if (currentLoadCount < config.targetLoadCount && userPressedButton) {
clickLoadMoreButton();
} else {
resetState();
}
}
function handleAddedNode(node) {
if (!(node instanceof HTMLElement)) {
return;
}
if (node.matches(SELECTORS.activity)) {
if (!removeEntry(node)) {
currentLoadCount++;
}
} else if (node.matches(SELECTORS.button)) {
handleLoadMoreButton(node);
}
}
function removeEntry(node) {
if (isAllowedUrl()) {
const repliesDiv = node.querySelector(SELECTORS.replies);
const likesDiv = node.querySelector(SELECTORS.likes);
if ((config.remove.uncommented && !hasCountSpan(repliesDiv)) || (config.remove.unliked && !hasCountSpan(likesDiv))) {
node.remove();
return true;
}
}
return false;
}
function handleLoadMoreButton(button) {
loadMoreButton = button;
loadMoreButton.addEventListener('click', function() {
userPressedButton = true;
simulateDomEvents();
showCancelButton();
});
}
function showCancelButton() {
if (!cancelButton) {
createCancelButton();
} else {
cancelButton.style.display = 'block';
}
}
function hasCountSpan(node) {
return node?.querySelector('span.count');
}
function isAllowedUrl() {
const currentUrl = window.location.href;
return (config.runOn.home && new RegExp(URLS.home.replace('*', '.*')).test(currentUrl))
|| (config.runOn.profile && new RegExp(URLS.profile.replace('*', '.*')).test(currentUrl))
|| (config.runOn.social && new RegExp(URLS.social.replace('*', '.*')).test(currentUrl));
}
function simulateDomEvents() {
const domEvent = new Event('scroll', {bubbles: true});
const intervalId = setInterval(function() {
if (userPressedButton) {
window.dispatchEvent(domEvent);
} else {
clearInterval(intervalId);
}
}, 100);
}
function clickLoadMoreButton() {
if (loadMoreButton) {
loadMoreButton.click();
loadMoreButton = null;
}
}
function resetState() {
currentLoadCount = 0;
userPressedButton = false;
if (cancelButton) {
cancelButton.style.display = 'none';
}
}
function createCancelButton() {
const buttonStyles = `
position: fixed;
bottom: 10px;
right: 10px;
z-index: 9999;
line-height: 1.3;
background-color: rgb(var(--color-background-blue-dark));
color: rgb(var(--color-text-bright));
font: 1.6rem 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
-webkit-font-smoothing: antialiased;
box-sizing: border-box;
`;
cancelButton = Object.assign(document.createElement('button'), {
textContent: 'Cancel',
className: 'cancel-button',
style: `--button-color: rgb(var(--color-blue)); ${buttonStyles}`,
onclick: () => {
userPressedButton = false;
cancelButton.style.display = 'none';
},
});
document.body.appendChild(cancelButton);
}
function validateConfig(config) {
const errors = [
typeof config.remove.uncommented !== 'boolean' && 'removeUncommented must be a boolean',
typeof config.remove.unliked !== 'boolean' && 'removeUnliked must be a boolean',
(!Number.isInteger(config.targetLoadCount) || config.targetLoadCount < 1) && 'targetLoadCount must be a positive non-zero integer',
typeof config.runOn.home !== 'boolean' && 'runOnHome must be a boolean',
typeof config.runOn.profile !== 'boolean' && 'runOnProfile must be a boolean',
typeof config.runOn.social !== 'boolean' && 'runOnSocial must be a boolean',
].filter(Boolean);
if (errors.length > 0) {
console.error('Script configuration errors:');
errors.forEach(error => console.error(error));
return false;
}
return true;
}
})();