// ==UserScript==
// @name Watches Favorites Viewer
// @namespace Violentmonkey Scripts
// @match *://*.furaffinity.net/*
// @require https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.4.4/lz-string.min.js
// @grant none
// @version 1.4.2
// @author Midori Dragon
// @description Scans the Favorites of your Watches for new Favorites and shows a Button to view these (if any where found). (Works like Submission Page)
// @icon https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png?v2
// @homepageURL https://greasyfork.org/de/scripts/463464-watches-favorites-viewer
// @supportURL https://greasyfork.org/de/scripts/463464-watches-favorites-viewer/feedback
// @license MIT
// ==/UserScript==
// jshint esversion: 8
//User Options:
let showLoadLastXFavsButton = JSON.parse(localStorage.getItem("wfsetting_1"));
if (showLoadLastXFavsButton == null || showLoadLastXFavsButton == undefined)
showLoadLastXFavsButton = false;
let maxFavsLength = +localStorage.getItem("wfsetting_2");
if (maxFavsLength == null || maxFavsLength == undefined || maxFavsLength == 0 || isNaN(maxFavsLength))
maxFavsLength = 100;
let maxAmountRequests = +localStorage.getItem("wfsetting_3");
if (maxAmountRequests == null || maxAmountRequests == undefined || maxAmountRequests == 0 || isNaN(maxAmountRequests))
maxAmountRequests = 2;
let doImmediateScan = JSON.parse(localStorage.getItem("wfsetting_6"));
if (doImmediateScan == null || doImmediateScan == undefined)
doImmediateScan = false;
if (window.parent !== window) return;
let lastFavs = {};
let _running = false;
let exButtonsShown = false;
let firstStart = false;
let wfButton;
let settingsCount = 0;
let currentLength = 0;
let totalLength = 0;
let percent = 0;
let exSettings = JSON.parse(localStorage.getItem("wfsettings")) || false;
let color = "color: blue";
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)
color = "color: aqua";
if (exSettings)
console.info(`%cSettingsPage: ${GM_info.script.name} v${GM_info.script.version}`, color);
else
console.info(`%cRunning: ${GM_info.script.name} v${GM_info.script.version} (Settings: "LastX = ${showLoadLastXFavsButton}", "MaxLength = ${maxFavsLength}", "MaxRequests = ${maxAmountRequests}", "ImmediateScan = ${doImmediateScan}")`, color);
let excludedUsers = JSON.parse(localStorage.getItem("excludedUsers")) || [];
let clicked = JSON.parse(localStorage.getItem("clicked")) || false;
Object.defineProperty(window, "running", {
get() {
return _running;
},
set(value) {
_running = value;
wfButton.setAttribute("loading", value);
if (running) {
localStorage.setItem("wfloadingstate", "running");
} else {
localStorage.setItem("wfloadingstate", "finished");
localStorage.removeItem("wfloadingusers");
localStorage.removeItem("wfloadingpercent");
}
},
});
// Set state to interrupted if tab is closed while running
window.addEventListener("beforeunload", () => {
if (running) localStorage.setItem("wfloadingstate", "interrupted");
});
if (window.location.toString().includes("buddylist")) {
const controlPanel = document.getElementById("controlpanelnav");
controlPanel.innerHTML += "<br><br>";
const showExButton = document.createElement("button");
showExButton.type = "button";
showExButton.className = "button standard mobile-fix";
showExButton.textContent = exButtonsShown ? "Hide WF Buttons" : "Show WF Buttons";
showExButton.onclick = function () {
exButtonsShown = !exButtonsShown;
showExButton.textContent = exButtonsShown ? "Hide WF Buttons" : "Show WF Buttons";
exButtonsShown ? addExcludeButtons() : removeExcludeButtons();
};
controlPanel.appendChild(showExButton);
}
if (!JSON.parse(localStorage.getItem("lastFavs"))) firstStart = true;
if (!clicked) createWFButton();
if (window.location.toString().includes("submissions") && clicked) {
localStorage.setItem("clicked", false.toString());
createWFDocument();
}
addExSettings();
if (window.location.toString().includes("controls/settings")) {
addExSettingsSidebar();
if (exSettings) createSettings();
}
async function waitForBuddyListOnePageReady() {
return new Promise((resolve) => {
const intervalId = setInterval(() => {
let value = localStorage.getItem("buddyListOnePageReady");
if (value == undefined || value == "true") {
clearInterval(intervalId);
resolve();
}
}, 100);
});
}
// Add exclude buttons
async function addExcludeButtons() {
// Wait for buddylist to load
await waitForBuddyListOnePageReady();
const watchers = document.querySelectorAll("div.flex-item-watchlist.aligncenter");
for (const watcher of watchers) {
let user = watcher.querySelector("a[href]").href;
if (user.endsWith("/"))
user = user.slice(0, -1);
user = user.substring(user.lastIndexOf("/") + 1, user.length);
const excludeButton = document.createElement("button");
excludeButton.id = "excludeButton_" + user;
excludeButton.type = "button";
excludeButton.className = "button standard mobile-fix";
if (excludedUsers.includes(user))
excludeButton.textContent = "^ WF Include ^";
else
excludeButton.textContent = "^ WF Exclude ^";
excludeButton.addEventListener("click", () => toggleExcludeUser(user, excludeButton));
watcher.style.paddingBottom = "18px";
watcher.appendChild(excludeButton);
}
}
// Remove exclude buttons
async function removeExcludeButtons() {
let buttons = document.querySelectorAll("button[id^=excludeButton]");
for (const button of buttons) {
button.parentNode.style.paddingBottom = "";
button.parentNode.removeChild(button);
}
}
// Toggle exclude user
async function toggleExcludeUser(user, button) {
if (excludedUsers.includes(user)) {
// Remove user from excludedUsers
excludedUsers = excludedUsers.filter((name) => name !== user);
if (button) button.textContent = "^ WF Exclude ^";
console.log('Including: "' + user + '"');
} else {
// Add user to excludedUsers
excludedUsers.push(user);
if (button) button.textContent = "^ WF Include ^";
console.log('Excluding: "' + user + '"');
}
localStorage.setItem("excludedUsers", JSON.stringify(excludedUsers));
}
// Creating the WFButton and loading the favs
async function createWFButton(again) {
if (window.location.toString().includes("buddylist") || exSettings)
return;
// Create WFButton
wfButton = document.createElement("a");
wfButton.id = "wfButton";
wfButton.className = "notification-container inline";
wfButton.title = "Start a WF scan";
wfButton.textContent = "WF Scan";
wfButton.style.cursor = "pointer";
const messageBar = document.getElementsByClassName("message-bar-desktop")[0];
messageBar.appendChild(wfButton);
lastFavs = JSON.parse(localStorage.getItem("lastFavs"));
// Check loadingstate and wait for other instance to finish
let finished = false;
let intSavedUsers;
const state = localStorage.getItem("wfloadingstate");
if (state && state !== "finished") {
console.log("Other WF instance found copying...");
running = true;
let status = await waitForOtherInstance();
finished = status.successfull;
if (finished)
console.log("Copying instance finished successfull");
else
console.log("Copying instance not finished");
intSavedUsers = status.intSavedUsers || [];
}
if (again) {
wfButton.onclick = () => startWFScan(finished, intSavedUsers);
running = false;
return;
}
if (doImmediateScan || finished)
startWFScan(finished, intSavedUsers);
else {
wfButton.onclick = () => startWFScan(finished, intSavedUsers);
running = false;
}
}
async function startWFScan(finished, intSavedUsers)
{
let newFavs;
running = true;
wfButton.title = "Watches Favorites Notifications";
wfButton.textContent = "WF: 0%";
if (finished) {
// Load finished favs
newFavs = JSON.parse(await decompressString(localStorage.getItem("wfloading")));
} else {
// Load new favs
newFavs = await loadUnreadFavsAll(maxFavsLength, intSavedUsers);
newFavs = Array.from(newFavs);
newFavs = newFavs.map((newFav) => newFav.outerHTML);
}
// Update WFButton
const totalLength = newFavs.length;
if (totalLength !== 0) {
wfButton.onclick = loadWFDocument;
wfButton.textContent = `${totalLength}WF`;
} else if (firstStart) {
// Replace WFButton with Ready Text
wfButton.textContent = "WF Ready";
wfButtonClone = wfButton.cloneNode(true);
wfButtonClone.setAttribute("loading", false);
wfButtonClone.onclick = () => location.reload();
wfButton.parentNode.replaceChild(wfButtonClone, wfButton);
} else {
wfButton.parentNode.removeChild(wfButton);
}
// Compress and save new favs
const favsComp = await compressString(JSON.stringify(newFavs));
localStorage.setItem("favs", favsComp);
console.log("Finished scanning");
console.log(`There are "${totalLength}" unseen Favs`);
running = false;
// Show last XFavs button if there are no new favs
if (totalLength === 0 && !firstStart) {
if (showLoadLastXFavsButton)
createLastXFavsButton();
else {
currentLength = 0;
percent = 0;
await createWFButton(true);
wfButton.textContent = "WF Scan again";
}
}
firstStart = false;
}
// Waiting for other WF instance
async function waitForOtherInstance() {
return new Promise((resolve, reject) => {
// Get current loadingstate
let state = localStorage.getItem("wfloadingstate");
if (state === null) {
resolve({ successfull: false });
return;
}
let lpercent = 0;
let intSavedUsers = [];
// Check loadingstate
const intervalId = setInterval(() => {
state = localStorage.getItem("wfloadingstate");
if (state === "finished") {
clearInterval(intervalId);
resolve({ successfull: true });
} else if (state === "interrupted") {
clearInterval(intervalId);
intSavedUsers = JSON.parse(localStorage.getItem("wfloadingusers")) || [];
resolve({ successfull: false, intSavedUsers: intSavedUsers });
} else {
percent = localStorage.getItem("wfloadingpercent");
if (percent !== lpercent) {
lpercent = percent;
console.log(`Copying: ${percent}%`);
wfButton.textContent = `WF: ${percent}%`;
}
}
}, 100);
});
}
// Loads the WFDocument
async function loadWFDocument() {
localStorage.setItem("lastFavs", JSON.stringify(lastFavs));
localStorage.setItem("clicked", true.toString());
window.location.href = "https://www.furaffinity.net/msg/submissions/";
}
// Creating the WFDocument to view the favs
async function createWFDocument() {
const standardPage = document.getElementById("standardpage");
const messageCenter = document.getElementById("messagecenter-submissions");
const emptyElem = messageCenter.querySelector('div[class="no-messages"]');
if (emptyElem) emptyElem.remove();
const header = standardPage.querySelector('div[class="section-header"] h2');
header.textContent = "Watches Favorites";
const oldNewButtonsButtonsTop = standardPage.querySelector('div[class="aligncenter"][style]');
oldNewButtonsButtonsTop.remove();
const selectionButtons = standardPage.querySelector('button[class="standard check-uncheck"]').parentNode.parentNode.parentNode;
selectionButtons.remove();
const oldNewButtonsBottom = messageCenter.parentNode.querySelector('div[class="aligncenter"]');
oldNewButtonsBottom.remove();
const galleries = document.querySelectorAll('div[class="notifications-by-date"]');
galleries.forEach((gallery) => gallery.remove());
let gallery = document.getElementById("gallery-0");
if (!gallery) {
gallery = document.createElement("section");
gallery.id = "gallery-0";
gallery.className = "gallery messagecenter with-checkboxes s-250";
messageCenter.appendChild(gallery);
}
gallery.innerHTML = "";
const favsDecomp = await decompressString(localStorage.getItem("favs"));
const figures = JSON.parse(favsDecomp);
const parser = new DOMParser();
const figureElements = figures.map((figure) => parser.parseFromString(figure, "text/html").body.firstChild);
console.log(`Loading "${figureElements.length}" figures`);
figureElements.forEach((figure) => gallery.appendChild(figure));
}
// Loading all unseen favs
async function loadUnreadFavsAll(maxFavsLength, intSavedUsers = []) {
// Getting watchers
const watchers = await getWatchers();
totalLength = watchers.length;
console.log(`You are watching "${totalLength}" people`);
console.log("Scanning for unseen Favs...");
// Getting lastFavs
let progress = { newFavs: [], percent: 0, intSavedUsers: intSavedUsers, currScanFavs: [] };
let newFavsAll = [];
let promises = [];
let semaphore = new Semaphore(maxAmountRequests);
for (const watcher of watchers) {
promises.push(
semaphore.acquire().then(async () => {
try {
const watcherLink = watcher.querySelector("a").href;
if (!intSavedUsers.includes(watcherLink)) {
// Getting newFavs from watcher
progress = await getUnreadFavsWatcher(watcherLink, maxFavsLength, progress);
if (progress.newFavs) {
newFavsAll = newFavsAll.concat(progress.newFavs);
}
// Updating WF Button prefix
if (firstStart) {
wfButton.textContent = `WF Initializing: ${Math.round(percent)}%`;
} else {
wfButton.textContent = `WF: ${Math.round(percent)}%`;
}
}
} catch (error) {
console.error(error);
}
finally {
semaphore.release();
}
})
);
}
await Promise.all(promises);
// Updating firstStart
if (firstStart) {
localStorage.setItem("lastFavs", JSON.stringify(lastFavs));
newFavsAll = [];
}
totalLength = 0;
return newFavsAll;
}
async function getWatchers() {
let watchers = [];
let prevWatchers;
for (let i = 1; true; i++) {
// Getting watchers html from page i
const watchersDoc = await getHTML(`https://www.furaffinity.net/controls/buddylist/${i}/`);
const nextWatchers = Array.from(watchersDoc.querySelectorAll('div[class="flex-item-watchlist aligncenter"]'));
if (prevWatchers && prevWatchers[prevWatchers.length - 1].outerHTML == nextWatchers[nextWatchers.length - 1].outerHTML) break;
prevWatchers = nextWatchers;
watchers.push(...nextWatchers);
}
return watchers;
}
// Getting newFavs from a specific watcher
async function getUnreadFavsWatcher(watcher, maxFavsLength, progress, ignoreLastSeen = false) {
// Getting username from watcher
let user = watcher.substring(0, watcher.length - 1);
user = user.substring(user.lastIndexOf("/"), user.length);
user = user.substring(1, user.length);
// Calculating current percent
percent = (currentLength / totalLength) * 100;
currentLength++;
// Checking if user is excluded
if (excludedUsers.includes(user)) {
console.log(`${percent.toFixed(2)}% | ${user} is excluded`);
return { intSavedUsers: progress.intSavedUsers, currScanFavs: progress.currScanFavs };
} else {
console.log(`${percent.toFixed(2)}% | ${user}`);
}
// Getting fav figures from user
const figuresAll = await getUserFavFigures(user, maxFavsLength, ignoreLastSeen);
// Exclude user if no images found
if (figuresAll && figuresAll === "no-images") {
console.log(user + " gets excluded");
let excludeButton = document.getElementById("excludeButton_" + user);
// toggleExcludeUser(`/user/${user}/`, button);
return { intSavedUsers: progress.intSavedUsers, currScanFavs: progress.currScanFavs };
}
// Changing Caption to include user
let newFavs = [];
for (const figure of figuresAll) {
const figcaption = figure.querySelector("figcaption");
const byElem = figcaption.childNodes[1].cloneNode(true);
const linkElem = byElem.querySelector("a[href]");
const iElem = byElem.querySelector("i");
const aElem = byElem.querySelector("a");
linkElem.style.fontWeight = "400";
iElem.textContent = "from";
aElem.title = user;
aElem.textContent = user;
aElem.href = `https://www.furaffinity.net/favorites/${user}`;
figcaption.appendChild(byElem);
newFavs.push(figure);
}
// Removing lastFavs from figures
let newCurrScanFavs = newFavs.map((figure) => figure.outerHTML);
progress.currScanFavs = progress.currScanFavs.concat(newCurrScanFavs);
// Saving progress to localStorage
progress.intSavedUsers.push(watcher);
localStorage.setItem("wfloadingusers", JSON.stringify(progress.intSavedUsers));
localStorage.setItem("wfloadingpercent", percent.toFixed(2));
setCompLocalStorageArrayItemAsync("wfloading", progress.currScanFavs);
return { newFavs: newFavs, intSavedUsers: progress.intSavedUsers, currScanFavs: progress.currScanFavs };
}
async function createLastXFavsButton() {
let lastXFavsButton = document.createElement("a");
lastXFavsButton.id = "lastXFavsButton";
lastXFavsButton.className = "notification-container inline";
lastXFavsButton.textContent = "Load last x Favs";
lastXFavsButton.title = "Show last X Favorites";
lastXFavsButton.style.cursor = "pointer";
lastXFavsButton.onclick = () => {
currentLength = 0;
let amount = prompt("Enter the amount of Favs you want to load: ");
while (amount && isNaN(parseInt(amount))) amount = prompt("Input was not a Number. Please enter the amount of Favs you want to load: ");
if (amount && amount > 0) loadLastXFavsAll(lastXFavsButton, amount);
};
document.getElementsByClassName("message-bar-desktop")[0].appendChild(lastXFavsButton);
}
async function loadLastXFavsAll(lastXFavsButton, amount) {
// Getting watchers
const watchers = await getWatchers();
totalLength = watchers.length;
console.log(`You are watching "${totalLength}" people`);
console.log(`Searching for last "${amount}" Favs...`);
// Getting lastFavs
let progress = { newFavs: [], percent: 0, intSavedUsers: [], currScanFavs: [] };
let newFavsAll = [];
let promises = [];
let semaphore = new Semaphore(2);
for (const watcher of watchers) {
promises.push(
semaphore.acquire().then(async () => {
try {
const watcherLink = watcher.querySelector("a").href;
// Getting last favs from watcher
progress = await getUnreadFavsWatcher(watcherLink, amount, progress, true);
if (progress.newFavs) {
newFavsAll = newFavsAll.concat(progress.newFavs);
}
// Updating LastXButton prefix
lastXFavsButton.textContent = `WF Last ${amount}: ${Math.round(percent)}%`;
} catch (error) {
console.error(error);
}
finally {
semaphore.release();
}
})
);
}
await Promise.all(promises);
// Loading last x favs
const figureCount = newFavsAll.length;
if (figureCount !== 0) {
lastXFavsButton.setAttribute("loading", false);
lastXFavsButton.textContent = figureCount + "WF";
totalLength = 0;
localStorage.setItem("clicked", true);
newFavsAll = Array.from(newFavsAll);
newFavsAll = newFavsAll.map((newFav) => newFav.outerHTML);
var favsComp = await compressString(JSON.stringify(newFavsAll));
localStorage.setItem("favs", favsComp);
window.location.href = "https://www.furaffinity.net/msg/submissions/";
} else lastXFavsButton.parentNode.removeChild(lastXFavsButton);
totalLength = 0;
return newFavsAll;
}
// Getting fav figures from a specific user
async function getUserFavFigures(user, maxFavsLength, ignoreLastSeen = false) {
// Checking last seen fav
const lastFavsTemp = JSON.parse(localStorage.getItem("lastFavs")) || {};
const userInLastFavs = user in lastFavsTemp;
let figuresAll = [];
let lastFigureIndex = -1;
for (let i = 1; lastFigureIndex == -1 && (i == 0 || figuresAll.length < maxFavsLength); i++) {
// Getting figures html from page i
const favLink = `https://www.furaffinity.net/favorites/${user}/${i}`;
const favs = await getHTML(favLink);
if (!favs || !favs.body) break;
if (favs.getElementById("no-images")) {
return "no-images";
}
const figures = Array.from(favs.body.getElementsByTagName("figure"));
if (!figures || figures.length == 0) break;
// Check last seen fav
if (!ignoreLastSeen && userInLastFavs) {
lastFigureIndex = figuresAll.findIndex((figure) => figure.id == lastFavsTemp[user]); //figures
}
figuresAll = figuresAll.concat(figures);
if (!userInLastFavs)
break;
}
if (figuresAll.length > maxFavsLength) {
figuresAll = figuresAll.slice(0, maxFavsLength);
}
if (!ignoreLastSeen && lastFigureIndex !== -1) {
figuresAll = figuresAll.slice(0, lastFigureIndex);
if (figuresAll.length !== 0) lastFavs[user] = figuresAll[0].id;
} else if (firstStart) {
if (figuresAll && figuresAll.length !== 0) {
if (!lastFavs) lastFavs = {};
lastFavs[user] = figuresAll[0].id;
}
} else if (!userInLastFavs) {
lastFavs[user] = figuresAll[0].id;
}
return figuresAll;
}
async function getHTML(url) {
try {
const response = await fetch(url);
const html = await response.text();
const parser = new DOMParser();
const doc = parser.parseFromString(html, "text/html");
return doc;
} catch (error) {
console.error(error);
}
}
async function setCompLocalStorageArrayItemAsync(itemname, item) {
let itemcomp = await compressString(JSON.stringify(item));
localStorage.setItem(itemname, itemcomp);
}
async function compressString(str) {
return LZString.compress(str);
}
async function decompressString(compStr) {
return LZString.decompress(compStr);
}
class Semaphore {
constructor(maxConcurrency) {
this.maxConcurrency = maxConcurrency;
this.currentConcurrency = 0;
this.waitingQueue = [];
}
acquire() {
return new Promise((resolve, reject) => {
if (this.currentConcurrency < this.maxConcurrency) {
this.currentConcurrency++;
resolve();
} else {
this.waitingQueue.push(resolve);
}
});
}
release() {
if (this.waitingQueue.length > 0) {
let nextResolve = this.waitingQueue.shift();
nextResolve();
} else {
this.currentConcurrency--;
}
}
}
// ------------------------------ //
// ---------- SETTINGS ---------- //
// ------------------------------ //
// Adding settings to the navigation menu
async function addExSettings() {
const settings = document.querySelector('ul[class="navhideonmobile"]').querySelector('a[href="/controls/settings/"]').parentNode;
if (document.getElementById("extension_settings")) {
document.getElementById("midori_settings").addEventListener("click", function () {
localStorage.setItem("wfsettings", true.toString());
});
return;
}
let exSettingsHeader = document.createElement("h3");
exSettingsHeader.id = "extension_settings";
exSettingsHeader.textContent = "Extension Settings";
settings.appendChild(exSettingsHeader);
let wfsettings = document.createElement("a");
wfsettings.id = "midori_settings";
wfsettings.textContent = "Midori's Script Settings";
wfsettings.style.cursor = "pointer";
wfsettings.onclick = function () {
localStorage.setItem("wfsettings", true.toString());
window.location = "https://www.furaffinity.net/controls/settings";
};
settings.appendChild(wfsettings);
}
// Adding settings to the settings sidebar menu
async function addExSettingsSidebar() {
const settings = document.getElementById("controlpanelnav");
if (document.getElementById("extension_settings_side")) {
document.getElementById("midori_settings_side").addEventListener("click", function () {
localStorage.setItem("wfsettings", true.toString());
});
return;
}
let exSettingsHeader = document.createElement("h3");
exSettingsHeader.id = "extension_settings_side";
exSettingsHeader.textContent = "Extension Settings";
settings.appendChild(exSettingsHeader);
let wfsettings = document.createElement("a");
wfsettings.id = "midori_settings_side";
wfsettings.textContent = "Midori's Script Settings";
wfsettings.style.cursor = "pointer";
wfsettings.onclick = function () {
localStorage.setItem("wfsettings", true.toString());
window.location = "https://www.furaffinity.net/controls/settings";
};
settings.appendChild(wfsettings);
}
// Creating the settings page
async function createSettings() {
localStorage.setItem("wfsettings", false.toString());
const columnPage = document.getElementById("columnpage");
const content = columnPage.querySelector('div[class="content"]');
for (const section of content.querySelectorAll('section:not([class="exsettings"])')) section.parentNode.removeChild(section);
const section = document.createElement("section");
section.className = "exsettings";
const headerContainer = document.createElement("div");
headerContainer.className = "section-header";
const header = document.createElement("h2");
header.textContent = "Watches Favorite Viewer Settings";
headerContainer.appendChild(header);
section.appendChild(headerContainer);
const bodyContainer = document.createElement("div");
bodyContainer.className = "section-body";
// Last X Favs Setting
const lastXFavsSetting = createSetting("Last X Favs", "Sets wether the Load last x Favs buttons appears after a new Fav scan found no new Favs", "boolean", "Show Last X Favs Button", (target) => {
showLoadLastXFavsButton = target.checked;
localStorage.setItem(target.id, showLoadLastXFavsButton.toString());
});
lastXFavsSetting.querySelector('[id*="setting"]').checked = showLoadLastXFavsButton;
bodyContainer.appendChild(lastXFavsSetting);
// Max Favs Loaded Setting
const maxFavsLoadedSetting = createSetting("Max Favs Loaded", "Sets the maximum number of Favs loaded", "number", "", (target) => {
maxFavsLength = +target.value;
localStorage.setItem(target.id, maxFavsLength.toString());
});
maxFavsLoadedSetting.querySelector('[id*="setting"]').value = maxFavsLength.toString();
bodyContainer.appendChild(maxFavsLoadedSetting);
// Max amount of simultaneous requests Setting
const maxAmountSimultaneousRequestsSetting = createSetting("Max amount of simultaneous requests", "Sets the maximum number of simultaneous requests. Higher value means faster scans but a too high value will overload Furaffinity and crash the Extension", "number", "", (target) => {
maxAmountRequests = +target.value;
localStorage.setItem(target.id, maxAmountRequests.toString());
});
maxAmountSimultaneousRequestsSetting.querySelector('[id*="setting"]').value = maxAmountRequests.toString();
bodyContainer.appendChild(maxAmountSimultaneousRequestsSetting);
// Reset Synchronisation Error Setting
const resetSynchronizationErrorSetting = createSetting("Reset Synchronisation", "Resets the synchronisation variable to fix an error that no scan will start", "action", "Reset Loadingstate", (target) => {
localStorage.removeItem("wfloadingstate");
const wfloadingstatetemp = localStorage.getItem("wfloadingstate");
if (wfloadingstatetemp == null || wfloadingstatetemp == undefined) {
target.textContent = "<---- Success ---->";
setTimeout(() => {
target.textContent = "Reset Loadingstate";
}, 3000);
} else {
target.textContent = "<---- Failed ---->";
setTimeout(() => {
target.textContent = "Reset Loadingstate";
}, 3000);
}
});
bodyContainer.appendChild(resetSynchronizationErrorSetting);
// Reset Saving Variable Setting
const resetSavingVariableSetting = createSetting("Reset Last seen Favs", "Resets the last seen favs variable to reinitialize the Fav-Scanner", "action", "Reset Last seen Favs", (target) => {
localStorage.removeItem("lastFavs");
const lastfavxtemp = localStorage.getItem("lastFavs");
if (lastfavxtemp == null || lastfavxtemp == undefined) {
target.textContent = "<---- Success ---->";
setTimeout(() => {
target.textContent = "Reset Last seen Favs";
}, 3000);
} else {
target.textContent = "<---- Failed ---->";
setTimeout(() => {
target.textContent = "Reset Last seen Favs";
}, 3000);
}
});
bodyContainer.appendChild(resetSavingVariableSetting);
// Immediately Scan Setting
const immedScanSetting = createSetting("Immediately Scan", "Sets wether a scan is started immediately uppon loading a Page", "boolean", "Immediately start a Scan", (target) => {
doImmediateScan = target.checked;
localStorage.setItem(target.id, doImmediateScan.toString());
});
immedScanSetting.querySelector('[id*="setting"]').checked = doImmediateScan;
bodyContainer.appendChild(immedScanSetting);
section.appendChild(bodyContainer);
content.appendChild(section);
}
function createSetting(name, description, type, typeDescription, executeFunction) {
const settingContainer = document.createElement("div");
settingContainer.className = "control-panel-item-container";
const settingName = document.createElement("div");
settingName.className = "control-panel-item-name";
const settingNameText = document.createElement("h4");
settingNameText.textContent = name;
settingName.appendChild(settingNameText);
settingContainer.appendChild(settingName);
const settingDesc = document.createElement("div");
settingDesc.className = "control-panel-item-description";
const settingDescText = document.createTextNode(description);
settingDesc.appendChild(settingDescText);
settingContainer.appendChild(settingDesc);
const settingOption = document.createElement("div");
settingOption.className = "control-panel-item-options";
if (type === "number") {
settingsCount++;
const settingInput = document.createElement("input");
settingInput.id = "wfsetting_" + settingsCount;
settingInput.type = "text";
settingInput.className = "textbox";
settingInput.addEventListener("keydown", (event) => {
const currentValue = parseInt(settingInput.value) || 0;
if (event.key === "ArrowUp") {
settingInput.value = (currentValue + 1).toString();
executeFunction(settingInput);
} else if (event.key === "ArrowDown") {
if (currentValue != 0)
settingInput.value = (currentValue - 1).toString();
executeFunction(settingInput);
}
});
settingInput.addEventListener("input", () => {
settingInput.value = settingInput.value.replace(/[^0-9]/g, "");
if (settingInput.value < 0)
settingInput.value = 0;
});
settingInput.addEventListener("input", () => executeFunction(settingInput));
settingOption.appendChild(settingInput);
} else if (type === "boolean") {
settingsCount++;
const settingCheckbox = document.createElement("input");
settingCheckbox.id = "wfsetting_" + settingsCount;
settingCheckbox.type = "checkbox";
settingCheckbox.style.cursor = "pointer";
settingCheckbox.style.marginRight = "4px";
settingCheckbox.addEventListener("change", () => executeFunction(settingCheckbox));
settingOption.appendChild(settingCheckbox);
const settingOptionLabel = document.createElement("label");
settingOptionLabel.textContent = typeDescription;
settingOptionLabel.style.cursor = "pointer";
settingOptionLabel.addEventListener("click", () => {
settingCheckbox.checked = !settingCheckbox.checked;
executeFunction(settingCheckbox);
});
settingOption.appendChild(settingOptionLabel);
} else if (type === "action") {
settingsCount++;
const settingButton = document.createElement("button");
settingButton.id = "wfsetting_" + settingsCount;
settingButton.type = "button";
settingButton.className = "button standard mobile-fix";
settingButton.textContent = typeDescription;
settingButton.addEventListener("click", () => executeFunction(settingButton));
settingOption.appendChild(settingButton);
}
settingContainer.appendChild(settingOption);
return settingContainer;
}