// ==UserScript==
// @name F95zone marker
// @namespace http://tampermonkey.net/
// @version 0.1.3
// @description Marks F95Zone threads for future reference
// @author agreg
// @license MIT
// @match https://f95zone.to/*
// @icon https://www.google.com/s2/favicons?domain=f95zone.to
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// ==/UserScript==
(function() {
'use strict';
const THREADS = /^(https:\/\/f95zone.to)?\/threads\//;
const OP = '.message-threadStarterPost';
const OP_ICONS = `${OP} header .message-attribution-opposite`;
let urlId = s => (!THREADS.test(s) ? null : s.replace(THREADS, '').match(/^([^\/]+\.)?([0-9]+)/)[2]);
let $find = (s, e=document) => e.querySelector(s);
let $find_ = (s, e=document) => Array.from( e.querySelectorAll(s) );
let $parent = (e, check=()=>true) => (check(e.parentNode) ? e.parentNode : $parent(e.parentNode, check));
let $e = (tag, options={}, ...children) => {var e = Object.assign(document.createElement(tag), options);
children.forEach(x => e.append(x));
return e}
let $updData = (id, e, data=GM_getValue(id), upd={}) => {if (data) {
GM_setValue(id, Object.assign(data, upd));
e.classList[data.fade ? 'add' : 'remove']('-marker-fade');
e.classList[data.mark ? 'add' : 'remove']('-marker-mark');
e.title = data.info || "";
} else {
GM_deleteValue(id);
e.classList.remove('-marker-fade', '-marker-mark');
e.title = "";
}}
GM_addStyle(`.-marker-unmarked {opacity: 0.5} .-marker-marked {color: rgb(193, 88, 88)}
.-marker-fade:not(:hover) {opacity: 0.25} .-marker-fade:hover {outline: 2px solid black} .-marker-mark {outline: 2px solid grey}
.-marker-dialog {position: fixed; top: 30%; left: 30%; width: 40%; background: rgb(29, 31, 33); border-radius: 5px; z-index:1000}
.-marker-dialog > * {margin: 1em} .-marker-dialog textarea {width: calc(100% - 2em)}
.-marker-dialog .-marker-row > * {margin-left: .5em; margin-right: .5em}`);
$find_(".structItem-title").forEach(e => { // forum, similar threads
let _id = urlId(e.getAttribute('uix-data-href')||"");
_id && $updData(_id, $parent(e, x => x.classList.contains('structItem--thread')));
});
if (location.pathname.startsWith('/search/')) { // search results
$find_(".contentRow-title a").forEach(e => {
let _id = urlId(e.href||"");
console.log(e.href, _id)
_id && $updData(_id, $parent(e, x => /^li$/i.test(x.tagName)));
});
}
if (['/latest', '/sam/latest_alpha'].some(s => location.pathname.startsWith(s))) { // latest updates
new MutationObserver(mutations => mutations.forEach(m => Array.from(m.addedNodes).filter(e => e.tagName).forEach(node => {
console.warn(node, node.children);
$find_("a.resource-tile_link", node).forEach(e => {
let _id = urlId(e.href||"");
console.log(e.href, _id)
_id && $updData(_id, e);
});
}))).observe(document.body, {subtree: true, childList: true});
}
if (location.pathname.startsWith('/threads/') && $find(OP)) { // first page of a thread
var id = urlId(location.href);
var op = $find(OP);
var icons = $find(OP_ICONS);
var icon = $e('i', {className: "fas fa-star"})
var data = GM_getValue(id);
var _$updData = (upd={}) => {$updData(id, op, data, upd);
icon.classList.add(`-marker-${data ? "" : "un"}marked`);
icon.classList.remove(`-marker-${data ? "un" : ""}marked`)}
let $deleteMark = () => {if (confirm("Delete mark?")) {
$toggleEdit();
data = null;
_$updData();
}}
var edit = null;
let $toggleEdit = () => {
if (edit) {
edit.remove();
edit = null;
} else {
data = data || {};
document.body.append(edit = $e('div', {className: '-marker-dialog'},
$e('textarea', {placeholder: "Tooltip", value: data.info||"", oninput () {_$updData({info: this.value})}}),
$e('div', {className: '-marker-row'},
$e('label', {},
$e('input', {type: 'checkbox', checked: data.fade, onchange () {_$updData({fade: this.checked})}}),
$e('span', {innerText: "Fade"})),
$e('label', {},
$e('input', {type: 'checkbox', checked: data.mark, onchange () {_$updData({mark: this.checked})}}),
$e('span', {innerText: "Mark"}))),
$e('div', {className: '-marker-row'},
$e('button', {innerText: "OK", onclick: $toggleEdit}),
$e('button', {innerText: "Delete", onclick: $deleteMark}))));
}
}
if ( $find_('a', icons).some(e => e.innerText == "#1") ) {
_$updData();
icons.insertBefore($e('li', {}, $e('a', {href: location.href, onclick () {$toggleEdit(); return false}}, icon)),
icons.firstChild);
}
}
})();