您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Hide old comments, highlight only parent text if it has newer children
当前为
- // ==UserScript==
- // @name Hide-Older-Comments
- // @namespace https://orbitar.space/
- // @version 1.8.0
- // @description Hide old comments, highlight only parent text if it has newer children
- // @match https://*.orbitar.space/*
- // @match https://*.orbitar.local/*
- // @grant none
- // @license MIT
- // ==/UserScript==
- (function () {
- 'use strict';
- console.log("✅ Comment filtering script is running...");
- let observer; // Global observer to allow disconnecting on URL change
- function isPostPage() {
- return /^https:\/\/([^\.]*\.)?orbitar\.space\/(p\d+|s\/[^\/]+\/p\d+)([\?].*|[\#].*)?$/.test(window.location.href);
- }
- function observeForLinksSection() {
- if (observer) {
- observer.disconnect(); // Disconnect previous observer if it exists
- }
- observer = new MutationObserver(() => {
- let linksSection = document.querySelector('[class^="PostPage_postButtons__"]');
- if (linksSection && !document.getElementById("comment-filter-container")) {
- createUI(linksSection);
- }
- });
- observer.observe(document.body, { childList: true, subtree: true });
- }
- function createUI(linksSection) {
- if (document.getElementById("comment-filter-container")) return;
- let container = document.createElement("span");
- container.id = "comment-filter-container";
- //container.style.marginLeft = "10px";
- let divider = document.createTextNode(" • ");
- container.appendChild(divider);
- let showFilterLink = document.createElement("a");
- showFilterLink.href = "#fr";
- showFilterLink.innerText = "фильтровать по дате";
- showFilterLink.onclick = (event) => {
- event.preventDefault();
- filterUI.style.display = "inline";
- showFilterLink.style.display = "none";
- };
- let filterUI = document.createElement("span");
- filterUI.style.display = "none";
- filterUI.style.marginLeft = "10px";
- let dateInput = document.createElement("input");
- dateInput.type = "datetime-local";
- dateInput.id = "comment-filter-date";
- dateInput.style.marginRight = "5px";
- let filterLink = document.createElement("a");
- filterLink.href = "#fr";
- filterLink.innerText = "фильтровать";
- filterLink.onclick = (event) => {
- event.preventDefault();
- filterComments();
- };
- let clearLink = document.createElement("a");
- clearLink.href = "#fr";
- clearLink.innerText = "очистить";
- clearLink.style.marginLeft = "10px";
- clearLink.onclick = (event) => {
- event.preventDefault();
- clearFilter();
- };
- let quickLinks = document.createElement("div");
- quickLinks.style.marginTop = "10px";
- ["3 часа", "12 часов", "сутки", "3 дня", "неделя"].forEach((text, index) => {
- let timeAdjustLink = document.createElement("a");
- timeAdjustLink.href = "#ft";
- timeAdjustLink.innerText = text;
- timeAdjustLink.style.marginRight = "5px";
- timeAdjustLink.onclick = (event) => {
- event.preventDefault();
- adjustDate(index);
- };
- quickLinks.appendChild(timeAdjustLink);
- if (index < 4) quickLinks.appendChild(document.createTextNode(" | "));
- });
- ["gray", "pink", "blue", "skyblue", "salmon" ].forEach((color, index) => {
- quickLinks.appendChild(document.createTextNode(" | ")); // Add divider
- let colorLink = document.createElement("a");
- colorLink.href = "#fc";
- colorLink.innerText = color;
- colorLink.style.marginRight = "5px";
- colorLink.onclick = (event) => {
- event.preventDefault();
- changeParentCommentBgColor("light" + color);
- };
- quickLinks.appendChild(colorLink);
- });
- filterUI.appendChild(dateInput);
- filterUI.appendChild(filterLink);
- filterUI.appendChild(clearLink);
- filterUI.appendChild(quickLinks);
- container.appendChild(showFilterLink);
- container.appendChild(filterUI);
- linksSection.appendChild(container);
- }
- let parentCommentBgColor = 'lightpink'; // Default background color
- function changeParentCommentBgColor(color) {
- parentCommentBgColor = color;
- let comments = document.querySelectorAll('.comment');
- comments.forEach(comment => {
- let commentTextContainer = comment.querySelector('[class^="CommentComponent_content__"]');
- if (commentTextContainer &&
- (commentTextContainer.style.backgroundColor === 'lightgray' ||
- commentTextContainer.style.backgroundColor === 'lightpink' ||
- commentTextContainer.style.backgroundColor === 'lightblue' ||
- commentTextContainer.style.backgroundColor === 'lightskyblue' ||
- commentTextContainer.style.backgroundColor === 'lightsalmon')) {
- commentTextContainer.style.backgroundColor = color;
- }
- });
- }
- function adjustDate(option) {
- let dateInput = document.getElementById("comment-filter-date");
- if (!dateInput) return;
- let currentDate = new Date();
- switch (option) {
- case 0:
- currentDate.setHours(currentDate.getHours() - 3);
- break;
- case 1:
- currentDate.setHours(currentDate.getHours() - 12);
- break;
- case 2:
- currentDate.setDate(currentDate.getDate() - 1);
- break;
- case 3:
- currentDate.setDate(currentDate.getDate() - 3);
- break;
- case 4:
- currentDate.setDate(currentDate.getDate() - 7);
- break;
- }
- let localISOTime = new Date(currentDate.getTime() - currentDate.getTimezoneOffset() * 60000)
- .toISOString()
- .slice(0, 16);
- dateInput.value = localISOTime;
- }
- function filterComments() {
- let dateInput = document.getElementById("comment-filter-date");
- if (!dateInput) return;
- let selectedDate = new Date(dateInput.value);
- if (isNaN(selectedDate)) {
- console.error("Invalid date selected.");
- return;
- }
- console.log("Filtering comments older than:", selectedDate.toString());
- let comments = document.querySelectorAll('.comment');
- let commentMap = new Map();
- comments.forEach(comment => {
- let dateElement = findDateElement(comment);
- if (!dateElement) return;
- let commentDateText = dateElement.innerText.trim();
- let commentDate = parseCommentDate(commentDateText);
- let commentId = comment.dataset.commentId;
- if (isNaN(commentDate)) return;
- commentMap.set(commentId, { comment, commentDate, hasNewerChild: false });
- });
- comments.forEach(comment => {
- let commentId = comment.dataset.commentId;
- let commentData = commentMap.get(commentId);
- if (!commentData) return;
- let { commentDate } = commentData;
- let childComments = [...comment.querySelectorAll('.comment')];
- let hasNewerChild = childComments.some(child => {
- let childId = child.dataset.commentId;
- return commentMap.has(childId) && commentMap.get(childId).commentDate >= selectedDate;
- });
- if (hasNewerChild) {
- commentData.hasNewerChild = true;
- }
- });
- comments.forEach(comment => {
- let commentId = comment.dataset.commentId;
- let commentData = commentMap.get(commentId);
- if (!commentData) return;
- let { commentDate, hasNewerChild } = commentData;
- let commentTextContainer = comment.querySelector('[class^="CommentComponent_content__"]');
- if (!commentTextContainer) return;
- if (commentDate >= selectedDate) {
- comment.style.display = "";
- commentTextContainer.style.backgroundColor = "";
- } else if (hasNewerChild) {
- comment.style.display = "";
- commentTextContainer.style.padding = "5px";
- commentTextContainer.style.backgroundColor = parentCommentBgColor;
- } else {
- comment.style.display = "none";
- }
- });
- }
- function clearFilter() {
- let comments = document.querySelectorAll('.comment');
- comments.forEach(comment => {
- comment.style.display = "";
- let commentTextContainer = comment.querySelector('[class^="CommentComponent_content__"]');
- if (commentTextContainer) {
- commentTextContainer.style.backgroundColor = "";
- }
- });
- console.log("Filter cleared, all comments visible.");
- }
- function findDateElement(comment) {
- let signature = comment.querySelector('[class^="SignatureComponent_signature__"]');
- if (!signature) return null;
- let dateLinks = signature.querySelectorAll("a");
- return dateLinks.length >= 2 ? dateLinks[1] : null;
- }
- function parseCommentDate(dateText) {
- let months = {
- "января": "January", "февраля": "February", "марта": "March",
- "апреля": "April", "мая": "May", "июня": "June",
- "июля": "July", "августа": "August", "сентября": "September",
- "октября": "October", "ноября": "November", "декабря": "December"
- };
- // Handle "вчера в 12:34" format
- if (dateText.startsWith("вчера в")) {
- let match = dateText.match(/вчера в (\d{1,2}):(\d{2})/);
- if (match) {
- let yesterday = new Date();
- yesterday.setDate(yesterday.getDate() - 1);
- yesterday.setHours(parseInt(match[1], 10), parseInt(match[2], 10), 0, 0);
- return yesterday;
- }
- }
- // Handle "сегодня в 12:34" format
- if (dateText.startsWith("сегодня в")) {
- let match = dateText.match(/сегодня в (\d{1,2}):(\d{2})/);
- if (match) {
- let today = new Date();
- today.setHours(parseInt(match[1], 10), parseInt(match[2], 10), 0, 0);
- return today;
- }
- }
- // Handle Old Format: "9 февраля в 12:12"
- let oldFormatMatch = dateText.match(/(\d{1,2})\s([а-яА-Я]+)\sв\s(\d{1,2}):(\d{2})/);
- if (oldFormatMatch) {
- let [_, day, monthName, hour, minute] = oldFormatMatch;
- let month = months[monthName];
- if (!month) return NaN;
- let currentYear = new Date().getFullYear();
- return new Date(`${day} ${month} ${currentYear} ${hour}:${minute}`);
- }
- // Handle New Format: "27.08.2024 12:17"
- let newFormatMatch = dateText.match(/(\d{2})\.(\d{2})\.(\d{4})\s(\d{2}):(\d{2})/);
- if (newFormatMatch) {
- let [_, day, month, year, hour, minute] = newFormatMatch;
- return new Date(`${year}-${month}-${day}T${hour}:${minute}:00`);
- }
- return NaN; // If no format matched, return NaN
- }
- function runScript() {
- if (isPostPage()) {
- // Remove existing UI container if present to avoid duplicates
- let existingContainer = document.getElementById("comment-filter-container");
- if (existingContainer) {
- existingContainer.remove();
- }
- // Clear any applied filters before reinitializing
- clearFilter();
- observeForLinksSection();
- }
- }
- // Run the script initially if on a post page
- runScript();
- // Listen for URL changes via popstate (back/forward navigation)
- window.addEventListener('popstate', runScript);
- // Listen for hash changes if navigation uses URL fragments
- window.addEventListener('hashchange', runScript);
- // Override pushState to detect URL changes
- const originalPushState = history.pushState;
- history.pushState = function () {
- originalPushState.apply(this, arguments);
- runScript();
- };
- // Override replaceState similarly
- const originalReplaceState = history.replaceState;
- history.replaceState = function () {
- originalReplaceState.apply(this, arguments);
- runScript();
- };
- })();