Sleazy Fork is available in English.

E-H Visited

Marks visited galleries.

28.03.2019 itibariyledir. En son verisyonu görün.

// ==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
// @grant          GM_setValue
// @grant          GM_getValue
// @icon           https://i.imgur.com/pMMVGRx.png
// @version        3.0
// ==/UserScript==
// 2019 fork of exvisited (sleazyfork.org/en/scripts/22270)
// bug reports: greasyfork.org/en/forum/post/discussion?script=377945

/*═════════════════════════╦═════════════════════════════╦════════════════════════╗
║          IMPORT          ║           EXPORT            ║          CSS           ║
╠══════════════════════════╬═════════════════════════════╬════════════════════════╣
║ data format is unchanged ║ localstorage is impermanent ║ you can set custom css ║
║ should import from any   ║ but exporting is simple     ║ for marking viewed     ║
║ old exvisited scripts    ║ one click gives plain text  ║ galleries              ║
╚══════════════════════════╩═════════════════════════════╩═══════════════════════*/

var storageName = "ehVisited"; //name of object, to avoid clash with old installs
var url = document.URL;
var sto = localStorage.getItem(storageName) ? localStorage.getItem(storageName) : '{"data":{}}';
var vis = JSON.parse(sto);
var spl = url.split("/");
var d1 = spl[3]
var d2 = spl[4];
var d3 = spl[5];
var css = GM_getValue("css") ? GM_getValue("css") : "background:rgba(2, 129, 255, .2) !important"; //default highlight colour

if (css === "initial") {
	css = "background:rgba(2, 129, 255, .2) !important";
} else if (css === "none") {
	css = "";
}

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

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

// date.now shim (probably unnecessary)
if (!Date.now) {
	Date.now = function () {
		return new Date().getTime();
	};
}

Number.prototype.pad0 = function (length) {
	var result = this.toString();
	while (result.length < length) result = "0" + result;
	return result;
}

Object.size = function (obj) {
	var size = 0,
		key;
	for (key in obj) {
		if (obj.hasOwnProperty(key)) size++;
	}
	return size;
};

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 ehvTimestamp() {
	var list = $("table.itg>tbody>tr"); //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 = 0; 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");
					//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'>&#128065;" + timeDifference(Date.now(), vis.data[galleryId]) + "<br>" + d.getFullYear().toString() + "&#8209;" + (d.getMonth() + 1) + "&#8209;" + d.getDate() + " (" + d.getHours().pad0(2) + ":" + d.getMinutes().pad0(2) + ")</ehv>");
					} else {
						//empty div avoids nth-child styles meant for date favourited
						$(list[i]).find('.gl3e').append("<div></div><ehv class='ehv-extended'>&#128065;" + timeDifference(Date.now(), vis.data[galleryId]) + "<br>" + d.getFullYear().toString() + "&#8209;" + (d.getMonth() + 1) + "&#8209;" + d.getDate() + " (" + d.getHours().pad0(2) + ":" + d.getMinutes().pad0(2) + ")</ehv>");
					}
				}
			}
		} else if ($('.gl1c').length) { //compact
			var borderColour = $('.gl1c').first().css('border-top-color'); //border colour different between domains
			$('table.itg tbody>tr:first-child th:nth-child(2)').after('<th>Visited</th>');
			for (i = 1; 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().pad0(2) + ":" + d.getMinutes().pad0(2) + ')<br>' + d.getFullYear().toString().substr(2) + "&#8209;" + (d.getMonth() + 1) + "&#8209;" + d.getDate() + '</ehv></td>');
				} else {
					$(list[i]).children('.gl2c').after('<td class="ehv-compact" style="border-color:' + borderColour + ';"></td>');
				}
			}
		} else { //minimal
			$('table.itg tbody>tr:first-child th:nth-child(2)').after('<th title="E-H Visited: Hover for timestamps">&#128065;</th>');
			for (i = 1; 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('.gl2m').after('<td class="ehv-minimal" title="E-H Visited: ' + timeDifference(Date.now(), vis.data[galleryId]) + " (" + d.getHours().pad0(2) + ":" + d.getMinutes().pad0(2) + ") " + d.getFullYear().toString() + "&#8209;" + (d.getMonth() + 1) + "&#8209;" + d.getDate() + '">&#128065;</td>');
				} else {
					$(list[i]).children('.gl2m').after('<td class="ehv-minimal"></td>');
				}
			}
		}
	} else if (thumb.length > 0) { //thumbnail
		for (var i = 0; i < thumb.length; i++) {
			gid = $(thumb[i]).find(".glname 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'>&#128065;" + timeDifference(Date.now(), vis.data[galleryId]) + " (" + d.getHours().pad0(2) + ":" + d.getMinutes().pad0(2) + ") " + d.getFullYear().toString() + "&#8209;" + (d.getMonth() + 1) + "&#8209;" + 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");
	}
}

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

	$('a').bind('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));
		}
	});

	if (d1.substr(0, 1) == "?" || d1.substr(0, 1) == "#" || d1.substr(0, 1) == "f" || d1.substr(0, 1) == "t" || !d1) {
		var len = Object.size(vis.data);
		$("#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-css'>CSS</a>)</ehv>");

		$(".ehv-export").click(function () {
			var e = "";
			for (var d in vis.data) {
				e += d + ":" + vis.data[d] + ";";
			}
			prompt("E-H Visited:\nYour data has been exported.", e);
		});

		$(".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(";");
				for (var k in sp) {
					var s = sp[k].split(":");
					d.data[s[0]] = parseInt(s[1]);
				}

				alert("Imported " + Object.size(d.data) + " entries.");
				localStorage.setItem(storageName, JSON.stringify(d))
				location.reload();

			}
		});

		$(".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();
			}
		});

		ehvTimestamp();

		$("<style data-jqstyle='ehVisited'>.gl2c{width:115px;}.gl3e>div:nth-child(6){left:unset;width:100%;text-align:center;}" + //overrides
			".ehv-compact{border-style:solid;border-width:1px 0;text-align:center;}" +
			".ehv-extended{width:120px;position:absolute;left:3px;top:180px;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{text-align:center;display:block;}" +
			"table.itg>tbody>tr.ehv-visited, .gl1t.ehv-visited{" + css + "}" +
			"</style>").appendTo("head");
	}
});