// I'm not a React developer. Be advised! // If you are, and want to rewrite this the "right way", go ahead and do it :) // This is plain Javascript and only requires basic calls to implement customizations // Do simple XHR requests to the API on Mastodon // make sure you control errors correctly, as a Mastodon Server might not setup CORS correctly function mastodon_get(path, payload, callbk) { return mastodon_request('GET', path, payload, callbk); } function mastodon_post(path, payload, callbk) { return mastodon_request('POST', path, payload, callbk); } function mastodon_request(method, path, payload, callbk) { payload = payload || null; var instance = JSON.parse(localStorage.store_currentInstance); var token = JSON.parse(localStorage.store_loggedInInstances)[instance].access_token; var url = 'https://'+instance+path; var oReq = new XMLHttpRequest(); oReq.addEventListener("load", function() { callbk(this.responseText); }); oReq.open(method, url); oReq.setRequestHeader('Authorization', 'Bearer '+token); oReq.send(payload); } function api_status_fav(dom, status_id) { var dislike = false; var path = `/api/v1/statuses/${status_id}/favourite`; if (dom.getAttribute('data-liked') === "1") { path = `/api/v1/statuses/${status_id}/unfavourite`; dislike = true; } mastodon_post(path, {}, function(data) { // to-do: check "data" if the POST succeded (for now we expect it did xD) if (!dislike) { $(dom).addClass('liked-msg'); $(dom).attr('data-liked', 1); dom.style.animation = "spin2 .5s linear 1"; } else { $(dom).removeClass('liked-msg'); $(dom).attr('aria-label', '0 '+$(dom).attr('aria-label')); $(dom).removeAttr('data-liked'); dom.style.animation = undefined; } }); } // this is our URL-based customizations made by JavaScript var intervalChatCssChange = null; function fedilove_customization() { document.querySelector('.main-content').classList = "main-content"; document.querySelector('#chat-compose-global').style = 'visibility: collapse'; if (window.location.pathname.startsWith('/statuses/')) { // this is ugly enough, so we will use CSS for the rest xD $('div.main-content').addClass('chat'); // show the chat message compose bottom layer document.querySelector('#chat-compose-global').style = ''; // add some animations var style = document.createElement('style'); style.innerHTML = '@keyframes spin2 { 100% { transform:rotate(-360deg); } }'; document.body.appendChild(style); // this function changes the css class on articles (messages) // that match the given account_id var makeMessageUIModifications = function(account_id) { if (intervalChatCssChange !== null) return; var theint = 150; setInterval(function() { intervalChatCssChange = this; // paint MY messages as mine $('div.main-content.chat article.status-article').each(function(i) { if ($(this).find('a.status-author-name').attr('href').endsWith(`/accounts/${account_id}`)) { $(this).addClass('mymsg'); theint = 250; } }); // paint LIKES $('a.status-favs-reblogs.status-favs').each(function(i) { // easy, aria-label contains the times this status was fav // so, we use this as the input source to search for "0", // if no "0" found in text, we mark element as liked so we can apply styles and "undo like" function if ($(this).attr('aria-label').search(/0/) == -1) { $(this).addClass('liked-msg'); $(this).attr('data-liked', 1); } }); }, theint); }; // get the userAccountId to check against the href /account/NUM on the messages // so we can apply different style to my messages if (localStorage.store_userAccountId === undefined) { mastodon_get('/api/v1/accounts/verify_credentials', {}, function(data) { var json = JSON.parse(data); if (json !== undefined) { localStorage.store_userAccountId = json.id; makeMessageUIModifications(json.id); } }); } else { makeMessageUIModifications(localStorage.store_userAccountId); } } } // we inject this script.js into the React framework at timelines.js // Watch for URL changes every 1/2 seconds (this is efficient, don't worry about it!) // and dispatch a call to "fedilove_customization" to load page customizations depending on URL context var theurl = null; setInterval(function() { var newurl = window.location.pathname; if (newurl != theurl) { fedilove_customization(); theurl = newurl; } }, 250);