E-H Visited

Marks visited galleries.

À partir de 2019-04-09. Voir la dernière version.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name           E-H Visited
// @description    Marks visited galleries.
// @author         Hen Tie
// @homepage       https://hen-tie.tumblr.com/
// @namespace      https://greasyfork.org/en/users/8336
// @include        /https?:\/\/(e-|ex)hentai\.org\/.*/
// @require        https://code.jquery.com/jquery-3.3.1.min.js
// @require        https://greasyfork.org/scripts/381436-gmshim/code/GMshim.js
// @grant          GM_setValue
// @grant          GM_getValue
// @icon           https://i.imgur.com/pMMVGRx.png
// @version        3.6
// ==/UserScript==
// 2019 fork of exvisited (sleazyfork.org/en/scripts/22270)
// bug reports: greasyfork.org/en/forum/post/discussion?script=377945

/*════════════════════╗
║    configuration    ║
╚════════════════════*/
// true: adds column with eye icon to viewed galleries
// false: truly minimal, hover on gallery title for timestamp
var minimalAddColumn = true;
// true: (minimalAddColumn must also be true) replace eye icon with timestamp text
var minimalShowText = false;
/*═══════════════════*/

var storageName = "ehVisited";
var sto = localStorage.getItem(storageName) ? localStorage.getItem(storageName) : '{"data":{}}';
var vis = JSON.parse(sto);
var spl = document.URL.split("/");
var d1 = spl[3];
var d2 = spl[4];
var d3 = spl[5];
var css = GM_getValue("css") ? GM_getValue("css") : "box-shadow: inset 0 0 0 500px rgba(2, 129, 255, .2) !important;"; //default highlight colour
var postInfiniteScroll = 0;
var headerGalLen = 1; // yes i=1, this skips the table header
var galLen = 0;
var observer = new MutationObserver(function () {
	// track galleries opened on-site
	$('a').on('mouseup', function () {
		var spl = this.href.split("/");
		var d1 = spl[3]
		var d2 = spl[4];
		var d3 = spl[5];

		if (d1 == "g") {
			var c = d2 + "." + d3;
			vis.data[c] = Date.now();
			localStorage.setItem(storageName, JSON.stringify(vis));
		}
	});
	postInfiniteScroll = 1;
	headerGalLen = galLen = $("table.itg>tbody>tr, .itg .gl1t").length - 50;
	ehvTimestamp();
});

vis.data = !vis.data ? Array() : vis.data;

// convert keywords to CSS
if (css === "initial") {
	css = "box-shadow: inset 0 0 0 500px rgba(2, 129, 255, .2) !important;";
} else if (css === "none") {
	css = "";
}

// localstorage unsupported warning
if (typeof (Storage) == "undefined") {
	alert("E-H Visited:\nYour browser does not support localStorage :(");
}

// get time difference in words
function timeDifference(current, previous, abbreviate) {
	var msPerMinute = 60 * 1000;
	var msPerHour = msPerMinute * 60;
	var msPerDay = msPerHour * 24;
	var msPerMonth = msPerDay * 30;
	var msPerYear = msPerDay * 365;
	var elapsed = current - previous;

	if (elapsed < msPerMinute) {
		return Math.round(elapsed / 1000) + ((typeof abbreviate !== 'undefined') ? '&nbsp;sec' : ' seconds ago');
	} else if (elapsed < msPerHour) {
		return Math.round(elapsed / msPerMinute) + ((typeof abbreviate !== 'undefined') ? '&nbsp;min' : ' minutes ago');
	} else if (elapsed < msPerDay) {
		return Math.round(elapsed / msPerHour) + ((typeof abbreviate !== 'undefined') ? '&nbsp;hrs' : ' hours ago');
	} else if (elapsed < msPerMonth) {
		return Math.round(elapsed / msPerDay) + ((typeof abbreviate !== 'undefined') ? '&nbsp;days' : ' days ago');
	} else if (elapsed < msPerYear) {
		return Math.round(elapsed / msPerMonth) + ((typeof abbreviate !== 'undefined') ? '&nbsp;mos' : ' months ago');
	} else {
		return Math.round(elapsed / msPerYear) + ((typeof abbreviate !== 'undefined') ? '&nbsp;yrs' : ' years ago');
	}
}

function ehvExport(message) {
	var data = "";
	for (var d in vis.data) {
		data += d + ":" + vis.data[d] + ";";
	}
	if ($('.ehv-exported-data').length) {
		$('.ehv-exported-data').remove();
	}
	$('.ehv-controls').append('<ehv class="ehv-exported-data"><strong>' + message + '</strong><textarea class="ehv-exported-data-text">' + data + '</textarea></ehv>');
}

function ehvTimestamp() {
	observer.disconnect();
	var list = $("table.itg>tbody>tr").has('.glhide, .gldown'); //present only in list views
	var thumb = $(".itg .gl1t"); //present only in thumbnail view
	var gid;
	var d;
	var galleryId;

	// check current view
	if (list.length > 0) {
		if ($('.gl1e').length) { //extended
			for (i = galLen; i < list.length; i++) {
				gid = $(list[i]).find(".gl1e a").attr("href").split("/");
				galleryId = gid[4] + "." + gid[5];
				if (vis.data[galleryId] != undefined) {
					d = new Date(vis.data[galleryId]);
					$(list[i]).addClass("ehv-visited");
					//check for fav pages
					if ($(list[i]).find('.gl3e').children('div').length >= 7) { //date favourited div is present
						$(list[i]).find('.gl3e > div:last-child').append("<br><ehv class='ehv-extended-favs'>\uD83D\uDC41" + timeDifference(Date.now(), vis.data[galleryId]) + "<br>" + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ")</ehv>");
					} else {
						$(list[i]).find('.gl3e').append("<ehv class='ehv-extended'>\uD83D\uDC41" + timeDifference(Date.now(), vis.data[galleryId]) + "<br>" + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ")</ehv>");
					}
				}
			}
		} else if ($('.gl1c').length) { //compact
			var borderColour = $('.gl1c').first().css('border-top-color'); //border colour different between domains
			if (!postInfiniteScroll) {
				$('table.itg tbody>tr:first-child th:nth-child(2)').after('<th>Visited</th>');
			}
			for (i = headerGalLen; i < list.length; i++) {
				gid = $(list[i]).find(".glname a").attr("href").split("/");
				galleryId = gid[4] + "." + gid[5];
				if (vis.data[galleryId] != undefined) {
					d = new Date(vis.data[galleryId]);
					$(list[i]).addClass("ehv-visited");
					$(list[i]).children('.gl2c').after('<td class="ehv-compact" style="border-color:' + borderColour + ';"><ehv>' + timeDifference(Date.now(), vis.data[galleryId], true) + "<br>(" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ')<br>' + d.getFullYear().toString().substr(2) + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + '</ehv></td>');
				} else {
					$(list[i]).children('.gl2c').after('<td class="ehv-compact" style="border-color:' + borderColour + ';"></td>');
				}
			}
		} else { //minimal
			if (minimalAddColumn && !postInfiniteScroll) {
				$('table.itg tbody>tr:first-child th:nth-child(2)').after('<th title="E-H Visited: Hover for timestamps">\uD83D\uDC41</th>');
			}
			for (i = headerGalLen; i < list.length; i++) {
				gid = $(list[i]).find(".glname a").attr("href").split("/");
				galleryId = gid[4] + "." + gid[5];
				if (minimalAddColumn) {
					if (vis.data[galleryId] != undefined) {
						d = new Date(vis.data[galleryId]);
						$(list[i]).addClass("ehv-visited");
						$(list[i]).children('.glname')[0].setAttribute("title", 'E-H Visited: ' + timeDifference(Date.now(), vis.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate());
						if (minimalShowText) {
							$(list[i]).children('.gl2m').after('<td class="ehv-minimal-text"><ehv>' + timeDifference(Date.now(), vis.data[galleryId], true) + "<br>(" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ')<br>' + d.getFullYear().toString().substr(2) + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + '</ehv></td>');
						} else {
							$(list[i]).children('.gl2m').after('<td class="ehv-minimal" title="E-H Visited: ' + timeDifference(Date.now(), vis.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + '"><ehv>\uD83D\uDC41</ehv></td>');
						}
					} else {
						$(list[i]).children('.gl2m').after('<td class="ehv-minimal"></td>');
					}
				} else {
					if (vis.data[galleryId] != undefined) {
						d = new Date(vis.data[galleryId]);
						$(list[i]).addClass("ehv-visited");
						$(list[i]).children('.glname')[0].setAttribute("title", 'E-H Visited: ' + timeDifference(Date.now(), vis.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate());
					}
				}
			}
		}
	} else if (thumb.length > 0) { //thumbnail
		for (var i = galLen; i < thumb.length; i++) {
			gid = $(thumb[i]).find(".gl3t a").attr("href").split("/");
			galleryId = gid[4] + "." + gid[5];
			if (vis.data[galleryId] != undefined) {
				d = new Date(vis.data[galleryId]);
				$(thumb[i]).addClass("ehv-visited");
				$(thumb[i]).children('.gl5t').after("<ehv class='ehv-thumbnail'>\uD83D\uDC41" + timeDifference(Date.now(), vis.data[galleryId]) + " (" + d.getHours().toString().padStart(2, '0') + ":" + d.getMinutes().toString().padStart(2, '0') + ") " + d.getFullYear().toString() + "\u2011" + (d.getMonth() + 1) + "\u2011" + d.getDate() + "</ehv>");
			}
		}
	} else {
		console.log("E-H Visited:\n	Something is wrong, I don't know what view mode this is!\n	Bug reports: greasyfork.org/en/forum/post/discussion?script=377945");
	}
	observer.observe($('.itg').get(0), {
		childList: true,
		subtree: true
	});
}

$(function () {
	// track galleries opened on-site
	$('a').on('mouseup', function () {
		var spl = this.href.split("/");
		var d1 = spl[3]
		var d2 = spl[4];
		var d3 = spl[5];

		if (d1 == "g") {
			var c = d2 + "." + d3;
			vis.data[c] = Date.now();
			localStorage.setItem(storageName, JSON.stringify(vis));
		}
	});

	// track galleries opened indirectly (offsite link, shortcut file, context menu, bookmark, etc.)
	$(window).one('click scroll', function () {
		if (d1 == "g") {
			var c = d2 + "." + d3;
			vis.data[c] = Date.now();
			localStorage.setItem(storageName, JSON.stringify(vis));
		}
	});

	if (d1.substr(0, 1) == "?" || d1.substr(0, 1) == "#" || d1.substr(0, 1) == "f" || d1.substr(0, 1) == "t" || !d1) {
		var len = Object.keys(vis.data).length;
		var ehvClearConfirm = 0;

		$("#toppane").append("<ehv class='ehv-controls'>Galleries visited: " + len + " (<a href='javascript:;' class='ehv-import'>Import</a> / <a href='javascript:;' class='ehv-export'>Export</a> / <a href='javascript:;' class='ehv-merge'>Merge</a> / <a href='javascript:;' class='ehv-clear'>Clear</a> / <a href='javascript:;' class='ehv-css'>CSS</a>)</ehv>");

		$(".ehv-import").click(function () {
			var c = prompt("E-H Visited:\nPaste here to import, and overwrite current data.");
			if (c) {
				var d = JSON.parse('{"data":{}}');
				var sp = c.split(";");
				//sp = sp.filter(Boolean);
				for (var k in sp) {
					var s = sp[k].split(":");
					d.data[s[0]] = parseInt(s[1]);
				}
				localStorage.setItem(storageName, JSON.stringify(d))
				console.log(d);
				alert("E-H Visited:\nImported " + Object.keys(d.data).length + " entries.");
				location.reload();
			}
		});

		$(".ehv-export").click(function () {
			ehvExport('Exported entries:');
		});

		$(".ehv-css").click(function () {
			var c = prompt("E-H Visited:\nThis CSS is applied to visited galleries.\n('initial' to reset, or 'none' for no styling)", css);
			if (c) {
				GM_setValue("css", c);
				location.reload();
			}
		});

		$(".ehv-merge").click(function () {
			var c = prompt("E-H Visited:\nPaste here to import, and merge with current data.");
			if (c) {
				var d = JSON.parse('{"data":{}}');
				var sp = c.split(";");
				sp = sp.filter(Boolean);
				for (var k in sp) {
					var s = sp[k].split(":");
					d.data[s[0]] = parseInt(s[1]);
				}
				for (var i = 0; i < Object.keys(vis.data).length; i++) {
					d.data[Object.keys(vis.data)[i]] = vis.data[Object.keys(vis.data)[i]];
				}
				alert("E-H Visited\nMerged data, " + Object.keys(d.data).length + " unique entries.");
				localStorage.setItem(storageName, JSON.stringify(d));
				location.reload();
			}
		});

		$(".ehv-clear").click(function () {
			if (!ehvClearConfirm) {
				ehvClearConfirm = 1;
				$('.ehv-clear').append(': Are you sure?');
				ehvExport('Backup your current data:');
			} else {
				alert("E-H Visited:\nCleared all entries.");
				localStorage.removeItem(storageName);
				location.reload();
			}
		});

		// append icon friendly fonts to the calculated font stack
		var inheritFonts = $('body').css('font-family') + ', arial, symbola';
		$(`<style data-jqstyle='ehVisited'>
ehv { font-family:` + inheritFonts + ` }
.gl2c { width: 115px; }
.ehv-visited .gl3e { min-height: 206px; }
.ehv-visited .gl4e { min-height: 264px !important; }
.ehv-exported-data { display: block; }
.ehv-exported-data-text { display: block; margin: 0 auto; height: 5em; width: 50vw; padding: .25em; }
.ehv-minimal-text { text-align: center; display: block; }
.ehv-compact { border-style: solid; border-width: 1px 0; text-align: center; }
.ehv-extended { width: 120px; position: absolute; left: 3px; top: 172px; text-align: center; font-size: 8pt; line-height: 1.5; }
.ehv-extended-favs { padding: 3px 1px; display: block; line-height: 1.5; }
.ehv-thumbnail { display: block; text-align: center; margin: 3px 0 5px; line-height: 12px; }
.ehv-controls { padding: 3px 1px; text-align: center; display: block; }
table.itg > tbody > tr.ehv-visited, .gl1t.ehv-visited { ` + css + ` }
</style>`).appendTo("head");

		ehvTimestamp();
	}
});