User:What7what8/CommentHistoryTool.js

维基百科,自由的百科全书

注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ 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() + '&nbsp;&nbsp;</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("正在努力搜尋中");
					//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);
				}
			}
		});
	});
});