返回首頁 

Greasy Fork is available in English.

[AO3] Mute Selectively

Allow more flexible muting without resorting to a site skin


安装此脚本?
// ==UserScript==// @name         [AO3] Mute Selectively// @namespace    http://tampermonkey.net/// @version      1.1// @description  Allow more flexible muting without resorting to a site skin// @license      MIT// @match        *://*.archiveofourown.org/*// @grant        GM.getValue// @grant        GM.setValue// @grant        GM.deleteValue// ==/UserScript==// Many thanks to a certain other nonnieconst standardSize = {titleFont: 30,headerFont: 20,tabFont: 19,refreshFont: 15,actionFont: 14,menuWidth: 600,menuHeight: 600}const mobileSize = {titleFont: 24,headerFont: 18,tabFont: 14,refreshFont: 13,actionFont: 12,menuWidth: 390,menuHeight: 500}var fontSizing = {}var commentMute = []function getMenuRules() {var rules = {};rules['.AO3-MS-toggle'] = {'background-color': 'lightgray','padding': '1px 4px','display': 'inline-block','border-style': 'solid','border': 'black',};rules['.AO3-MS-toggle a'] = {'text-decoration': 'none','border': 'black','color': 'black',};rules['.AO3-MS-usermenu'] = {'position': 'absolute','display': 'inline-block','background-color': 'lightgray','margin': '0px 0px 0px 4px','border-style': 'solid','border-color': 'black','z-index': '100',};rules['.AO3-MS-usermenu-item'] = {'display': 'block','position': 'relative','padding': '3px 5px 2px 5px',};rules['.AO3-MS-usermenu-item-selected'] = {'background-color': '#f1f1f1',};rules['.AO3-MS-usermenu-item a'] = {'color': 'black','text-decoration': 'none','display': 'inline-block','width': '100%','border': 'black',};rules['.AO3-MS-usermenu-item:hover'] = {'background-color': '#ddd',};rules['.AO3-MS-muted'] = {'display': 'none !important',};rules['.AO3-MS-collapseBlurb'] = {'padding': '20px',}rules['.AO3-MS-mutePhrase'] = {'margin': '0px 4px',}rules['#AO3-MS-settings'] = {'background-color': 'white','color': 'black','display': 'none','flex-flow': 'column','position': 'fixed','top': '50%','left': '50%','width': fontSizing.menuWidth + 'px','height': fontSizing.menuHeight + 'px','margin': '-' + (fontSizing.menuHeight / 2 ) + 'px -' + (fontSizing.menuWidth / 2) + 'px','box-shadow': '10px 10px 20px rgba(0, 0, 0, 0.5)','z-index': '100','border': '1px solid black','font-size': fontSizing.actionFont + 'px',};rules['#AO3-MS-title'] = {'margin': '10px 0px 0px','text-align': 'center','font-size': fontSizing.titleFont + 'px',};rules['#AO3-MS-closeMenu'] = {'position': 'absolute','top': '0px','right': '0px','margin': '5px','width': (fontSizing.actionFont + 10) + 'px','height': (fontSizing.actionFont + 10) + 'px','font-size': fontSizing.actionFont + 'px',};rules['#AO3-MS-tablist'] = {'margin': '10px 0px','text-align': 'center','border-bottom': '1px solid black',};rules['.AO3-MS-tab'] = {'display': 'inline-block','padding': '5px','height': fontSizing.tabFont + 'px','background': 'lightgray','color': 'black','border': '1px solid black','box-size': 'border-box',};rules['#AO3-MS-viewport'] = {'display': 'flex','flex-flow': 'column','flex': '1 1 auto','bottom': '0px',};rules['.AO3-MS-view'] = {'display': 'none',};rules['.AO3-MS-active.AO3-MS-view'] = {'display': 'flex','flex-flow': 'column','height': '100%','bottom': '0px',};rules['.AO3-MS-active.AO3-MS-tab'] = {'background': '#FFF',};rules['.AO3-MS-header'] = {'position': 'inline-block','left': '0px','right': '0px','top': '0px','margin': '5px 10px','font-size': fontSizing.headerFont + 'px','text-align': 'center',};rules['.AO3-MS-list'] = {'flex': '1 1 auto','height': '100px','overflow-y': 'scroll',};rules['.AO3-MS-refresh'] = {'position': 'inline-block','font-size': fontSizing.refreshFont + 'px','margin': '0px 10px','text-align': 'center',};rules['#AO3-MS-checkboxes'] = {'flex': '1 1 auto','height': '100px','padding': '10px','overflow-y': 'scroll',};rules['.AO3-MS-padding'] = {'display': 'flex','flex-flow': 'column','flex': '1 1 auto','padding': '10px',};rules['.AO3-MS-textarea'] = {'position': 'inline-block','left': '0px','width': '100%','display': 'flex','flex-flow': 'column','padding': '10px','height': '100%','resize': 'none','box-sizing': 'border-box',};rules['#AO3-MS-viewport input[type="button"]'] = {'display': 'inline-block','flex': '0 1 auto','bottom': '0px','margin': '5px 0px 0px 0px','font-size': fontSizing.refreshFont + 'px','box-shadow': '2px 1px 2px gray',};rules['#AO3-MS-viewport input[type="button"]:active'] = {'box-shadow': '0 0 0 white',};rules['#AO3-MS-css-reset,#AO3-MS-css-save'] = {'width': '100%',};rules['#AO3-MS-import-button'] = {'width': '100%',};rules['.AO3-MS-action'] = {'font-size': fontSizing.actionFont + 'px','margin-left': '5px','color': 'blue !important',};rules['.AO3-MS-action:before'] = {'content': '"("',};rules['.AO3-MS-action:after'] = {'content': '")"',};rules['.AO3-MS-item'] = {'padding': '10px',};rules['.AO3-MS-item a'] = {'border': 'black',};rules['.AO3-MS-filter:before'] = {'content': '\'"\'',};rules['.AO3-MS-filter:after'] = {'content': '\'"\'',};return rules;}function addMuteRules(muteByStyle) {var rules = {};rules[muteByStyle] = {'display': 'none !important',};return rules;}function makeStyleCode(rules) {var contents = "";for (var descriptor in rules) {if (! rules.hasOwnProperty(descriptor)) continue;contents += descriptor + " {\n";for (var property in rules[descriptor]) {if (! rules[descriptor].hasOwnProperty(property)) continue;contents += "    " + property + ": " + rules[descriptor][property] + ";\n";}contents += "}\n";}return contents;}function makeStyleSheet(str,identifier) {if (document.querySelectorAll('#' + identifier).length) {document.querySelector('#' + identifier).remove()}var sheet = document.createElement('style');sheet.innerHTML = str;sheet.id = identifierdocument.body.appendChild(sheet);}async function changeReason(identifier,index,reason) {let temp = await GM.getValue(identifier)temp[index][3] = reasonawait GM.setValue(identifier,temp)let affectedReasons = document.querySelectorAll('.AO3-MS-collapsed-' + temp[index][0] + ' .AO3-MS-mutePhraseReason')for (const r of affectedReasons) {if (!reason) {r.innerText = ''} else {r.innerText = ' (' + reason + ')'}}var refresh = refreshFilterList(identifier)refresh();}function makeBlurbFilterItem(identifier,index,value,refresh) {var element = document.createElement("div");element.className = "AO3-MS-item";var filter = document.createElement("span");filter.className = "AO3-MS-filter";var aTitle = document.createElement('a');aTitle.href = 'https://archiveofourown.org/works/' + value[0].split('work-')[1]aTitle.appendChild(document.createTextNode(value[1]));element.appendChild(aTitle)element.appendChild(document.createTextNode(' by '))var names = value[2].split(', ')for (let i = 0; i < names.length; i++) {let aName = document.createElement('a')aName.href = 'https://archiveofourown.org/users/' + names[i]aName.appendChild(document.createTextNode(names[i]))element.appendChild(aName)if (i < names.length - 1) {element.appendChild(document.createTextNode(', '))}}var remove = makeActionLink("unmute", async function() {await delVal(identifier,value[0])await refresh();});element.appendChild(remove)var reason = document.createTextNode(' Reason: ' + value[3])element.appendChild(reason)var editReason = makeActionLink('edit reason', async function () {var newReason = prompt("Reason for muting " + value[1] + ":", value[3]);if (newReason === null) {return null;}await changeReason(identifier,index,newReason)await refresh();});element.appendChild(editReason)return element;}function makeUserFilterItem(identifier, index, value, refresh) {var element = document.createElement("div");element.className = "AO3-MS-item";var filter = document.createElement("span");filter.className = "AO3-MS-filter";var id = document.createTextNode('(UserID ' + value[0].split('user-')[1] + ') ')var aName = document.createElement('a');aName.href = 'https://archiveofourown.org/users/' + value[2]aName.appendChild(document.createTextNode(value[2]));var remove = document.createElement('a')remove.className = "AO3-MS-action";remove.href = "javascript:void(0)";remove.appendChild(document.createTextNode('edit'));remove.onclick = async function() {await toggleUser(element,remove,value[0],value[2])};var reason = document.createTextNode(' Reason: ' + value[3])var editReason = makeActionLink('edit reason', async function () {var newReason = prompt("Reason for muting " + value[2] + ":", value[3]);if (newReason !== null) {return null;}await changeReason(identifier,index,newReason)await refresh();});element.appendChild(id)element.appendChild(aName)element.appendChild(remove)element.appendChild(reason)element.appendChild(editReason)return element;}function refreshFilterList(identifier) {var refresh = async function() {// Load the array first to prevent visual glitches.var array = await GM.getValue(identifier,[]),list = document.querySelector('#AO3-MS-list-' + identifier)while (list.firstChild !== null) {list.removeChild(list.firstChild);}if (identifier === 'blurblist') {for (let i = 0; i < array.length; ++i) {list.appendChild(makeBlurbFilterItem(identifier, i, array[i], refresh));}} else if (identifier === 'userlist') {for (let i = 0; i < array.length; ++i) {list.appendChild(makeUserFilterItem(identifier, i, array[i], refresh));}}};return refresh;}function makeFilterList(container, identifier, title) {var header = document.createElement("div");header.className = "AO3-MS-header";var list = document.createElement("div");list.id = "AO3-MS-list-" + identifier;list.className = "AO3-MS-list";var refresh = refreshFilterList(identifier)header.appendChild(document.createTextNode(title));refresh();container.appendChild(header);container.appendChild(list);return refresh;}function makeBlurbTab(viewport) {// Create the tab showing blocked entriesvar mutelist = document.createElement("div");mutelist.id = "AO3-MS-mutedWorks";viewport.appendChild(mutelist);var listRefresh = makeFilterList(mutelist, "blurblist", "Works & Series");return async function() {await listRefresh();};}function makeUserTab(viewport) {// Create the tab showing blocked entriesvar mutelist = document.createElement("div");mutelist.id = "AO3-MS-mutedUsers";viewport.appendChild(mutelist);var listRefresh = makeFilterList(mutelist, "userlist", "Users");return async function() {await listRefresh();};}async function addCheckbox(container, identifier, caption, hover) {var item = document.createElement("div");var checkbox = document.createElement("input");checkbox.type = "checkbox";checkbox.id = "AO3-MS-settings-" + identifier;checkbox.checked = await GM.getValue(identifier, false);checkbox.onclick = async function() {await GM.setValue(identifier, checkbox.checked);};var label = document.createElement("label");label.appendChild(document.createTextNode(caption));label.setAttribute('for', "AO3-MS-settings-" + identifier);label.setAttribute('title', hover);item.appendChild(checkbox);item.appendChild(label);container.appendChild(item);var refresh = async function() {checkbox.checked = await GM.getValue(identifier, false);};return refresh;}async function makeFilterTab(viewport) {// Create the tab with the general settings.var general = document.createElement("div");general.id = "AO3-MS-general";viewport.appendChild(general);var header = document.createElement("div");header.className = "AO3-MS-header";header.appendChild(document.createTextNode("Filter Settings"));general.appendChild(header);var refresh = document.createElement("div");refresh.className = "AO3-MS-refresh";refresh.appendChild(document.createTextNode("Refresh the page to make new extension settings take effect."));general.appendChild(refresh);var checkboxes = document.createElement("div");checkboxes.id = "AO3-MS-checkboxes";general.appendChild(checkboxes);var refreshList = [];refreshList.push(await addCheckbox(checkboxes, "addReason","Ask me for a reason whenever something/someone is muted.","When unchecked, it will mute in one click and leave the reason blank.\n" +"When checked, it will prompt for a reason before the mute goes through."));refreshList.push(await addCheckbox(checkboxes, "mute","Remove 'Hidden content' messages (aka total mute).","When unchecked, the content vanishes without trace for works and series.\n"+"When checked, it will display a message to indicate a work/series has been hidden.\n"+"Note that this means you'll only be able to unmute items from the menu.\n"+"Bookmarks and comments by a muted user will not have hidden content indicators."));refreshList.push(await addCheckbox(checkboxes, "showName","Show name/title in hidden content message for works and series.","If there is a hidden content message, it defaults to a generic 'Hidden content' message.\n"+"If you check this box, then it will display the name of the user who posted the content.\n"+"If the specific work/series was muted, it will also display the title."));refreshList.push(await addCheckbox(checkboxes, "showReason","Show reason for muting in hidden content message for works and series.","If there is a hidden content message, it defaults to a generic 'Hidden content' message.\n"+"If this box is checked, it will display the reason you entered for muting the content."));refreshList.push(await addCheckbox(checkboxes, "forceMobile","Display in mobile-friendly view even on larger screens.","Displays a smaller window with smaller font."));return async function() {for (var i = 0; i < refreshList.length; ++i) {await refreshList[i]();}};}// Unicode fix from https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22function utf8_to_b64(str) {return window.btoa(unescape(encodeURIComponent(str)));}function b64_to_utf8(str) {return decodeURIComponent(escape(window.atob(str)));}async function getFilterSettings() {var settings = {};settings['userlist'] = await GM.getValue('userlist');settings['blurblist'] = await GM.getValue('blurblist');var booleanNames = ['addReason','mute','showName','showReason','forceMobile',];for (var i = 0; i < booleanNames.length; ++i) {var name = booleanNames[i];settings[name] = await GM.getValue(name, false);}settings['custom-css'] = await loadCustomCSS();return settings;}async function saveFilterSettings(settings) {await GM.setValue('userlist',settings['userlist'])await GM.setValue('blurblist',settings['blurblist'])var booleanNames = ['addReason','mute','showName','showReason','forceMobile',];for (let i = 0; i < booleanNames.length; ++i) {var name = booleanNames[i];if (settings.hasOwnProperty(name)) {GM.setValue(name, settings[name]);}}if (settings.hasOwnProperty('custom-css')) {GM.setValue('custom-css', settings['custom-css']);}}async function updateExport() {var exportText = document.getElementById("AO3-MS-export");var settings = await getFilterSettings();exportText.value = utf8_to_b64(JSON.stringify(settings));exportText.select();exportText.focus();}async function doImport() {var importText = document.getElementById("AO3-MS-import");try {var settings = JSON.parse(b64_to_utf8(importText.value));await saveFilterSettings(settings);updateExport();} catch (e) {alert("Invalid data.");}}function makeImportTab(viewport) {// Make tab to import settings & filtersvar contMain = document.createElement("div");contMain.id = "AO3-MS-importMain";viewport.appendChild(contMain);var header = document.createElement("div");header.className = "AO3-MS-header";header.appendChild(document.createTextNode("Import settings & filters"));contMain.appendChild(header);var refresh = document.createElement("div");refresh.className = "AO3-MS-refresh";refresh.appendChild(document.createTextNode("Refresh the page to make new extension settings take effect."));contMain.appendChild(refresh);var padder = document.createElement("div")padder.className = "AO3-MS-padding"contMain.appendChild(padder)var importText = document.createElement("textarea");importText.id = "AO3-MS-import";importText.className = "AO3-MS-textarea";padder.appendChild(importText);var importButton = document.createElement("input");importButton.id = "AO3-MS-import-button";importButton.type = "button";importButton.value = "Import";importButton.onclick = doImport;padder.appendChild(importButton);}function makeExportTab(viewport) {// Create the tab with save and export boxes.var contMain = document.createElement("div");contMain.id = "AO3-MS-exportMain";viewport.appendChild(contMain);var exportHeader = document.createElement("div");exportHeader.className = "AO3-MS-header";exportHeader.appendChild(document.createTextNode("Export settings & filters"));contMain.appendChild(exportHeader);var padder = document.createElement("div")padder.className = "AO3-MS-padding"contMain.appendChild(padder)var exportText = document.createElement("textarea");exportText.id = "AO3-MS-export";exportText.className = "AO3-MS-textarea";exportText.readOnly = true;padder.appendChild(exportText);return updateExport;}function getDefaultRules() {var rules = {};var blockedBackground = 'none';var blockedColor = 'none';rules['.AO3-MS-collapseBlurb'] = {'background-color': blockedBackground,'color': blockedColor,'padding': '20px',}return rules;}async function loadCustomCSS() {var r###lt = await GM.getValue('custom-css', null);if (r###lt === null) {r###lt = makeStyleCode(getDefaultRules());}return r###lt;}async function updateCSS() {var cssText = document.getElementById("AO3-MS-css");cssText.value = await loadCustomCSS();}async function saveCSS() {var cssText = document.getElementById("AO3-MS-css");await GM.setValue('custom-css', cssText.value);}async function resetCSS() {await GM.deleteValue('custom-css');await updateCSS();}function makeColorsTab(viewport) {// Create the tab with the custom CSS editor.var colors = document.createElement("div");colors.id = "AO3-MS-colors";viewport.appendChild(colors);var cssHeader = document.createElement("div");cssHeader.className = "AO3-MS-header";cssHeader.appendChild(document.createTextNode("Custom styling"));colors.appendChild(cssHeader);var refresh = document.createElement("div");refresh.className = "AO3-MS-refresh";refresh.appendChild(document.createTextNode("Refresh the page to make new extension settings take effect."));colors.appendChild(refresh);var padder = document.createElement("div")padder.className = "AO3-MS-padding"colors.appendChild(padder)var css = document.createElement("textarea");css.id = "AO3-MS-css";css.className = "AO3-MS-textarea";padder.appendChild(css);var cssSave = document.createElement("input");cssSave.id = "AO3-MS-css-save";cssSave.className = "AO3-MS-css-button";cssSave.type = "button";cssSave.value = "Save";cssSave.onclick = async function () {await GM.setValue('custom-css',css.value)};padder.appendChild(cssSave);var cssReset = document.createElement("input");cssReset.id = "AO3-MS-css-reset";cssReset.className = "AO3-MS-css-button";cssReset.type = "button";cssReset.value = "Reset to Default";cssReset.onclick = resetCSS;padder.appendChild(cssReset);css.onchange = saveCSS;return updateCSS;}function toggleSettings() {var settings = document.getElementById("AO3-MS-settings");if (settings === null) return;if (settings.style.display == "flex") {settings.style.top = "-50%";settings.style.display = "none";} else {settings.style.display = "flex";settings.style.top = "50%";}}function addTab(container, name, view, active, action) {var classView = "AO3-MS-view";var classActive = "AO3-MS-active";var classTab = "AO3-MS-tab";var link = document.createElement("a");link.className = classTab;link.href = "javascript:void(0)";var text = document.createTextNode(name);link.appendChild(text);container.appendChild(link);var viewElement = document.getElementById(view);viewElement.className = classView;link.onclick = function(e) {var views = document.getElementsByClassName(classView);for (let i = 0; i < views.length; ++i) {views[i].className = classView;}var tabs = document.getElementsByClassName(classTab);for (let i = 0; i < tabs.length; ++i) {tabs[i].className = classTab;}viewElement.className += " " + classActive;link.className += " " + classActive;if (action !== undefined && action !== null) {action();}};if (active) {viewElement.className += " " + classActive;link.className += " " + classActive;}}function makeActionLink(text, action) {var link = document.createElement("a");link.href = "javascript:void(0)";link.className = "AO3-MS-action";link.onclick = action;link.appendChild(document.createTextNode(text));return link;}async function makeSettings() {// Create the settings window.var settings = document.createElement("div");settings.id = "AO3-MS-settings";var header = document.createElement("div");header.id = "AO3-MS-title";header.appendChild(document.createTextNode("Selective Muting"));settings.appendChild(header);var closeButton = document.createElement("input");closeButton.id = "AO3-MS-closeMenu";closeButton.type = "button";closeButton.value = "X";closeButton.onclick = function () {toggleSettings()};header.appendChild(closeButton);var tabs = document.createElement("div");tabs.id = "AO3-MS-tablist";settings.appendChild(tabs);var viewport = document.createElement("div");viewport.id = "AO3-MS-viewport";settings.appendChild(viewport);document.body.appendChild(settings);// Create the tabs and add them.var blurblistRefresh = await makeBlurbTab(viewport);var userlistRefresh = await makeUserTab(viewport);var generalRefresh = await makeFilterTab(viewport);var colorsRefresh = await makeColorsTab(viewport);var importRefresh = await makeImportTab(viewport);var exportRefresh = await makeExportTab(viewport);addTab(tabs, "Works/Series", "AO3-MS-mutedWorks", true, blurblistRefresh);addTab(tabs, "Users", "AO3-MS-mutedUsers", false, userlistRefresh);addTab(tabs, "Settings", "AO3-MS-general", false, generalRefresh);addTab(tabs, "CSS", "AO3-MS-colors", false, colorsRefresh);addTab(tabs, "Import", "AO3-MS-importMain", false, importRefresh);addTab(tabs, "Export", "AO3-MS-exportMain", false, exportRefresh);}async function makeCollapseBlurb(blurb,blurbInfo) {var container = document.createElement('li')container.classList.add('AO3-MS-collapseBlurb')container.classList.add('blurb')container.classList.add('AO3-MS-collapsed-' + blurbInfo[0])container.classList.add(blurb.id)blurb.parentElement.insertBefore(container,blurb)var mutePhrase = document.createElement('span')mutePhrase.classList.add('AO3-MS-mutePhrase')mutePhrase.innerText = 'Hidden content'var reason = document.createElement('span')reason.classList.add('AO3-MS-mutePhraseReason')if (blurbInfo[0].split('work').length > 1 || blurbInfo[0].split('series').length > 1) {makeTogglebox(blurb,'m',container)if (await GM.getValue('showName')) {mutePhrase.innerText += ': ' + blurbInfo[1] + ' by ' + blurbInfo[2]}if (await GM.getValue('showReason') && blurbInfo[3]) {reason.innerText += ' (' + blurbInfo[3] + ')'}mutePhrase.appendChild(reason)container.appendChild(mutePhrase)} else if (!blurb.classList.contains('bookmark')) {if (await GM.getValue('showName')) {mutePhrase.innerText += ' by ' + blurbInfo[2]}if (await GM.getValue('showReason') && blurbInfo[3]) {reason.innerText += ' (' + blurbInfo[3] + ')'}mutePhrase.appendChild(reason)container.appendChild(mutePhrase)makeTogglebox(blurb,'X',container)}}function getBlurbs(arrayName,value) {let blurbuser = arrayName.split('list')[0],toHide = ''if (blurbuser === 'blurb') {toHide = '.' + value[0]} else if (blurbuser === 'user') {value[1].split(',').forEach(w => {toHide += ',' + w + '.' + value[0]})toHide = toHide.substring(1)}return document.querySelectorAll(toHide)}async function addVal(arrayName,value) {// Add the entry to the saved arraylet temp = await GM.getValue(arrayName,[])for (let i = 0; i < temp.length; ++i) {if (temp[i][0] === value[0]) {return null;}}var reason = ''if (await GM.getValue('addReason',false)) {let muteObj = value[1]if (arrayName === 'userlist') {muteObj = value[2]}reason = prompt("Reason for muting " + muteObj + ":", '');if (reason === null) {return '';}}value.push(reason)temp.push(value);await GM.setValue(arrayName,temp)// Collapse/mute all works on the page that meet the criterialet mute = await GM.getValue('mute', false)let blurbs = getBlurbs(arrayName,value)for (let blurb of blurbs) {if (!mute && !document.querySelectorAll('.' + blurb.id).length &&(arrayName === 'blurblist' || blurb.classList.contains('work') || blurb.classList.contains('series')) ) {await makeCollapseBlurb(blurb,value)}blurb.classList.add('AO3-MS-muted')}var refresh = refreshFilterList(arrayName)refresh()return true}async function delVal(arrayName,key) {// Remove the entry from the saved arraylet temp = await GM.getValue(arrayName,false)let value = [];let i = 0;while (i < temp.length) {if (temp[i][0] === key) {value = temp[i];temp.splice(i, 1);} else {++i;}}await GM.setValue(arrayName,temp)// Uncollapse/unmute all works on the page that meet the criterialet mute = await GM.getValue('mute',false)let blurbs = getBlurbs(arrayName,value)if (!mute) {for (let c of document.querySelectorAll('.AO3-MS-collapsed-' + key)) {c.remove();}}for (let blurb of blurbs) {blurb.classList.remove('AO3-MS-muted')}if(arrayName === 'userlist') {let delMe = []for (let i = 0; i < commentMute.length; i++) {if (commentMute[i].includes(value[0])) {let delMe = commentMute.splice(i,1)delMe ? makeStyleSheet(makeStyleCode(addMuteRules(commentMute.join(','))),'AO3-MS-muteByStyle') : null}}setInitialMute('blurblist')}var refresh = refreshFilterList(arrayName)refresh()}async function getVal(arrayName,key) {let temp = [];if (await GM.getValue(arrayName)) {temp = await GM.getValue(arrayName)} else {return null;}for (let i = 0; i < temp.length; ++i) {if (temp[i][0] === key) {return temp[i]}}return null;}function getBlurbUserID(blurb) {for (let e of blurb.classList) {if (e.includes('user-')) {return e;}}return null;}async function toggleBlurb(blurb,toggleboxA) {var blurbInfo = [];if (blurb) {for (let e of blurb.classList) {if (e.includes('work-') || e.includes('series-')) {blurbInfo.push(e)}}// record titleblurbInfo.push(blurb.querySelectorAll('.heading a')[1].textContent)// record creatorsif (!blurb.querySelectorAll('h4.heading [rel="author"]').length) {blurbInfo.push('(Anonymous creator)')} else {let authorNames = ''blurb.querySelectorAll('h4.heading [rel="author"]').forEach (a => {authorNames += ', ' + a.innerText})authorNames = authorNames.substring(2)blurbInfo.push(authorNames)}} else if (document.querySelectorAll('h2.title.heading').length) {blurbInfo.push(getIdFromWorkPage())blurbInfo.push(document.querySelector('h2.title.heading').textContent.substring(1).trim())blurbInfo.push(document.querySelector('a[rel="author"]').innerText)} else if (document.querySelectorAll('.series-show h2.heading').length) {blurbInfo.push(getIdFromSeriesPage())blurbInfo.push(document.querySelector('.series-show h2.heading').textContent.substring(1).trim())blurbInfo.push(document.querySelector('a[rel="author"]').innerText)}if(toggleboxA.textContent == 'M') {await addVal('blurblist',blurbInfo) && !blurb ? toggleboxA.textContent = 'm' : ''// The M->m change only actually matters on title pages; on blurblists M vs m are actually in two different blurbs} else {await delVal('blurblist',blurbInfo[0])!blurb ? toggleboxA.textContent = 'M' : ''}}async function toggleUser(blurb,togglebox,userID,username) {if (togglebox.parentNode.querySelectorAll('.AO3-MS-usermenu').length){togglebox.parentNode.querySelector('.AO3-MS-usermenu').remove()return null;}var usermenu = document.createElement('div');usermenu.id = 'AO3-MS-usermenu-' + userID;usermenu.classList.add('AO3-MS-usermenu')if(!blurb) {// Prevent the menu from being enormous on profile pagesusermenu.style.fontSize = fontSizing.refreshFont + 'px'usermenu.style.display = 'block'}let items = [['.work','Works'],['.work,.series','Works & Series'],['.comment','Comments'],['','Mute all'],['none','Unmute']]async function createItem(item) {var container = document.createElement('span')container.classList.add('AO3-MS-usermenu-item')usermenu.appendChild(container)// check what the current option is, and highlight itlet currEntry = await getVal('userlist',userID)if (currEntry) {if (currEntry[1] === item[0]) {container.classList.add('AO3-MS-usermenu-item-selected')}} else if (item[0] === 'none') {container.classList.add('AO3-MS-usermenu-item-selected')}var a = document.createElement('a')a.href = "javascript:void(0)";a.appendChild(document.createTextNode(item[1]));container.appendChild(a)a.onclick = async function() {let currEntry = await getVal('userlist',userID)if (currEntry) {if (item[0] != currEntry[1]) {await delVal('userlist',userID)}}if (item[0] != 'none') {let newEntry = [userID,item[0],username];await addVal('userlist',newEntry);}// remove all menues on the page because things have probably changedlet rl = document.querySelectorAll('.AO3-MS-usermenu')for (let ri of rl) {ri.remove()}}item.push(container)}for (let i = 0; i < items.length; i++) {await createItem(items[i])}togglebox.parentElement.appendChild(usermenu)// console.log ('checking right: ' + togglebox.getBoundingClientRect().right)// console.log ('checking parent right: ' + togglebox.parentElement.getBoundingClientRect().right)// Fix if it's likely to get squished -- not great, but ehif (blurb && (await GM.getValue('forceMobile',false) || window.innerWidth < 900)) {usermenu.style.display = 'block'}}function makeTogglebox(blurb, tType, pin) {var togglebox = document.createElement('div');var toggleboxA = document.createElement('a');togglebox.classList.add('AO3-MS-toggle');togglebox.appendChild(toggleboxA);toggleboxA.href = "javascript:void(0)";toggleboxA.appendChild(document.createTextNode(tType));if (blurb) {if (tType == 'X') {toggleboxA.onclick = async function() {let username = blurb.querySelector('.heading a[rel="author"]').textContentawait toggleUser(blurb,togglebox,getBlurbUserID(blurb),username)};} else {toggleboxA.onclick = async function() {await toggleBlurb(blurb,toggleboxA)};}} else {if (tType == 'X') {toggleboxA.onclick = async function() {let username = document.querySelector('.profile-show h2.heading').innerText.split(' ')[0]await toggleUser(false,togglebox,getIdFromProfilePage(),username)}} else {toggleboxA.onclick = async function() {await toggleBlurb(false,toggleboxA)};}}if (tType == 'X') {pin.append(togglebox)} else {pin.prepend(togglebox)}}function addMuteButtonToBlurbs() {const blurbs = document.querySelectorAll('.blurb.work,.blurb.series,.blurb.bookmark');for (let blurb of blurbs) {let blurbTitle = blurb.querySelector('.heading')makeTogglebox(blurb,'M',blurbTitle)if(blurb.querySelectorAll('h4.heading a').length == 3 && !blurb.classList.contains('bookmark')) {makeTogglebox(blurb,'X',blurbTitle)}}}async function setInitialMute(identifier) {let entries = await GM.getValue(identifier,[]);if (!entries) {return null;}let mute = await GM.getValue('mute',false),blurbs = ''for (const entry of entries) {if (identifier === 'userlist') {let typeToHide = ''if (entry[1].includes('work')) {entry[1].split(',').forEach(w => {typeToHide += ',' + w + '.' + entry[0]})} else {typeToHide = ',.work.' + entry[0] + ',.series.' + entry[0]}typeToHide = typeToHide.substring(1)typeToHide ? blurbs = document.querySelectorAll(typeToHide) : null} else {blurbs = document.querySelectorAll('.' + entry[0])}for (let blurb of blurbs) {if (!blurb.classList.contains('AO3-MS-muted')) {if (!mute && !document.querySelectorAll('.' + blurb.id).length) {await makeCollapseBlurb(blurb,entry)}blurb.classList.add('AO3-MS-muted')}}}}function getIdFromWorkPage() {if (document.querySelectorAll('li.download a').length > 1) {if (isNaN(document.querySelectorAll('li.download a')[1].href.split('/')[4])) {return null;} else {return 'work-' + document.querySelectorAll('li.download a')[1].href.split('/')[4]}}return null;}function getIdFromSeriesPage() {let parts = window.location.pathname.split('/')for (let i = 0; i < parts.length - 1; i++) {if (parts[i] === 'series' && !isNaN(parts[i+1])) {return 'series-' + parts[i+1]}}return null}function getIdFromProfilePage() {if(document.querySelectorAll('.meta').length) {let parts = document.querySelector('.meta').innerText.split('\n')for (let i = 0; i < parts.length - 1; i++) {if (parts[i] === 'My user ID is:' && !isNaN(parts[i+1])) {return 'user-' + parts[i+1]}}return null}}async function setTitleMute() {let blurbId = ''async function determineMm(blurbId) {if (await getVal('blurblist',blurbId)) {return 'm'}return 'M'}if (document.querySelectorAll('h2.title.heading').length) { // work or chapter pageblurbId = getIdFromWorkPage()blurbId ? makeTogglebox(false,await determineMm(blurbId),document.querySelector('h2.title.heading')) : null} else if (document.querySelectorAll('.series-show h2.heading').length) { // series pageblurbId = getIdFromSeriesPage()blurbId ? makeTogglebox(false,await determineMm(blurbId),document.querySelector('.series-show h2.heading')) : null} else if (document.querySelectorAll('.profile-show h2.heading').length) { // profile pageblurbId = getIdFromProfilePage()blurbId ? makeTogglebox(false,'X',document.querySelector('.profile-show h2.heading')) : null}}function addToNavBar() {let searchNode = document.querySelector('li.search'),li = document.createElement('li'),a = document.createElement('a')a.href = 'javascript:void(0)'a.appendChild(document.createTextNode('Muting'))a.onclick = function() {toggleSettings();};li.classList.add('dropdown')li.appendChild(a)searchNode.parentNode.insertBefore(li,searchNode)}(async function() {'use strict';var filterSettings = await getFilterSettings();var useMobile = (window.innerWidth < 900 ? true : false)fontSizing = standardSizeif (useMobile || await GM.getValue('forceMobile',false)) {fontSizing = mobileSize}fontSizing.menuWidth > (window.innerWidth - 10) ? fontSizing.menuWidth = window.innerWidth -10 : ''fontSizing.menuHeight > (window.innerHeight -10) ? fontSizing.menuHeight = window.innerHeight -10 : ''addToNavBar();makeSettings();var userlist = await GM.getValue('userlist',[])for (const u of userlist) {if (u[1] === '.comment') {commentMute.push('.comment.' + u[0])} else if (!u[1]) {commentMute.push('.' + u[0] + ':not(.work,.series)')}}var muteByStyle = commentMute.join(',')makeStyleSheet(makeStyleCode(getMenuRules()),'AO3-MS-mainStyle');makeStyleSheet(filterSettings['custom-css'],'AO3-MS-custom-css');makeStyleSheet(makeStyleCode(addMuteRules(commentMute.join(','))),'AO3-MS-muteByStyle')await setInitialMute('userlist');await setInitialMute('blurblist');await setTitleMute();addMuteButtonToBlurbs();})();