Ignore topics and forums, and other topic list tweaks
当前为
// ==UserScript==
// @name Cook'd and Bomb'd Ignore Topics
// @description Ignore topics and forums, and other topic list tweaks
// @namespace https://github.com/insin/greasemonkey/
// @version 6
// @match https://www.cookdandbombd.co.uk/forums/index.php/board*
// @match https://www.cookdandbombd.co.uk/forums/index.php?action=unread*
// @grant GM.registerMenuCommand
// ==/UserScript==
const IGNORED_TOPICS_STORAGE = 'cab_ignoredTopics'
const IGNORED_FORUMS_STORAGE = 'cab_ignoredForums'
// Logged out: index.php/topic,12345
// Logged in: index.php?topic=12345
const TOPIC_ID_RE = /index.php[?/]topic[,=](\d+)/
// Only in Recent Unread Topics - must be logged in
const FORUM_ID_RE = /index.php\/board,(\d+)/
let topics = []
let ignoredTopicIds
let ignoredForumIds
let config = {
hideRecentUnreadTopicsPageNumbers: true,
// Set this to false if you're done hiding forums in Recent Unread Topics
showIgnoreForumControl: true,
showIgnoredTopics: false,
topicLinksNewPost: true,
}
function loadIgnoreConfig() {
let ignoredTopicsJson = localStorage[IGNORED_TOPICS_STORAGE]
let ignoredForumsJson = localStorage[IGNORED_FORUMS_STORAGE]
ignoredTopicIds = ignoredTopicsJson ? JSON.parse(ignoredTopicsJson) : []
ignoredForumIds = ignoredForumsJson ? JSON.parse(ignoredForumsJson) : []
}
function toggleIgnoreTopic(id, topic) {
if (!ignoredTopicIds.includes(id)) {
ignoredTopicIds.unshift(id)
}
else {
let index = ignoredTopicIds.indexOf(id)
ignoredTopicIds.splice(index, 1)
}
localStorage[IGNORED_TOPICS_STORAGE] = JSON.stringify(ignoredTopicIds)
topic.updateClassNames()
}
function toggleIgnoreForum(id) {
if (!ignoredForumIds.includes(id)) {
ignoredForumIds.unshift(id)
}
else {
let index = ignoredForumIds.indexOf(id)
ignoredForumIds.splice(index, 1)
}
localStorage[IGNORED_FORUMS_STORAGE] = JSON.stringify(ignoredForumIds)
topics.forEach(topic => topic.updateClassNames())
}
function toggleShowIgnoredTopics(showIgnoredTopics) {
config.showIgnoredTopics = showIgnoredTopics
topics.forEach(topic => topic.updateClassNames())
}
function addStyle(css) {
let $style = document.createElement('style')
$style.appendChild(document.createTextNode(css))
document.querySelector('head').appendChild($style)
}
function ForumPage() {
let isRecentUnreadTopicsPage = location.search.includes('action=unread')
addStyle(`
.cab_ignoreControl {
visibility: hidden;
}
.cab_ignored {
display: none;
}
.cab_ignored.cab_show {
display: table-row;
}
.cab_ignored.cab_show td {
background-color: #fdd !important;
}
tr:hover .cab_ignoreControl {
visibility: visible;
}
.cab_ignoredForum .cab_ignoreTopic {
display: none;
}
.cab_ignoredTopic .cab_ignoreForum {
display: none;
}
.cab_ignoredTopic.cab_ignoredForum .cab_ignoreForum {
display: inline;
}
${isRecentUnreadTopicsPage && config.hideRecentUnreadTopicsPageNumbers ? 'td.subject small { display: none; }' : ''}
`)
function Topic($topicRow) {
let $topicLink = $topicRow.querySelector('td.subject a')
// Only in Recent Unread Topics
let $forumLink = $topicRow.querySelector('td.subject p > em > a')
let $lastPostLink = $topicRow.querySelector('td.lastpost a')
let topicIdMatch = TOPIC_ID_RE.exec($lastPostLink.href)
if (!topicIdMatch) {
return null
}
let topicId = topicIdMatch[1]
let forumId = null
if ($forumLink) {
let forumIdMatch = FORUM_ID_RE.exec($forumLink.href)
if (forumIdMatch) {
forumId = forumIdMatch[1]
}
}
let api = {
updateClassNames() {
let isTopicIgnored = ignoredTopicIds.includes(topicId)
let isForumIgnored = forumId ? ignoredForumIds.includes(forumId) : false
$topicRow.classList.toggle('cab_ignoredTopic', isTopicIgnored)
$topicRow.classList.toggle('cab_ignoredForum', isForumIgnored)
$topicRow.classList.toggle('cab_ignored', isTopicIgnored || isForumIgnored)
$topicRow.classList.toggle('cab_show', config.showIgnoredTopics && (isTopicIgnored || isForumIgnored))
}
}
$lastPostLink.insertAdjacentHTML('afterend', `
<a href="#" class="cab_ignoreControl cab_ignoreTopic">
<img src="/forums/Themes/default/images/icons/delete.gif" alt="Ignore topic" title="Ignore topic" width="14" height="14">
</a>
`)
$topicRow.querySelector('a.cab_ignoreTopic').addEventListener('click', (e) => {
e.preventDefault()
toggleIgnoreTopic(topicId, api)
})
if (config.showIgnoreForumControl && forumId) {
$forumLink.parentElement.insertAdjacentHTML('afterend', `
<a href="#" class="cab_ignoreControl cab_ignoreForum">
<img src="/forums/Themes/default/images/icons/delete.gif" alt="Ignore forum" title="Ignore forum" width="14" height="14">
</a>
`)
$topicRow.querySelector('a.cab_ignoreForum').addEventListener('click', (e) => {
e.preventDefault()
toggleIgnoreForum(forumId)
})
}
if (config.topicLinksNewPost) {
let $newPostLink = $topicRow.querySelector('a[id^=newicon]')
if ($newPostLink) {
$topicLink.href = $newPostLink.href
}
}
return api
}
/**
* Add ignore controls to a topic and hide it if it's being ignored.
*/
function processTopicRow($topicRow) {
let topic = Topic($topicRow)
if (topic == null) {
return
}
topics.push(topic)
topic.updateClassNames()
}
Array.from(document.querySelectorAll('#main_content_section table.table_grid tbody tr'), processTopicRow)
}
// Already-processed pages seem to be getting cached on back navigation... sometimes
if (!document.querySelector('a.cab_ignoreTopic')) {
if (typeof GM != 'undefined') {
loadIgnoreConfig()
ForumPage()
GM.registerMenuCommand('Toggle ignored topic display', () => {
toggleShowIgnoredTopics(!config.showIgnoredTopics)
})
}
else {
chrome.storage.local.get((storedConfig) => {
Object.assign(config, storedConfig)
loadIgnoreConfig()
ForumPage()
})
chrome.storage.onChanged.addListener((changes) => {
if ('showIgnoredTopics' in changes) {
toggleShowIgnoredTopics(changes['showIgnoredTopics'].newValue)
}
})
}
}