User:Closingbracket/changesviewer.js

const ENABLE = false;

let changes = []; let lastChange = null;

function updateChanges(callback = ( => {})) { let lines = Array.from(document.getElementsByClassName("mw-changeslist-line")); if (!lastChange) lines = lines.slice(0, 5); else lines = lines.slice(		0,		lines.findIndex(line => line.getAttribute("data-mw-revid") == lastChange)	); console.log(lines); if (lines.length == 0) return; changes = changes.concat(lines.reverse); lastChange = lines[lines.length - 1].getAttribute("data-mw-revid"); console.log(`Update changes; lines are ${ lines }`); callback(lines); }

function autoRefresh(callback) { const butt = document.getElementsByClassName("mw-rcfilters-ui-filterWrapperWidget-showNewChanges")[0]; setInterval( => {		if (butt.classList.contains("oo-ui-element-hidden")) return;		else {			butt.children[0].click;			console.log("Refreshing");			setTimeout( => updateChanges(callback), 400);			setTimeout( => updateChanges(callback), 800);		}	}, 750); }

function openViewer { const main = document.createElement("div"); main.id = "cv-content"; main.innerHTML = ` Changes viewer Loading... 				 Next change Latest change `;	document.getElementById("content").style.display = "none"; document.getElementById("mw-content").appendChild(main); const content = document.getElementById("cv-frames"); const headerContainer = document.getElementById("cv-header"); const header = headerContainer.children[0]; const buttons = headerContainer.children[1].children; const buttonState = (state) => { buttons[0].disabled = !state; buttons[1].disabled = !state; };	const updateViewer = (newLines) => { console.log("Updating viewer"); for (const line of newLines) { const newFrame = document.createElement("iframe"); newFrame.src = line.getElementsByClassName("mw-changeslist-diff")[0].href; content.appendChild(newFrame); newFrame.onload = => newFrame .contentDocument .getElementById("mw-header-container") .remove; //header.innerText = `Viewing revision ${ line.getAttribute("data-mw-revid") }`; this is wrong }		if (changes.length == 0) buttonState(false); else buttonState(true); };	buttons[0].onclick = => { console.log("Continuing"); changes = changes.slice(1); content.children[0].remove; if (changes.length == 0) buttonState(false); else buttonState(true); console.log(changes); };	buttons[1].onclick = => { console.log("Skipping"); changes = changes.slice(changes.length - 1); for (let i = 0; i < changes.length; i++) content.children[0].remove; if (changes.length == 0) buttonState(false); else buttonState(true); console.log(changes); };	autoRefresh(updateViewer); }

function init { // add to the sidebar const sidebarItem = document.createElement("div"); sidebarItem.setAttribute("id", "p-cv-sidebar"); sidebarItem.setAttribute("class", "mw-portlet"); sidebarItem.setAttribute("role", "navigation"); sidebarItem.setAttribute("labelledby", "p-cv-sidebar-label"); sidebarItem.innerHTML = ` Changes viewer   Changes viewer    `;	sidebarItem.querySelector("li").onclick = => openViewer; const sidebar = document.querySelector("#page-tools .sidebar-inner"); sidebar.insertBefore(sidebarItem, sidebar.children[0]); // add styling const style = document.createElement("style"); style.innerText = ` /* changes viewer styling */ #cv-header { display: flex; width: 100%; justify-content: space-between; align-items: center; } #cv-header button { background: blue; border: none; cursor: pointer; outline: none; padding: 2px; margin: 0px 2px; color: white; border-radius: 2px; } #cv-header button:disabled { background: gray; } #cv-frames iframe:first-child { border: none; height: 65vh; width: 100%; } #cv-frames :not(:first-child) { display: none; } `;	document.head.appendChild(style); mw.notify("Changes viewer loaded"); }

if (ENABLE && location.pathname.endsWith("/Special:RecentChanges")) init;