User:What7what8/CommentHistoryTool.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
//TODO:
//若留言經刪後重建,無法搜尋到重建以前的歷史 (https://zh.wikipedia.org/w/index.php?title=Wikipedia:%E4%BA%92%E5%8A%A9%E5%AE%A2%E6%A0%88/%E6%96%B9%E9%92%88&diff=next&oldid=80890074)
//適配對話頁討論存檔,找回原討論
$(function() {
mw.loader.using('ext.gadget.HanAssist').then((require) => {
const {conv} = require('ext.gadget.HanAssist');
mw.loader.load('https://zh.wikipedia.org/w/load.php?lang=' + mw.config.get("wgPageViewLanguage") + '&modules=ext.visualEditor.diffPage.init.styles%7Cmediawiki.diff.styles&only=styles&skin='+mw.config.get('skin') , 'text/css');
$(".ext-discussiontools-init-replylink-buttons").after(`
<span style="display: none;" class="tool-init-comment-historybutton oo-ui-widget oo-ui-widget-enabled oo-ui-buttonElement oo-ui-buttonElement-frameless oo-ui-iconElement oo-ui-labelElement oo-ui-flaggedElement-progressive oo-ui-buttonWidget" id="ooui-php-42" data-ooui="">
<div class="tool-init-comment-historybutton-tooltip" data-hasrun="false" haspreview="false" oldest_old_id = -1></div>
<a class="oo-ui-buttonElement-button" role="button" tabindex="0" rel="nofollow">
<span class="oo-ui-iconElement-icon oo-ui-icon-clock oo-ui-image-progressive style="background-size: 1.2em;top: -0.1em;"></span>
<span class="oo-ui-labelElement-label">` + conv({hans: '历史', hant: '歷史'}) + `</span>
<span class="oo-ui-indicatorElement-indicator oo-ui-indicatorElement-noIndicator oo-ui-image-progressive"></span>
</a>
</span>`);
$(document).ajaxStop(function() {
$(".tool-init-comment-historybutton").css("display", "");
});
$(".tool-init-comment-historybutton-tooltip").css({
"display": "none",
"width": "auto",
"background-color": "black",
"color": "#fff",
"border-radius": "6px",
"padding": "5px 0",
"position": "absolute",
"z-index": "1",
"flex-wrap": "wrap",
"justify-content": "center",
"align-items": "center",
"align-content": "center"
});
String.format = function(format) {
var args = Array.prototype.slice.call(arguments, 1);
return format.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined' ? args[number] : match;
});
};
function equal(a, b) {
return JSON.stringify(a) === JSON.stringify(b);
}
function updateWorkingProgress(input_tooltip) {
if (jQuery.active === 1) {
input_tooltip[0].childNodes[0].nodeValue = conv({
hans: '搜寻完了',
hant: '搜尋完了'
});
} else input_tooltip[0].childNodes[0].nodeValue = mw.format(conv({
hans: '正在努力搜寻中(查询:$1)',
hant: '正在努力搜尋中(查詢:$1)'
}), jQuery.active);
}
function findComment(input_html, input_comment_id) {
return new RegExp(input_comment_id + '"></span>([\\s\\S]*?)' + input_comment_id).exec(input_html.replaceAll(' class="userlink"', '').trim());
}
function hashCode(s) {
return s.split("").reduce(function(a, b) {
a = ((a << 5) - a) + b.charCodeAt(0);
return a & a;
}, 0);
}
//lol mobile web can't add preview because "Access to XMLHttpRequest at 'url' from origin 'https://zh.m.wikipedia.org' has been blocked by CORS policy"
$.fn.addPreview = function() {
//console.log("preview gogo" + $(this).find("a").attr("href"));
let url = $(this).find("a").attr("href");
let item = $(this);
let item_tooltip = item.parents('div');
item.attr("haspreview", "true");
$.get(url, function(html) {
//console.log("preview going" + item.find("a").attr("href"));
let diff = $('<div/>').html(html).find('.diff');
diff.find(".diff-title").remove();
//diff.css("display","inline-block");
diff.find("td").css("font-size", "10px");
diff = diff[0].outerHTML;
item.append('<div class="diff-comment-preview" style="display: none;">' + diff + '</div>');
//console.log(item[0].innerHTML)
item.find(".diff-comment-preview").css({
"overflow": "auto",
"display": "none",
"min-width": "auto",
"width": "14cm",
"height": "auto",
"backgroundColor": '#000',
"position": 'absolute',
"transform": 'translate(-50%, -50%)',
"borderRadius": '5%',
"boxShadow": '0 0 20px rgba(16, 0, 54, 0.2)',
"transition": '0.1s ease-out',
"float": "left",
"z-index": "2"
//"flex-wrap": "wrap",
//"justify-content": "center",
//"align-items": "center",
//"align-content": "center"
});
const move = (e) => {
let offset = item.offset();
let show_diff = item[0].querySelector('.diff-comment-preview');
const rect = show_diff.getBoundingClientRect();
if ((e.clientX - 25) < rect.width) {
show_diff.style.left = (e.pageX - offset.left + rect.width / 2 + 25) + "px";
} else {
show_diff.style.left = (e.pageX - offset.left - rect.width / 2 - 25) + "px";
}
if (e.clientY + rect.height * 0.15 < rect.height / 2) {
show_diff.style.top = (e.pageY - offset.top + rect.height / 2) + "px";
} else {
show_diff.style.top = (e.pageY - offset.top) + "px";
}
};
//For mouse
item.find(".date-item").on("mousemove", (e) => {
move(e);
});
item.find(".date-item").hover(function() {
item.find(".diff-comment-preview").css("display", "");
}, function() {
item.find(".diff-comment-preview").css("display", "none");
});
updateWorkingProgress(item_tooltip);
});
};
$.fn.removeDuplicate = function(input_comment) {
let temp_comment = hashCode(input_comment);
$(this).find('*').each(function() {
//console.log("ready remove")
if (typeof $(this).attr("data-old_comment") === 'undefined') {
return;
}
//console.log(temp_comment+"vs"+$(this).attr("data-old_comment"));
//console.log($(this).attr("data-old_comment") === temp_comment)
if ($(this).attr("data-old_comment") === temp_comment) {
temp_comment = $(this).attr("data-old_comment");
$(this).remove();
//console.log("removed")
} else {
//console.log($(this).attr("data-old_comment") + " vs " + temp_comment);
temp_comment = $(this).attr("data-old_comment");
if ($(this).attr("haspreview") !== 'true') $(this).addPreview();
}
});
};
$.fn.addToolTipItem = function(input_item, input_diff) {
//console.log(input_item.old_comment)
//try{
let display_item = new DOMParser().parseFromString('<div data-old_id="' + input_item.old_id + '" data-old_comment="' + hashCode(input_item.old_comment) + '"><div class="date-item">' + input_item.timestamp.toISOString() + ' </div><a href="' + input_item.url + '">url</a></div>', 'text/html').body.firstChild;
//console.log(display_item);
let children = Array.prototype.slice.call($(this)[0].children);
// Find the one we should insert in front of
let before = children.find(function(element) {
return parseInt(element.getAttribute("data-old_id"), 10) < input_item.old_id;
});
$(this)[0].insertBefore(display_item, before);
$(this).removeDuplicate(input_item.comment);
};
//oldest_old_id is oldest page id has target comment
function isOldPageHasntOldComment(oldest_old_id, input_old_id) {
return oldest_old_id !== "-1" && parseInt(oldest_old_id, 10) > parseInt(input_old_id, 10);
}
window.wikipage_history_req = {};
function compareOldComment(input_edit, input_comment, input_comment_id, input_tooltip) {
let old_id = input_edit.id;
let timestamp = new Date(input_edit.timestamp);
if (isOldPageHasntOldComment(input_tooltip.attr("oldest_old_id"), old_id)) {
//console.log("returned!!! out");
return;
}
//new mw.Api().get({
// "action": "discussiontoolspageinfo",
// "format": "json",
// "formatversion": 2,
// "uselang": mw.config.get("wgPageViewLanguage"),
// "page": mw.config.get("wgPageName")
// "prop": "threaditemshtml"
// "excludesignatures": true
// "oldid": old_id
//})
//$..[?(@ && @.id=='c-Benevolen-20240301000700-Wongan4614-20240229185600')]
//change to api for support mobile web
let req = new mw.Api().get({
"action": "parse",
"format": "json",
"formatversion": 2,
"oldid": old_id,
"prop": "text",
"useskin": mw.config.get('skin')
}).done(function(old_page_json) {
if (old_page_json.hasOwnProperty("error")) {
//console.log("deteted"+old_id)
return;
}
let old_page = old_page_json.parse.text;
updateWorkingProgress(input_tooltip);
if (isOldPageHasntOldComment(input_tooltip.attr("oldest_old_id"), old_id)) {
//console.log("returned!!! in");
return;
}
let old_comment = findComment(old_page, input_comment_id);
if (old_comment === null) {
let start_item = {
"isDiff": false,
"timestamp": timestamp,
"old_id": old_id,
"comment": input_comment,
"old_comment": '',
"url": "https://" + mw.config.get("wgServerName") + "/w/index.php?title=" + encodeURIComponent(mw.config.get("wgPageName")) + "&diff=next&oldid=" + old_id //+ "#" + input_comment_id
};
input_tooltip.addToolTipItem(start_item);
input_tooltip.attr("oldest_old_id", old_id);
//console.log(start_item);
for (const [ongoing_req_old_id, ongoing_req] of Object.entries(window.wikipage_history_req[input_comment_id])) {
if (isOldPageHasntOldComment(old_id, ongoing_req_old_id)) {
ongoing_req.abort();
//console.log(ongoing_req_old_id + " is aborted!!!");
delete window.wikipage_history_req[input_comment_id][ongoing_req_old_id];
}
}
return;
}
//notice: comment will not change to old_comment
//that mean it can only detect is comment same as current
if (input_comment !== old_comment[0]) {
let item = {
"isDiff": true,
"url": "https://" + mw.config.get("wgServerName") + "/w/index.php?title=" + encodeURIComponent(mw.config.get("wgPageName")) + "&diff=next&oldid=" + old_id, //+ "#" + input_comment_id
"timestamp": timestamp,
"old_id": old_id,
"comment": input_comment,
"old_comment": old_comment[0]
};
//console.log(item);
input_tooltip.addToolTipItem(item);
}
});
if (!window.wikipage_history_req.hasOwnProperty(input_comment_id)) {
window.wikipage_history_req[input_comment_id] = {};
}
window.wikipage_history_req[input_comment_id][old_id] = {};
window.wikipage_history_req[input_comment_id][old_id] = req;
}
function search(input_maxSearch, input_comment, input_comment_id, input_tooltip) {
updateWorkingProgress(input_tooltip);
if (input_maxSearch >= window.maxSearch) {
return;
}
if (window.wikipage_history_list.length >= (input_maxSearch + 1) * 20) {
//console.log("using preload");
for (j = input_maxSearch * 20; j < (input_maxSearch + 1) * 20; j++) {
if (isOldPageHasntOldComment(input_tooltip.attr("oldest_old_id"), window.wikipage_history_list[j].id)) {
return;
}
compareOldComment(window.wikipage_history_list[j], input_comment, input_comment_id, input_tooltip);
}
search(input_maxSearch + 1, input_comment, input_comment_id, input_tooltip);
} else {
$.get(window.wikipage_history_url, function(data) {
window.wikipage_history_list = window.wikipage_history_list.concat(data.revisions);
data.revisions.forEach(edit => {
//console.log(window.wikipage_history_url);
compareOldComment(edit, input_comment, input_comment_id, input_tooltip);
});
if (data.hasOwnProperty('older')) {
//console.log(window.wikipage_history_url);
window.wikipage_history_url = data.older;
if (isOldPageHasntOldComment(input_tooltip.attr("oldest_old_id"), data.older.split("older_than=").slice(-1))) {
return;
}
search(input_maxSearch + 1, input_comment, input_comment_id, input_tooltip);
} else {
return;
}
});
}
}
$(".tool-init-comment-historybutton").click(function() {
let tooltip = $(this).find(".tool-init-comment-historybutton-tooltip");
if (tooltip.css("display") === "none") {
tooltip.css("display", "flex");
} else {
tooltip.css("display", "none");
}
if (tooltip.attr("data-hasrun") === "false") {
try {
tooltip.attr("data-hasrun", "true");
let comment_id = $(this).prev(".ext-discussiontools-init-replylink-buttons").attr("data-mw-thread-id");
let comment = findComment($('html').html(), comment_id)[0];
tooltip.append(conv({
hans: '正在努力搜寻中',
hant: '正在努力搜尋中'
}));
//console.log(comment);
window.maxSearch = 100;
if (typeof window.wikipage_history_list === 'undefined') {
window.wikipage_history_list = [];
}
if (typeof window.wikipage_history_url === 'undefined') {
window.wikipage_history_url = 'https://' + mw.config.get("wgServerName") + '/w/rest.php/v1/page/' + encodeURIComponent(mw.config.get("wgPageName")) + '/history';
}
search(0, comment, comment_id, tooltip);
} catch (e) {
console.log(e);
}
}
});
});
});