Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 31 additions & 13 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,43 +1,62 @@
{
"cSpell.words": [
"*action",
"*close",
"*content",
"*enctype",
"*evasion",
"*hacks",
"*id",
"*input",
"*length",
"*method",
"*novalidate",
"*open",
"*opener",
"*referrer",
"*target",
"*unreleased*",
"*votes",
"*voting",
"anthro",
"APIIQDB",
"banevasion",
"ban*",
"bdrawer",
"bitwolfy",
"bloodlust",
"Bolden",
"callout",
"cdnp",
"colspan",
"commandfor",
"cooldown",
"Copybox",
"Customizer",
"Danbooru",
"Datetime",
"defval",
"Derpibooru",
"dialogclose",
"dialogopen",
"dialog*",
"dmail",
"dmails",
"dnpcache",
"downvotes",
"downvoting",
"down*",
"Dragonfruit",
"dtext",
"Earlopain",
"favorited",
"fileinput",
"file*",
"fitv",
"fnct",
"fontawesome",
"form*",
"formspan",
"forumdot",
"Greasemonkey",
"Helpdesk",
"Hrefs",
"IBTL",
"interestfor",
"IQDB",
"jqueryui",
"Keybind",
Expand All @@ -49,19 +68,18 @@
"lazyload",
"Mairo",
"MATCHNAME",
"maxlength",
"max*",
"metascript",
"no*",
"nonselectable",
"noopener",
"noreferrer",
"octothorpes",
"onshift",
"paysite",
"Pixiv",
"popovertarget*",
"postface",
"postid",
"postinghacks",
"postingunreleasedcontent",
"posting*",
"propertychange",
"pximg",
"qedit",
Expand Down Expand Up @@ -89,8 +107,8 @@
"unformat",
"unmargin",
"Unvote",
"upvotes",
"userid",
"up*",
"user*",
"userscript",
"userscripts",
"webm",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "mod621",
"displayName": "RE621 Mod Tools",
"namespace": "mod621.bitwolfy.com",
"version": "6.9.0",
"version": "6.10.0",
"description": "Moderation toolkit for e621.net",
"author": "bitWolfy",
"contributors": [
Expand Down
87 changes: 67 additions & 20 deletions src/REMT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import RipStaffNotes from "./js/components/RipStaffNotes";
import TimeKeeper from "./js/components/TimeKeeper";
import HtmlBuilder from "./js/utilities/HtmlBuilder";
import XM from "./js/models/api/XM";
import { html } from "./js/utilities/HtmlTemplate";

export default class REMT {

Expand Down Expand Up @@ -130,42 +131,88 @@ export default class REMT {
*/
private buildSettingsButton(addListeners = false) {
this.settingsButton?.remove();
Debug.logPrefix("Checking for settings...");
const configs = Object.values(REMT._Registry).reduce((p, e) => {
if (!e) return p;
if (addListeners) e.on("settingsConfigured", () => this.buildSettingsButton());
const v = e.settingsMenuDialogParameters;
if (v) p.push(v);
return p;
}, [] as SettingsDialogConfig[]);
if (configs.length <= 0) {
Debug.logPrefix("No settings registered");
return;
}
Debug.logPrefix("Loading %s settings...", configs.length);
const cbs: JQuery<HTMLElement>[] = [];
Debug.logPrefix("Checking for component settings menus...");
const configs: SettingsDialogConfig[] = [], cbs: JQuery<HTMLElement>[] = [], setTo: ((v: boolean, setCb?: boolean) => void)[] = [];
let areAnyEnabled = false;
for (const [k, v] of Object.entries(REMT._Registry)) {
if (!v) continue;
Debug.logPrefix("%s.Settings.enabled:\n\tInstance's accessor: %o\n\tRaw Stored Value: %o", k, v?.Settings.enabled, XM.Storage.getValue<any>(k + "." + "enabled", undefined));
if (addListeners) v.on("settingsConfigured", () => this.buildSettingsButton());
const menuParams = v.settingsMenuDialogParameters;
if (menuParams) configs.push(menuParams);
// Debug.logPrefix("%s.Settings.enabled:\n\tInstance's accessor: %o\n\tRaw Stored Value: %o", k, v?.Settings.enabled, XM.Storage.getValue<any>(k + "." + "enabled", undefined));
const cb = HtmlBuilder.inputCheckboxBuilder({
checked: XM.Storage.getValue(k + "." + "enabled", v?.Settings.enabled),
value: k,
id: `${Script.htmlPrefix}-enable-${k}`,
name: `${Script.htmlPrefix}-enable-${k}`,
});
cb.addEventListener("change", _ => XM.Storage.setValue(k + "." + "enabled", v.Settings.enabled = cb.checked));
cbs.push($(HtmlBuilder.labelBuilder({
areAnyEnabled ||= cb.checked;
const st = (value: boolean, setCb = false) => { XM.Storage.setValue(k + "." + "enabled", v.Settings.enabled = value); if (setCb) cb.checked = value; };
setTo.push(st);
cb.addEventListener("change", _ => st(cb.checked));
const resetSettingsButton = HtmlBuilder.button({
id: `${Script.htmlPrefix}-reset-${k}`,
name: `${Script.htmlPrefix}-reset-${k}`,
type: "button",
innerHtml: "Reset",
title: "Reset to Default Settings?",
});
resetSettingsButton.addEventListener("click", _ => v.requestResetSettings());
cbs.push($(html`<div>${HtmlBuilder.labelBuilder({
forElement: `${Script.htmlPrefix}-enable-${k}`,
title: `Fully enable/disable the ${Util.pascalToTitle(k)} component?`,
innerHtml: [k, cb, `<br />`],
})));
innerHtml: [k, ":&nbsp;", cb],
})}&nbsp;${resetSettingsButton}</div>` as HTMLDivElement));
}
if (configs.length <= 0) {
Debug.logPrefix("No settings menus registered currently.");
// Must draw the menu if it has no chance of being drawn otherwise.
if (areAnyEnabled) return;
Debug.logPrefix("All components disabled; creating global settings menu...");
} else
Debug.logPrefix("Creating settings menu for %s components...", configs.length);
const enableAll = HtmlBuilder.button({
id: `${Script.htmlPrefix}-enable-all`,
type: "button",
innerHtml: "Enable All",
}), disableAll = HtmlBuilder.button({
id: `${Script.htmlPrefix}-disable-all`,
type: "button",
innerHtml: "Disable All",
});
/* enableAll.addEventListener("click", _ => cbs.forEach(e => {
const cb = e.children("input")[0];
if (!cb.checked) {
cb.checked = true;
cb.dispatchEvent(new Event("change"));
}
}));
disableAll.addEventListener("click", _ => cbs.forEach(e => {
const cb = e.children("input")[0];
if (cb.checked) {
cb.checked = false;
cb.dispatchEvent(new Event("change"));
}
})); */
enableAll.addEventListener("click", _ => setTo.forEach(e => e(true, true)));
disableAll.addEventListener("click", _ => setTo.forEach(e => e(false, true)));
/* function setAll(to: boolean) {
cbs.forEach(e => e.children("input")[0].checked = to);
}
enableAll.addEventListener("click", () => setAll(true));
disableAll.addEventListener("click", () => setAll(false)); */
configs.push({
elements: [
$("<label>Select which components should be enabled. All turned off here cannot be re-enabled with the UI.</label>"),
$("<label>Select which components should be enabled.</label>"),
$(`<br />`),
...cbs,
$(enableAll),
$(disableAll),
],
optionsOrTitle: {
title: "Global Settings",
defaultElements: [],
},
});
this.settingsButton = Util.DOM.addSettingsButton({
id: `${Script.htmlPrefix}-component-settings`,
Expand Down
59 changes: 45 additions & 14 deletions src/js/components/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,41 @@ import Util from "../utilities/Util";

export default class Component {

protected name: string; // Unique identifier for this component. Defaults to the class name.
/**
* Unique identifier for this component. Defaults to the class name.
*/
protected name: string;

private initialized = false; // Whether or not the component is currently running
private eventIndex = 0; // Used to provide IDs to the component event listeners
private constraintMatches: boolean; // Whether or not the declared page constraints match
private DOMLoadConditions: boolean | string; // DOM conditions that must be met for the component to load
private waitForFocus: boolean; // Wait for the window to come into focus before loading
private dependencies: string[]; // List of components names that need to be enabled
/**
* Whether or not the component is currently running
*/
private initialized = false;
/**
* Used to provide IDs to the component event listeners
*/
private eventIndex = 0;
/**
* Whether or not the declared page constraints match
*/
private constraintMatches: boolean;
/**
* DOM conditions that must be met for the component to load
*/
private DOMLoadConditions: boolean | string;
/**
* Wait for the window to come into focus before loading
*/
private waitForFocus: boolean;
/**
* List of components names that need to be enabled
*/
private dependencies: string[];

/**
* Component settings
*
* Defines default values and is used to access them via dynamic setters and getters,
* which are assigned over the values provided by child classes.
* Defines default values and is used to access them via dynamic setters and
* getters, which are assigned over the values provided by child classes.
* The original values are stored in `SettingsDefaults`.
*
* The `SettingsCache` object stores the current values of the settings.
Expand All @@ -43,7 +64,7 @@ export default class Component {
* overwritten with dynamic setters and getters.
*/
private get SettingsDefaults(): Settings {
if (!this._SettingsDefaults) throw Error("Component.SettingsDefaults is not yet defined.");
if (!this._SettingsDefaults) throw Error(`${this.name}.SettingsDefaults is not yet defined.`);
return this._SettingsDefaults;
}
/**
Expand Down Expand Up @@ -333,21 +354,31 @@ export default class Component {
this._settingsMenuDialogParameters = v;
this.trigger("settingsConfigured");
}

/**
* @todo Make protected again after creating the global settings component.
*/
protected resetSettings() {
for (const [k, v] of Object.entries(this.SettingsDefaults)) {
this.Settings[k] = v;
}
}

public requestResetSettings(label = this.settingsDialogTitle) {
if (confirm(`Reset ${label} to defaults?`)) {
this.resetSettings();
return true;
}
return false;
}

protected get prettyPrintName() { return Util.pascalToTitle(this.name); }
protected get settingsDialogTitle() { return `${this.prettyPrintName} Settings`; }
// #region Reset settings
protected get settingsIdPrefix() { return `${this.prettyPrintName.replace(/\s+/g, "-")}-setting-`; }
protected handleResetSettingsDialogElement(e: FormData, forceConfirm = true) {
if (
e.get(`${this.settingsIdPrefix}resetSettings`) === "true" &&
(!forceConfirm || confirm(`Reset ${this.settingsDialogTitle} to defaults?`))
) {
if (e.get(`${this.settingsIdPrefix}resetSettings`) === "true") {
if (forceConfirm) return this.requestResetSettings();
this.resetSettings();
return true;
}
Expand Down
Loading
Loading