NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name MastodonHelper // @namespace http://tampermonkey.net/ // @version 0.4.6 // @description Make Mastodon look nicer. // @author You // @match https://literatur.social/* // @license BSD-3-Clause; https://opensource.org/licenses/BSD-3-Clause // @updateURL https://openuserjs.org/meta/khzimmer/MastodonHelper.meta.js // @grant none // ==/UserScript== (function() { var MastodonHelperVERSION = '0.4.6'; // Color of the normal links: var linkColorDark = '#74AFDA'; var linkColorLight = '#0040A0'; // Color of the little "NOTES" text area below the account name in the right-most column: var noteColorDark = '#FED579'; var noteColorLight = '#800000'; // Background color of private messages: var privColorDark = '#333846'; var privColorLight = '#DDEEFF'; // Color for the Publish button: var buttonBackgroundColor = '#000060'; // Color for non-highlighted list rows: var textColorDark = '#CCCCCC'; var textColorLight = '#000000'; var cssForLight = 'packs/css/mastodon-light'; // as of yet unused: var cssForContrast = 'packs/css/contrast'; var linkColor = linkColorDark; var noteColor = noteColorDark; var privColor = privColorDark; var textColor = textColorDark; var globalColorsUnknown = true; function setGlobalColors () { if (globalColorsUnknown) { var links = document.getElementsByTagName ("link"); for (var i=0; i<links.length; i++) { if (links [i].href && links [i].rel && links [i].rel == 'stylesheet') { if (links [i].href.indexOf (cssForLight) > -1) { // console.log('(light theme found)'); linkColor = linkColorLight; noteColor = noteColorLight; privColor = privColorLight; textColor = textColorLight; } globalColorsUnknown = false; } } } } function getLinkColor () { setGlobalColors (); return linkColor; } function getNoteColor () { setGlobalColors (); return noteColor; } function getPrivateMessageColor () { setGlobalColors (); return privColor; } function getTextColor () { setGlobalColors (); return textColor; } function getFirstChildWithClassName (container, className) { var element = null; var elements = container.getElementsByClassName (className); if (elements.length > 0) { element = elements [0]; } return element; } function getFirstChildWithTagName (container, tagName) { var element = null; var elements = container.getElementsByTagName (tagName); if (elements.length > 0) { element = elements [0]; } return element; } var observerActionsAllowed = true; var myQuickAccessButton = null; function highlightPrivateMessages (rightMostColumn, className) { var boostButtons = document.getElementsByClassName (className); for (var i=0; i<boostButtons.length; i++) { var button = boostButtons [i]; if (getFirstChildWithClassName (button, 'fa fa-retweet fa-fw')) { var parent = rightMostColumn ? button.parentNode.parentNode.parentNode : button.parentNode.parentNode; parent.style.backgroundColor = getPrivateMessageColor (); var paras = parent.getElementsByTagName ('p'); for (var j=0; j<paras.length; j++) { paras [j].style.color = getNoteColor (); } } } } function colorizeTheLinks () { if (! observerActionsAllowed) { return; } observerActionsAllowed = false; var linkColor = getLinkColor (); var links = document.getElementsByTagName ("a"); for (var i=0; i<links.length; i++) { if (links [i].href && links [i].style && (links [i].style.color !== linkColor)) { var link = links [i]; var className = link.className; if (className && (className.indexOf ('display-name') < 0) && (className.indexOf ('status__relative-time') < 0) && (link.innerHTML.indexOf ('display-name') < 0)) { link.style.color = linkColor; } } } var button = getFirstChildWithClassName (document, 'button logo-button button--destructive button--with-bell'); if (button) { if (button.style && (button.style.backgroundColor !== buttonBackgroundColor)) { button.style.backgroundColor = buttonBackgroundColor; } } else { button = getFirstChildWithClassName (document, 'button logo-button'); if (button) { if (button.style && (button.style.backgroundColor !== buttonBackgroundColor)) { button.style.backgroundColor = buttonBackgroundColor; } } } var backLink = getFirstChildWithClassName (document, 'column-header__back-button'); if (! backLink) { backLink = getFirstChildWithClassName (document, 'column-back-button'); } if (backLink) { var span = getFirstChildWithTagName (backLink, 'span'); if (span && span.style && (span.style.color !== linkColor)) { span.style.color = linkColor; } } highlightPrivateMessages (false, 'status__action-bar__button icon-button disabled'); highlightPrivateMessages (true, 'icon-button disabled'); setTimeout(function () { observerActionsAllowed = true; }, 100); } var renameThePublishButtonWasDone = false; function renameThePublishButton () { if (renameThePublishButtonWasDone) { return; } var buttonContainer = getFirstChildWithClassName (document, 'compose-form__publish-button-wrapper'); if (renameThePublishButtonWasDone) { return; } if (buttonContainer) { renameThePublishButtonWasDone = true; var oldLabelText = 'Veröffentlichen!'; if (buttonContainer.innerHTML.indexOf (oldLabelText) > -1) { buttonContainer.innerHTML = '<button class="button button--block" title="Bei evtl. enthaltenen Bildern trage bitte vor dem Tröten eine Bildbeschreibung ein.\n\nDu ermöglichst ScreenReader Nutzenden so eine schönere und bessere Teilhabe. :)" type="submit">Trööt! 🐘</button>'; var button = getFirstChildWithTagName (buttonContainer, 'button'); if (button) { button.style.backgroundColor = buttonBackgroundColor; } console.log ('Publish button renamed successfully. :)'); } else { console.log ('No button with label "Veröffentlichen!" was found. Nothing was changed.'); } } } function getIconButtonContainer () { var buttonContainers = document.getElementsByClassName ('account__header__tabs__buttons'); if (buttonContainers.length > 0) { return buttonContainers [0]; } return null; } function getIconButtons () { var iconButtons = {}; var buttonContainer = getIconButtonContainer (); if (buttonContainer) { return buttonContainer.getElementsByClassName ('icon-button'); } return iconButtons; } function getLinkForLists () { var link = null; var menu = getFirstChildWithClassName (document, 'dropdown-menu bottom'); if (menu) { var items = menu.getElementsByClassName ('dropdown-menu__item'); for (var i = 0; i < items.length; i++) { var item = items [i]; var links = item.getElementsByTagName ('a'); if (links.length > 0) { var thisLink = links [0]; if (thisLink.innerHTML == 'Hinzufügen oder Entfernen von Listen' || thisLink.innerHTML == 'Add or Remove from lists' || thisLink.innerHTML == 'Ajouter ou retirer des listes' || thisLink.innerHTML == 'Aggiungi o togli dalle liste' || thisLink.innerHTML == 'Додати або видалити зі списків' || thisLink.innerHTML == 'Dodaj lub usuń z list') { link = thisLink; } } } } return link; } var listsDialog = null; var beautifyListsDialogIsRunning = false; function beautifyListsDialog () { if (beautifyListsDialogIsRunning || (! listsDialog)) { return; } beautifyListsDialogIsRunning = true; observerActionsAllowed = false; var items = listsDialog.getElementsByClassName ('list__wrapper'); for (var i = 0; i < items.length; i++) { var item = items [i]; var rightPart= getFirstChildWithClassName (item, 'account__relationship'); var button = getFirstChildWithTagName (rightPart, 'button'); if (button) { var color = (button.innerHTML.indexOf ('fa-times') > -1) ? getNoteColor () : getTextColor (); var leftPart = getFirstChildWithClassName (item, 'list__display-name'); /* var endOfI = leftPart.innerHTML.indexOf ('</i>'); if (endOfI > -1) { var listName = leftPart.innerHTML.substring (endOfI+4); leftPart.innerHTML = leftPart.innerHTML.substring (0, endOfI+4) + ' ◆ ' + listName; } else { leftPart.innerHTML = leftPart.innerHTML+' ◆◆◆'; } */ leftPart.style.color = color; var star = getFirstChildWithTagName (button, 'i'); if (star) { star.style.color = color; } } } observerActionsAllowed = true; beautifyListsDialogIsRunning = false; } function checkForListsDialog () { var oldDlg = listsDialog; listsDialog = getFirstChildWithClassName (document, 'modal-root__modal list-adder'); beautifyListsDialog (); } setInterval (checkForListsDialog, 1000); function openTheListsDialog () { var iconButtons = getIconButtons (); if (iconButtons.length > 0) { observerActionsAllowed = false; var menuButton = iconButtons [iconButtons.length - 1]; // open the menu after a short while: setTimeout(function () { menuButton.click (); }, 250); // Note (A): We specified a short delay here to give the menu time to be shown. // Find the opened menu and click the menu item to open the lists dialog: setTimeout(function () { var link = getLinkForLists (); if (link) { link.click (); } }, 500); // Note (B): The delay specified here must be longer than the small delay specified at (A). } } var currentUserName = '?'; var addQuickAccessButtonForListsIsRunning = false; function addQuickAccessButtonForLists () { if (addQuickAccessButtonForListsIsRunning) { return; } addQuickAccessButtonForListsIsRunning = true; var buttonContainer = getIconButtonContainer (); if (buttonContainer) { var iconButtons = getIconButtons (); if (iconButtons.length > 0) { var nameContainer = buttonContainer.parentNode.nextElementSibling; if (nameContainer) { var classOfMyButton = 'MastodonHelper-button-for-quick-access-to-lists'; myQuickAccessButton = getFirstChildWithClassName (nameContainer.parentNode, classOfMyButton); if (! myQuickAccessButton) { var menuButton = iconButtons [iconButtons.length - 1]; var newButton = document.createElement('button'); newButton.setAttribute ('type', 'button'); newButton.setAttribute ('title', 'Add or Remove from lists'); newButton.setAttribute ('class', classOfMyButton); newButton.innerHTML = ' <b>L</b> '; nameContainer.parentNode.insertBefore (newButton, nameContainer); myQuickAccessButton = getFirstChildWithClassName (nameContainer.parentNode, classOfMyButton); if (myQuickAccessButton) { myQuickAccessButton.addEventListener("click", function () { openTheListsDialog (); }); console.log ('Button "L" was added for opening the add to/remove from lists menu.'); } } var textArea = getFirstChildWithTagName (buttonContainer.parentNode.parentNode.parentNode, 'textarea'); if (textArea) { textArea.style.color = getNoteColor (); } } } } else { console.log ('Container not found, retrying in 1.5 seconds …'); setTimeout(addQuickAccessButtonForLists (), 1500); // Note: The delay specified here must be longer than the delays specified below. } setTimeout(function () { addQuickAccessButtonForListsIsRunning = false; }, 1000); // Note: The delay specified here must be shorter than the delays specified above. } var observerHasBeenSetUp = false; function setupObserver () { if (observerHasBeenSetUp) { return; } console.log ('Trying to setup observer for column area …'); var columnsArea = getFirstChildWithClassName (document, 'columns-area'); if (observerHasBeenSetUp) { return; } if (columnsArea) { observerHasBeenSetUp = true; let observer = new MutationObserver(mutationRecords => { if (observerActionsAllowed) { setTimeout(addQuickAccessButtonForLists (), 500); } }); observer.observe(columnsArea, { childList: true, // observe direct children subtree: true, // lower descendants too characterDataOldValue: false, // do not pass old data to callback }); console.log ('Observer was set up for column area.'); } } function beautifyMastodon () { console.log('Mastodon Helper ' + MastodonHelperVERSION + ' running …'); setInterval (renameThePublishButton, 1400); setInterval (setupObserver, 2500); setInterval (colorizeTheLinks, 3000); } beautifyMastodon (); })();