/* TODO
- make rows actually disappear when read (optionally?)
- should 'mark all' find all rows with that title and remove them too? oof.
- would be cool if the 'mark all' button could be hidden if there are no newer revisions for this page.
- theoretically, could probably do this without extra requests, just by looking at the DOM
*/
function lastRevForLine(line) {
let rev = line.dataset.mwRevid;
if (rev) return rev;
for (let row of line.querySelectorAll('tr.mw-changeslist-line')) {
if (row.dataset.mwRevid) {
return row.dataset.mwRevid;
}
}
}
const include_mark_all = true;
function addButtons(line, api) {
const revid = lastRevForLine(line);
//if (revid === undefined) return;
//const ts = parseInt(line.dataset.mwTs);
//const ts = line.dataset.mwTs;
// Hm, so setting timestamp to exactly ts seems to mark everything up to but not including that rev as read. Hack required?
// timestamps look like 20190827165313 i.e. 2019-08-27-16-53-13
// there must be some mw helper for encoding/decoding date strings like this...
const title_ele = line.querySelector('a.mw-changeslist-title');
if (!title_ele) {
// This shouldn't happen. Was previously triggered when we weren't excluding entries from move log or page curation log.
console.warn("Couldn't find a.mw-changeslist-title for line:", line);
return;
}
const href = title_ele.attributes.href.value;
const prefix = '/wiki/';
let title;
if (href.startsWith(prefix)) {
title = href.slice(prefix.length);
} else {
const pre2 = '/w/index.php?title=';
if (href.startsWith(pre2)) {
title = href.slice(pre2.length);
} else {
console.warn("Couldn't find title in...", title_ele);
return;
}
}
const row = line.querySelector('tr');
// Main watchlist entry ele (with links to article, diff, history, etc.). This is where we add the button(s).
const button_td = row.querySelector('td.mw-changeslist-line-inner');
const addButton = (label, onclick) => {
const button = document.createElement('button');
button.textContent = label;
button.addEventListener('click', onclick);
button_td.appendChild(button);
button.classList.add('markread');
button.style.padding = '0 2px';
button.style.marginLeft = '0.3em';
button.style.marginRight = '1.3em';
button.style.borderColor = '#555';
button.style.borderWidth = '2px';
return button;
};
// TODO: Guess don't need to import mw.Title anymore?
//const parsed_title = mw.Title.newFromText(title);
const markChangeRead = (evt) => {
const params = {
action: 'setnotificationtimestamp',
// Wait, then what the heck does the "revids" param do?
//torevid: parseInt(revid)+1,
newerthanrevid: revid,
// need only one of titles or revids
// But if we provide torevid/newerthanrevid WITHOUT title, the API call will fail silently. Because of course it will.
// need to get rid of any % encoding
titles: decodeURI(title)
};
console.log(params);
api.postWithEditToken(params);
line.style.opacity = 0.5;
};
const markAllRead = (evt) => {
// If no timestamp/revid is provided, default behaviour is to set timestamp to now (i.e. mark all extant revisions as read)
const params = {
action: 'setnotificationtimestamp',
titles: decodeURI(title)
};
console.log(params);
api.postWithEditToken(params);
line.style.opacity = 0.3;
};
const heavycheck = '✔';
const check = '✓';
addButton(check, markChangeRead);
if (include_mark_all) {
const markall = addButton(heavycheck, markAllRead);
markall.style.backgroundColor = '#d4b3ad';
markall.setAttribute('title', 'Mark all revisions of this page read');
}
}
if (mw.config.values.wgCanonicalSpecialPageName === 'Watchlist') {
mw.loader.using(['mediawiki.api', 'mediawiki.Title'], function () {
let api = new mw.Api();
window.wgAPI = api;
let wl = document.querySelector('.mw-changeslist');
// Exclude log lines (move log, page curation log, etc.)
let lines = wl.querySelectorAll('table.mw-changeslist-line:not(.mw-changeslist-log)');
lines.forEach((line) => addButtons(line, api));
});
}
/* re API...
So, the docs at https://www.mediawiki.org/wiki/API:Setnotificationtimestamp aren't totally clear at this, but
based on some experimentation, it seems like for each (page, user) pair, there's just one revid/timestamp stored, such
that anything newer is considered unseen, and anything older is seen.
This is totally contrary to my mental model, which was that there was a seen flag for every revision. I didn't realize that viewing the diff of one
particular rev of a page would cause all older revs to be marked as viewed.
Well this affects the implementation of this - and actually makes it a lot easier.
*/
/* Notes on watchlist DOM structure:
.mw-changeslist
<h4>date
div
table.mw-changeslist-line data-mw-revid=... data-mw-ts=...
tr
// or, for collapsed line with multiple revs (will have data-ts but not revid) data-mw-revid will be on the tr's
table.mw-chageslist-line.mw-collapsible > tbody
tr*
*/