// ==UserScript==
// @name Hide-Older-Comments
// @namespace https://orbitar.space/
// @version 1.6
// @description Hide old comments
// @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 = 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.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();
};
})();