mirror of
https://github.com/SwingTheVine/Wplace-BlueMarble.git
synced 2026-04-20 06:02:04 +00:00
Added Settings Window & Highlight UI
This commit is contained in:
parent
dd95406b31
commit
fbe86b8965
18 changed files with 498 additions and 26 deletions
27
dist/BlueMarble-For-GreasyFork.user.css
vendored
27
dist/BlueMarble-For-GreasyFork.user.css
vendored
|
|
@ -389,6 +389,33 @@ input[type=file] {
|
|||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* src/WindowSettings.css */
|
||||
#bm-window-settings .bm-highlight-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
width: 25%;
|
||||
min-width: 3ch;
|
||||
max-width: 30ch;
|
||||
}
|
||||
#bm-window-settings .bm-highlight-grid > button {
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
background-color: white;
|
||||
border: #333 1px solid;
|
||||
border-radius: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#bm-window-settings .bm-highlight-grid > button[data-status=Incorrect] {
|
||||
background-color: brown;
|
||||
}
|
||||
#bm-window-settings .bm-highlight-grid > button[data-status=Template] {
|
||||
background-color: darkslategray;
|
||||
}
|
||||
#bm-window-settings .bm-highlight-grid > button:hover,
|
||||
#bm-window-settings .bm-highlight-grid > button:focus {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* src/WindowWizard.css */
|
||||
#bm-wizard-tlist {
|
||||
display: flex;
|
||||
|
|
|
|||
181
dist/BlueMarble-For-GreasyFork.user.js
vendored
181
dist/BlueMarble-For-GreasyFork.user.js
vendored
|
|
@ -2,7 +2,7 @@
|
|||
// @name Blue Marble
|
||||
// @name:en Blue Marble
|
||||
// @namespace https://github.com/SwingTheVine/
|
||||
// @version 0.91.10
|
||||
// @version 0.91.38
|
||||
// @description A userscript to enhance the user experience on Wplace.live. This includes, but is not limited to: uploading images to display locally on a canvas, adding a button to move the Wplace color palette menu, and other QoL features.
|
||||
// @description:en A userscript to enhance the user experience on Wplace.live. This includes, but is not limited to: uploading images to display locally on a canvas, adding a button to move the Wplace color palette menu, and other QoL features.
|
||||
// @author SwingTheVine
|
||||
|
|
@ -521,6 +521,7 @@ Getting Y ${pixelY}-${pixelY + drawSizeY}`);
|
|||
this.name = name2;
|
||||
this.version = version2;
|
||||
this.apiManager = null;
|
||||
this.settingsManager = null;
|
||||
this.outputStatusId = "bm-output-status";
|
||||
this.overlay = null;
|
||||
this.currentParent = null;
|
||||
|
|
@ -533,6 +534,13 @@ Getting Y ${pixelY}-${pixelY + drawSizeY}`);
|
|||
setApiManager(apiManager2) {
|
||||
this.apiManager = apiManager2;
|
||||
}
|
||||
/** Populates the settingsManager variable with the settingsManager class.
|
||||
* @param {SettingsManager} settingsManager - The settingsManager class instance
|
||||
* @since 0.91.11
|
||||
*/
|
||||
setSettingsManager(settingsManager2) {
|
||||
this.settingsManager = settingsManager2;
|
||||
}
|
||||
/** Finishes building an element.
|
||||
* Call this after you are finished adding children.
|
||||
* If the element will have no children, call it anyways.
|
||||
|
|
@ -1713,10 +1721,7 @@ Getting Y ${pixelY}-${pixelY + drawSizeY}`);
|
|||
(part, i) => i == 0 ? part : part[0].toUpperCase() + part.slice(1)
|
||||
).join("")] = value;
|
||||
} else if (property.startsWith("aria")) {
|
||||
const camelCase = property.slice(5).split("-").map(
|
||||
(part, i) => i == 0 ? part : part[0].toUpperCase() + part.slice(1)
|
||||
).join("");
|
||||
element["aria" + camelCase[0].toUpperCase() + camelCase.slice(1)] = value;
|
||||
element.setAttribute(property, value);
|
||||
} else {
|
||||
element[property] = value;
|
||||
}
|
||||
|
|
@ -2707,7 +2712,7 @@ Did you try clicking the canvas first?`);
|
|||
button.ontouchend = () => {
|
||||
button.click();
|
||||
};
|
||||
}).buildElement().buildElement().addDiv({ "class": "bm-window-content" }).addDiv({ "class": "bm-container bm-center-vertically" }).addHeader(1, { "textContent": "Credits" }).buildElement().buildElement().addHr().buildElement().addDiv({ "class": "bm-container bm-scrollable" }).addSpan({ "role": "img", "aria-label": this.name }).addSpan({ "innerHTML": ascii, "class": "bm-ascii", "aria-hidden": "true" }).buildElement().buildElement().addBr().buildElement().addHr().buildElement().addBr().buildElement().addSpan({ "textContent": '"Blue Marble" userscript is made by SwingTheVine.' }).buildElement().addBr().buildElement().addSpan({ "innerHTML": 'The <a href="https://bluemarble.lol/" target="_blank" rel="noopener noreferrer">Blue Marble Website</a> is made by <a href="https://github.com/crqch" target="_blank" rel="noopener noreferrer">crqch</a>.' }).buildElement().addBr().buildElement().addSpan({ "textContent": `The Blue Marble Website used until ${localizeDate(new Date(1756069320 * 1e3))} was made by Camille Daguin.` }).buildElement().addBr().buildElement().addSpan({ "textContent": 'The favicon "Blue Marble" is owned by NASA. (The image of the Earth is owned by NASA)' }).buildElement().addBr().buildElement().addSpan({ "textContent": "Special Thanks:" }).buildElement().addUl().addLi({ "textContent": "Espresso, Meqa, and Robot for moderating SwingTheVine's community." }).buildElement().addLi({ "innerHTML": 'nof, <a href="https://github.com/TouchedByDarkness" target="_blank" rel="noopener noreferrer">darkness</a> for creating similar userscripts!' }).buildElement().addLi({ "innerHTML": '<a href="https://wondapon.net/" target="_blank" rel="noopener noreferrer">Wonda</a> for the Blue Marble banner image!' }).buildElement().addLi({ "innerHTML": '<a href="https://github.com/BullStein" target="_blank" rel="noopener noreferrer">BullStein</a>, <a href="https://github.com/allanf181" target="_blank" rel="noopener noreferrer">allanf181</a> for being early beta testers!' }).buildElement().addLi({ "innerHTML": 'guidu_ and <a href="https://github.com/Nick-machado" target="_blank" rel="noopener noreferrer">Nick-machado</a> for the original "Minimize" Button code!' }).buildElement().addLi({ "innerHTML": 'Nomad and <a href="https://www.youtube.com/@gustav_vv" target="_blank" rel="noopener noreferrer">Gustav</a> for the tutorials!' }).buildElement().addLi({ "innerHTML": '<a href="https://github.com/cfpwastaken" target="_blank" rel="noopener noreferrer">cfp</a> for creating the template overlay that Blue Marble was based on!' }).buildElement().addLi({ "innerHTML": '<a href="https://forcenetwork.cloud/" target="_blank" rel="noopener noreferrer">Force Network</a> for hosting the <a href="https://github.com/SwingTheVine/Wplace-TelemetryServer" target="_blank" rel="noopener noreferrer">telemetry server</a>!' }).buildElement().addLi({ "innerHTML": '<a href="https://thebluecorner.net" target="_blank" rel="noopener noreferrer">TheBlueCorner</a> for getting me interested in online pixel canvases!' }).buildElement().buildElement().addBr().buildElement().addSpan({ "innerHTML": '<a href="https://ko-fi.com/swingthevine" target="_blank" rel="noopener noreferrer">Donators</a>:' }).buildElement().addUl().addLi({ "textContent": "Espresso" }).buildElement().addLi({ "textContent": "BEST FAN" }).buildElement().addLi({ "textContent": "Jack" }).buildElement().addLi({ "textContent": "raiken_au" }).buildElement().addLi({ "textContent": "Jacob" }).buildElement().addLi({ "textContent": "StupidOne" }).buildElement().addLi({ "textContent": "1 Anonymous Supporter" }).buildElement().buildElement().buildElement().buildElement().buildElement().buildOverlay(this.windowParent);
|
||||
}).buildElement().buildElement().addDiv({ "class": "bm-window-content" }).addDiv({ "class": "bm-container bm-center-vertically" }).addHeader(1, { "textContent": "Credits" }).buildElement().buildElement().addHr().buildElement().addDiv({ "class": "bm-container bm-scrollable" }).addSpan({ "role": "img", "aria-label": this.name }).addSpan({ "innerHTML": ascii, "class": "bm-ascii", "aria-hidden": "true" }).buildElement().buildElement().addBr().buildElement().addHr().buildElement().addBr().buildElement().addSpan({ "textContent": '"Blue Marble" userscript is made by SwingTheVine.' }).buildElement().addBr().buildElement().addSpan({ "innerHTML": 'The <a href="https://bluemarble.lol/" target="_blank" rel="noopener noreferrer">Blue Marble Website</a> is made by <a href="https://github.com/crqch" target="_blank" rel="noopener noreferrer">crqch</a>.' }).buildElement().addBr().buildElement().addSpan({ "textContent": `The Blue Marble Website used until ${localizeDate(new Date(1756069320 * 1e3))} was made by Camille Daguin.` }).buildElement().addBr().buildElement().addSpan({ "textContent": 'The favicon "Blue Marble" is owned by NASA. (The image of the Earth is owned by NASA)' }).buildElement().addBr().buildElement().addSpan({ "textContent": "Special Thanks:" }).buildElement().addUl().addLi({ "textContent": "Espresso, Meqa, and Robot for moderating SwingTheVine's community." }).buildElement().addLi({ "innerHTML": 'nof, <a href="https://github.com/TouchedByDarkness" target="_blank" rel="noopener noreferrer">darkness</a> for creating similar userscripts!' }).buildElement().addLi({ "innerHTML": '<a href="https://wondapon.net/" target="_blank" rel="noopener noreferrer">Wonda</a> for the Blue Marble banner image!' }).buildElement().addLi({ "innerHTML": '<a href="https://github.com/BullStein" target="_blank" rel="noopener noreferrer">BullStein</a>, <a href="https://github.com/allanf181" target="_blank" rel="noopener noreferrer">allanf181</a> for being early beta testers!' }).buildElement().addLi({ "innerHTML": 'guidu_ and <a href="https://github.com/Nick-machado" target="_blank" rel="noopener noreferrer">Nick-machado</a> for the original "Minimize" Button code!' }).buildElement().addLi({ "innerHTML": 'Nomad and <a href="https://www.youtube.com/@gustav_vv" target="_blank" rel="noopener noreferrer">Gustav</a> for the tutorials!' }).buildElement().addLi({ "innerHTML": '<a href="https://github.com/cfpwastaken" target="_blank" rel="noopener noreferrer">cfp</a> for creating the template overlay that Blue Marble was based on!' }).buildElement().addLi({ "innerHTML": '<a href="https://forcenetwork.cloud/" target="_blank" rel="noopener noreferrer">Force Network</a> for hosting the <a href="https://github.com/SwingTheVine/Wplace-TelemetryServer" target="_blank" rel="noopener noreferrer">telemetry server</a>!' }).buildElement().addLi({ "innerHTML": '<a href="https://thebluecorner.net" target="_blank" rel="noopener noreferrer">TheBlueCorner</a> for getting me interested in online pixel canvases!' }).buildElement().buildElement().addBr().buildElement().addSpan({ "innerHTML": '<a href="https://ko-fi.com/swingthevine" target="_blank" rel="noopener noreferrer">Donators</a>:' }).buildElement().addUl().addLi({ "textContent": "Espresso" }).buildElement().addLi({ "textContent": "BEST FAN" }).buildElement().addLi({ "textContent": "Jack" }).buildElement().addLi({ "textContent": "raiken_au" }).buildElement().addLi({ "textContent": "Jacob" }).buildElement().addLi({ "textContent": "StupidOne" }).buildElement().addLi({ "textContent": "2 Anonymous Supporters" }).buildElement().buildElement().buildElement().buildElement().buildElement().buildOverlay(this.windowParent);
|
||||
this.handleDrag(`#${this.windowID}.bm-window`, `#${this.windowID} .bm-dragbar`);
|
||||
}
|
||||
};
|
||||
|
|
@ -2785,7 +2790,7 @@ Did you try clicking the canvas first?`);
|
|||
};
|
||||
}).buildElement().addButton({ "textContent": "Show All Colors" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _WindowFilter_instances, selectColorList_fn).call(this, true);
|
||||
}).buildElement().buildElement().addDiv({ "class": "bm-container bm-scrollable" }).addDiv({ "class": "bm-container", "style": "margin-left: 2.5ch; margin-right: 2.5ch;" }).addDiv({ "class": "bm-container" }).addSpan({ "id": "bm-filter-tile-load", "innerHTML": "<b>Tiles Loaded:</b> 0 / ???" }).buildElement().addBr().buildElement().addSpan({ "id": "bm-filter-tot-correct", "innerHTML": "<b>Correct Pixels:</b> ???" }).buildElement().addBr().buildElement().addSpan({ "id": "bm-filter-tot-total", "innerHTML": "<b>Total Pixels:</b> ???" }).buildElement().addBr().buildElement().addSpan({ "id": "bm-filter-tot-remaining", "innerHTML": "<b>Complete:</b> ??? (???)" }).buildElement().addBr().buildElement().addSpan({ "id": "bm-filter-tot-completed", "innerHTML": "??? ???" }).buildElement().buildElement().addDiv({ "class": "bm-container" }).addP({ "innerHTML": `Colors with the icon ${this.eyeOpen.replace("<svg", '<svg aria-label="Eye Open"')} will be shown on the canvas. Colors with the icon ${this.eyeClosed.replace("<svg", '<svg aria-label="Eye Closed"')} will not be shown on the canvas. The "Hide All Colors" and "Show All Colors" buttons only apply to colors that display in the list below. The amount of correct pixels is dependent on how many tiles of the template you have loaded since you last opened Wplace.live. If all tiles have been loaded, then the "correct pixel" count is accurate.` }).buildElement().buildElement().addHr().buildElement().addForm({ "class": "bm-container" }).addFieldset().addLegend({ "textContent": "Sort Options:", "style": "font-weight: 700;" }).buildElement().addDiv({ "class": "bm-container" }).addSelect({ "id": "bm-filter-sort-primary", "name": "sortPrimary", "textContent": "I want to view " }).addOption({ "value": "id", "textContent": "color IDs" }).buildElement().addOption({ "value": "name", "textContent": "color names" }).buildElement().addOption({ "value": "premium", "textContent": "premium colors" }).buildElement().addOption({ "value": "percent", "textContent": "percentage" }).buildElement().addOption({ "value": "correct", "textContent": "correct pixels" }).buildElement().addOption({ "value": "incorrect", "textContent": "incorrect pixels" }).buildElement().addOption({ "value": "total", "textContent": "total pixels" }).buildElement().buildElement().addSelect({ "id": "bm-filter-sort-secondary", "name": "sortSecondary", "textContent": " in " }).addOption({ "value": "ascending", "textContent": "ascending" }).buildElement().addOption({ "value": "descending", "textContent": "descending" }).buildElement().buildElement().addSpan({ "textContent": " order." }).buildElement().buildElement().addDiv({ "class": "bm-container" }).addCheckbox({ "id": "bm-filter-show-unused", "name": "showUnused", "textContent": "Show unused colors" }).buildElement().buildElement().buildElement().addDiv({ "class": "bm-container" }).addButton({ "textContent": "Sort Colors", "type": "submit" }, (instance, button) => {
|
||||
}).buildElement().buildElement().addDiv({ "class": "bm-container bm-scrollable" }).addDiv({ "class": "bm-container", "style": "margin-left: 2.5ch; margin-right: 2.5ch;" }).addDiv({ "class": "bm-container" }).addSpan({ "id": "bm-filter-tile-load", "innerHTML": "<b>Tiles Loaded:</b> 0 / ???" }).buildElement().addBr().buildElement().addSpan({ "id": "bm-filter-tot-correct", "innerHTML": "<b>Correct Pixels:</b> ???" }).buildElement().addBr().buildElement().addSpan({ "id": "bm-filter-tot-total", "innerHTML": "<b>Total Pixels:</b> ???" }).buildElement().addBr().buildElement().addSpan({ "id": "bm-filter-tot-remaining", "innerHTML": "<b>Complete:</b> ??? (???)" }).buildElement().addBr().buildElement().addSpan({ "id": "bm-filter-tot-completed", "innerHTML": "??? ???" }).buildElement().buildElement().addDiv({ "class": "bm-container" }).addP({ "innerHTML": `Press the \u{1F5D7} button to make this window smaller. Colors with the icon ${this.eyeOpen.replace("<svg", '<svg aria-label="Eye Open"')} will be shown on the canvas. Colors with the icon ${this.eyeClosed.replace("<svg", '<svg aria-label="Eye Closed"')} will not be shown on the canvas. The "Hide All Colors" and "Show All Colors" buttons only apply to colors that display in the list below. The amount of correct pixels is dependent on how many tiles of the template you have loaded since you last opened Wplace.live. If all tiles have been loaded, then the "correct pixel" count is accurate.` }).buildElement().buildElement().addHr().buildElement().addForm({ "class": "bm-container" }).addFieldset().addLegend({ "textContent": "Sort Options:", "style": "font-weight: 700;" }).buildElement().addDiv({ "class": "bm-container" }).addSelect({ "id": "bm-filter-sort-primary", "name": "sortPrimary", "textContent": "I want to view " }).addOption({ "value": "id", "textContent": "color IDs" }).buildElement().addOption({ "value": "name", "textContent": "color names" }).buildElement().addOption({ "value": "premium", "textContent": "premium colors" }).buildElement().addOption({ "value": "percent", "textContent": "percentage" }).buildElement().addOption({ "value": "correct", "textContent": "correct pixels" }).buildElement().addOption({ "value": "incorrect", "textContent": "incorrect pixels" }).buildElement().addOption({ "value": "total", "textContent": "total pixels" }).buildElement().buildElement().addSelect({ "id": "bm-filter-sort-secondary", "name": "sortSecondary", "textContent": " in " }).addOption({ "value": "ascending", "textContent": "ascending" }).buildElement().addOption({ "value": "descending", "textContent": "descending" }).buildElement().buildElement().addSpan({ "textContent": " order." }).buildElement().buildElement().addDiv({ "class": "bm-container" }).addCheckbox({ "id": "bm-filter-show-unused", "name": "showUnused", "textContent": "Show unused colors" }).buildElement().buildElement().buildElement().addDiv({ "class": "bm-container" }).addButton({ "textContent": "Sort Colors", "type": "submit" }, (instance, button) => {
|
||||
button.onclick = (event) => {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(document.querySelector(`#${this.windowID} form`));
|
||||
|
|
@ -3267,7 +3272,11 @@ Did you try clicking the canvas first?`);
|
|||
}).buildElement().addButton({ "textContent": "Filter" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _WindowMain_instances, buildWindowFilter_fn).call(this);
|
||||
}).buildElement().buildElement().addDiv({ "class": "bm-container" }).addTextarea({ "id": this.outputStatusId, "placeholder": `Status: Sleeping...
|
||||
Version: ${this.version}`, "readOnly": true }).buildElement().buildElement().addDiv({ "class": "bm-container bm-flex-between", "style": "margin-bottom: 0; flex-direction: column;" }).addDiv({ "class": "bm-flex-between" }).addButton({ "class": "bm-button-circle", "innerHTML": "\u{1F9D9}", "title": "Template Wizard" }, (instance, button) => {
|
||||
Version: ${this.version}`, "readOnly": true }).buildElement().buildElement().addDiv({ "class": "bm-container bm-flex-between", "style": "margin-bottom: 0; flex-direction: column;" }).addDiv({ "class": "bm-flex-between" }).addButton({ "class": "bm-button-circle", "innerHTML": "\u2699\uFE0F", "title": "Settings" }, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
instance.settingsManager.buildWindow();
|
||||
};
|
||||
}).buildElement().addButton({ "class": "bm-button-circle", "innerHTML": "\u{1F9D9}", "title": "Template Wizard" }, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
const templateManager2 = instance.apiManager?.templateManager;
|
||||
const wizard = new WindowWizard(this.name, this.version, templateManager2?.schemaVersion, templateManager2);
|
||||
|
|
@ -3388,6 +3397,158 @@ Version: ${this.version}`, "readOnly": true }).buildElement().buildElement().add
|
|||
GM.setValue("bmUserSettings", JSON.stringify(userSettings2));
|
||||
};
|
||||
|
||||
// src/WindowSettings.js
|
||||
var _WindowSettings_instances, errorOverrideFailure_fn;
|
||||
var WindowSettings = class extends Overlay {
|
||||
/** Constructor for the Settings window
|
||||
* @param {string} name - The name of the userscript
|
||||
* @param {string} version - The version of the userscript
|
||||
* @since 0.91.11
|
||||
* @see {@link Overlay#constructor} for examples
|
||||
*/
|
||||
constructor(name2, version2) {
|
||||
super(name2, version2);
|
||||
__privateAdd(this, _WindowSettings_instances);
|
||||
this.window = null;
|
||||
this.windowID = "bm-window-settings";
|
||||
this.windowParent = document.body;
|
||||
}
|
||||
/** Spawns a Settings window.
|
||||
* If another settings window already exists, we DON'T spawn another!
|
||||
* Parent/child relationships in the DOM structure below are indicated by indentation.
|
||||
* @since 0.91.11
|
||||
*/
|
||||
buildWindow() {
|
||||
if (document.querySelector(`#${this.windowID}`)) {
|
||||
document.querySelector(`#${this.windowID}`).remove();
|
||||
return;
|
||||
}
|
||||
this.window = this.addDiv({ "id": this.windowID, "class": "bm-window" }).addDragbar().addButton({ "class": "bm-button-circle", "textContent": "\u25BC", "aria-label": 'Minimize window "Color Filter"', "data-button-status": "expanded" }, (instance, button) => {
|
||||
button.onclick = () => instance.handleMinimization(button);
|
||||
button.ontouchend = () => {
|
||||
button.click();
|
||||
};
|
||||
}).buildElement().addDiv().buildElement().addDiv({ "class": "bm-flex-center" }).addButton({ "class": "bm-button-circle", "textContent": "\u2716", "aria-label": 'Close window "Color Filter"' }, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
document.querySelector(`#${this.windowID}`)?.remove();
|
||||
};
|
||||
button.ontouchend = () => {
|
||||
button.click();
|
||||
};
|
||||
}).buildElement().buildElement().buildElement().addDiv({ "class": "bm-window-content" }).addDiv({ "class": "bm-container bm-center-vertically" }).addHeader(1, { "textContent": "Settings" }).buildElement().buildElement().addHr().buildElement().addDiv({ "class": "bm-container bm-scrollable" }, (instance, div) => {
|
||||
this.buildHighlight();
|
||||
}).buildElement().buildElement().buildElement().buildOverlay(this.windowParent);
|
||||
this.handleDrag(`#${this.windowID}.bm-window`, `#${this.windowID} .bm-dragbar`);
|
||||
}
|
||||
/** Builds the highlight section of the window.
|
||||
* This should be overriden by {@link SettingsManager}
|
||||
* @since 0.91.11
|
||||
*/
|
||||
buildHighlight() {
|
||||
__privateMethod(this, _WindowSettings_instances, errorOverrideFailure_fn).call(this, "Pixel Highlight");
|
||||
}
|
||||
};
|
||||
_WindowSettings_instances = new WeakSet();
|
||||
/** Displays an error when a settings category fails to load.
|
||||
* @param {string} name - The name of the category
|
||||
*/
|
||||
errorOverrideFailure_fn = function(name2) {
|
||||
this.window = this.addDiv({ "class": "bm-container" }).addHeader(2, { "textContent": name2 }).buildElement().addHr().buildElement().addP({ "innerHTML": `An error occured loading the ${name2} category. <code>SettingsManager</code> failed to override the ${name2} function inside <code>WindowSettings</code>.` }).buildElement().buildElement();
|
||||
};
|
||||
|
||||
// src/settingsManager.js
|
||||
var _SettingsManager_instances, updateHighlightSettings_fn;
|
||||
var SettingsManager = class extends WindowSettings {
|
||||
/** Constructor for the SettingsManager class
|
||||
* @param {string} name - The name of the userscript
|
||||
* @param {string} version - The version of the userscript
|
||||
* @param {Object} userSettings - The user settings as an object
|
||||
* @since 0.91.11
|
||||
*/
|
||||
constructor(name2, version2, userSettings2) {
|
||||
super(name2, version2);
|
||||
__privateAdd(this, _SettingsManager_instances);
|
||||
this.userSettings = userSettings2;
|
||||
this.lastUpdateTime = 0;
|
||||
}
|
||||
// This is one of the most insane OOP setups I have ever laid my eyes on
|
||||
/** Builds the "highlight" category of the settings window
|
||||
* @since 0.91.18
|
||||
* @see WindowSettings#buildHighlight
|
||||
*/
|
||||
buildHighlight() {
|
||||
this.window = this.addDiv({ "class": "bm-container" }).addHeader(2, { "textContent": "Pixel Highlight" }).buildElement().addHr().buildElement().addDiv({ "style": "margin-left: 1.5ch;" }).addP({ "id": "bm-highlight-grid-label", "textContent": "Create a custom pattern:" }).buildElement().addDiv({ "class": "bm-highlight-grid", "role": "group", "aria-labelledby": "bm-highlight-grid-label" }).addButton({ "data-status": "Disabled", "aria-label": "Sub-pixel disabled" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _SettingsManager_instances, updateHighlightSettings_fn).call(this, button, [-1, -1]);
|
||||
}).buildElement().addButton({ "data-status": "Incorrect", "aria-label": "Sub-pixel disabled" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _SettingsManager_instances, updateHighlightSettings_fn).call(this, button, [0, -1]);
|
||||
}).buildElement().addButton({ "data-status": "Disabled", "aria-label": "Sub-pixel disabled" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _SettingsManager_instances, updateHighlightSettings_fn).call(this, button, [1, -1]);
|
||||
}).buildElement().addButton({ "data-status": "Incorrect", "aria-label": "Sub-pixel disabled" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _SettingsManager_instances, updateHighlightSettings_fn).call(this, button, [-1, 0]);
|
||||
}).buildElement().addButton({ "data-status": "Template", "aria-label": "Sub-pixel disabled" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _SettingsManager_instances, updateHighlightSettings_fn).call(this, button, [0, 0]);
|
||||
}).buildElement().addButton({ "data-status": "Incorrect", "aria-label": "Sub-pixel disabled" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _SettingsManager_instances, updateHighlightSettings_fn).call(this, button, [1, 0]);
|
||||
}).buildElement().addButton({ "data-status": "Disabled", "aria-label": "Sub-pixel disabled" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _SettingsManager_instances, updateHighlightSettings_fn).call(this, button, [-1, 1]);
|
||||
}).buildElement().addButton({ "data-status": "Incorrect", "aria-label": "Sub-pixel disabled" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _SettingsManager_instances, updateHighlightSettings_fn).call(this, button, [0, 1]);
|
||||
}).buildElement().addButton({ "data-status": "Disabled", "aria-label": "Sub-pixel disabled" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _SettingsManager_instances, updateHighlightSettings_fn).call(this, button, [1, 1]);
|
||||
}).buildElement().buildElement().buildElement().buildElement();
|
||||
}
|
||||
};
|
||||
_SettingsManager_instances = new WeakSet();
|
||||
/** Updates the display of the highlight buttons in the settings window.
|
||||
* Additionally, it will update user settings with the new selection.
|
||||
* @param {HTMLButtonElement} button - The button that was pressed
|
||||
* @param {Array<number, number>} coords - The relative coordinates of the button
|
||||
*/
|
||||
updateHighlightSettings_fn = function(button, coords2) {
|
||||
console.log(coords2);
|
||||
button.disabled = true;
|
||||
const status = button.dataset["status"];
|
||||
const userStorageOld = this.userSettings?.highlight || [[1, 0, 1], [2, 0, 0], [1, -1, 0], [1, 1, 0], [1, 0, -1]];
|
||||
let userStorageChange = [2, 0, 0];
|
||||
const userStorageNew = userStorageOld;
|
||||
console.log(userStorageOld);
|
||||
switch (status) {
|
||||
// If the button was in the "Disabled" state
|
||||
case "Disabled":
|
||||
button.dataset["status"] = "Incorrect";
|
||||
button.ariaLabel = "Sub-pixel incorrect";
|
||||
userStorageChange = [1, ...coords2];
|
||||
break;
|
||||
// If the button was in the "Incorrect" state
|
||||
case "Incorrect":
|
||||
button.dataset["status"] = "Template";
|
||||
button.ariaLabel = "Sub-pixel template";
|
||||
userStorageChange = [2, ...coords2];
|
||||
break;
|
||||
// If the button was in the "Template" state
|
||||
case "Template":
|
||||
button.dataset["status"] = "Disabled";
|
||||
button.ariaLabel = "Sub-pixel disabled";
|
||||
userStorageChange = [0, ...coords2];
|
||||
break;
|
||||
}
|
||||
console.log(userStorageChange);
|
||||
const indexOfChange = userStorageOld.findIndex(([, x, y]) => x == userStorageChange[1] && y == userStorageChange[2]);
|
||||
console.log(indexOfChange);
|
||||
if (userStorageChange[0] != 0) {
|
||||
if (indexOfChange != -1) {
|
||||
userStorageNew[indexOfChange] = userStorageChange;
|
||||
} else {
|
||||
userStorageNew.push(userStorageChange);
|
||||
}
|
||||
} else if (indexOfChange != -1) {
|
||||
userStorageNew.splice(indexOfChange, 1);
|
||||
}
|
||||
console.log(userStorageNew);
|
||||
this.userSettings["highlight"] = userStorageNew;
|
||||
button.disabled = false;
|
||||
};
|
||||
|
||||
// src/main.js
|
||||
var name = GM_info.script.name.toString();
|
||||
var version = GM_info.script.version.toString();
|
||||
|
|
@ -3493,15 +3654,17 @@ Time Since Blink: ${String(Math.floor(elapsed / 6e4)).padStart(2, "0")}:${String
|
|||
document.head?.appendChild(stylesheetLink);
|
||||
}
|
||||
var stylesheetLink;
|
||||
var userSettings = JSON.parse(GM_getValue("bmUserSettings", "{}"));
|
||||
var observers = new Observers();
|
||||
var windowMain = new WindowMain(name, version);
|
||||
var templateManager = new TemplateManager(name, version, windowMain);
|
||||
var apiManager = new ApiManager(templateManager);
|
||||
var settingsManager = new SettingsManager(name, version, userSettings);
|
||||
windowMain.setSettingsManager(settingsManager);
|
||||
windowMain.setApiManager(apiManager);
|
||||
var storageTemplates = JSON.parse(GM_getValue("bmTemplates", "{}"));
|
||||
console.log(storageTemplates);
|
||||
templateManager.importJSON(storageTemplates);
|
||||
var userSettings = JSON.parse(GM_getValue("bmUserSettings", "{}"));
|
||||
console.log(userSettings);
|
||||
console.log(Object.keys(userSettings).length);
|
||||
if (Object.keys(userSettings).length == 0) {
|
||||
|
|
|
|||
4
dist/BlueMarble-Standalone.user.js
vendored
4
dist/BlueMarble-Standalone.user.js
vendored
File diff suppressed because one or more lines are too long
2
dist/BlueMarble.user.css
vendored
2
dist/BlueMarble.user.css
vendored
File diff suppressed because one or more lines are too long
4
dist/BlueMarble.user.js
vendored
4
dist/BlueMarble.user.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -51,7 +51,7 @@
|
|||
<a href="https://discord.gg/tpeBPy46hf" target="_blank" rel="noopener noreferrer"><img alt="Contact Me" src="https://img.shields.io/badge/Contact_Me-gray?style=flat&logo=Discord&logoColor=white&logoSize=auto&labelColor=cornflowerblue"></a>
|
||||
<a href="https://bluemarble.lol/" target="_blank" rel="noopener noreferrer"><img alt="Blue Marble Website" src="https://img.shields.io/badge/Blue_Marble_Website-crqch-blue?style=flat&logo=globe&logoColor=white"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="WakaTime" src="https://img.shields.io/badge/Coding_Time-212hrs_17mins-blue?style=flat&logo=wakatime&logoColor=black&logoSize=auto&labelColor=white"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Patches" src="https://img.shields.io/badge/Total_Patches-1125-black?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Patches" src="https://img.shields.io/badge/Total_Patches-1153-black?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Lines of Code" src="https://img.shields.io/badge/Lines_Of_Code-6620-blue?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Comments" src="https://img.shields.io/badge/Lines_Of_Comments-5414-blue?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Compression" src="https://img.shields.io/badge/Compression-71.85%25-blue"></a>
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.91.10",
|
||||
"version": "0.91.38",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.91.10",
|
||||
"version": "0.91.38",
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"jsdoc": "^4.0.5",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.91.10",
|
||||
"version": "0.91.38",
|
||||
"type": "module",
|
||||
"homepage": "https://bluemarble.lol/",
|
||||
"repository": {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// @name Blue Marble
|
||||
// @name:en Blue Marble
|
||||
// @namespace https://github.com/SwingTheVine/
|
||||
// @version 0.91.10
|
||||
// @version 0.91.38
|
||||
// @description A userscript to enhance the user experience on Wplace.live. This includes, but is not limited to: uploading images to display locally on a canvas, adding a button to move the Wplace color palette menu, and other QoL features.
|
||||
// @description:en A userscript to enhance the user experience on Wplace.live. This includes, but is not limited to: uploading images to display locally on a canvas, adding a button to move the Wplace color palette menu, and other QoL features.
|
||||
// @author SwingTheVine
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ export default class Overlay {
|
|||
|
||||
/** The API manager instance. Later populated when setApiManager is called @type {ApiManager} */
|
||||
this.apiManager = null;
|
||||
|
||||
/** The Settings Manager instance. Later populated when setSettingsManager is called @type {SettingsManager} */
|
||||
this.settingsManager = null;
|
||||
|
||||
this.outputStatusId = 'bm-output-status'; // ID for status element
|
||||
|
||||
|
|
@ -51,6 +54,12 @@ export default class Overlay {
|
|||
*/
|
||||
setApiManager(apiManager) {this.apiManager = apiManager;}
|
||||
|
||||
/** Populates the settingsManager variable with the settingsManager class.
|
||||
* @param {SettingsManager} settingsManager - The settingsManager class instance
|
||||
* @since 0.91.11
|
||||
*/
|
||||
setSettingsManager(settingsManager) {this.settingsManager = settingsManager;}
|
||||
|
||||
/** Creates an element.
|
||||
* For **internal use** of the {@link Overlay} class.
|
||||
* @param {string} tag - The tag name as a string.
|
||||
|
|
@ -109,10 +118,7 @@ export default class Overlay {
|
|||
).join('')
|
||||
] = value;
|
||||
} else if (property.startsWith('aria')) {
|
||||
const camelCase = property.slice(5).split('-').map(
|
||||
(part, i) => (i == 0) ? part : part[0].toUpperCase() + part.slice(1)
|
||||
).join('');
|
||||
element['aria' + camelCase[0].toUpperCase() + camelCase.slice(1)] = value;
|
||||
element.setAttribute(property, value); // We can't do the solution for 'data', as 'aria-labelledby' would fail to apply
|
||||
} else {
|
||||
element[property] = value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ export default class WindowCredts extends Overlay {
|
|||
.addLi({'textContent': 'raiken_au'}).buildElement()
|
||||
.addLi({'textContent': 'Jacob'}).buildElement()
|
||||
.addLi({'textContent': 'StupidOne'}).buildElement()
|
||||
.addLi({'textContent': '1 Anonymous Supporter'}).buildElement()
|
||||
.addLi({'textContent': '2 Anonymous Supporters'}).buildElement()
|
||||
.buildElement()
|
||||
.buildElement()
|
||||
.buildElement()
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ export default class WindowFilter extends Overlay {
|
|||
.addSpan({'id': 'bm-filter-tot-completed', 'innerHTML': '??? ???'}).buildElement()
|
||||
.buildElement()
|
||||
.addDiv({'class': 'bm-container'})
|
||||
.addP({'innerHTML': `Colors with the icon ${this.eyeOpen.replace('<svg', '<svg aria-label="Eye Open"')} will be shown on the canvas. Colors with the icon ${this.eyeClosed.replace('<svg', '<svg aria-label="Eye Closed"')} will not be shown on the canvas. The "Hide All Colors" and "Show All Colors" buttons only apply to colors that display in the list below. The amount of correct pixels is dependent on how many tiles of the template you have loaded since you last opened Wplace.live. If all tiles have been loaded, then the "correct pixel" count is accurate.`}).buildElement()
|
||||
.addP({'innerHTML': `Press the 🗗 button to make this window smaller. Colors with the icon ${this.eyeOpen.replace('<svg', '<svg aria-label="Eye Open"')} will be shown on the canvas. Colors with the icon ${this.eyeClosed.replace('<svg', '<svg aria-label="Eye Closed"')} will not be shown on the canvas. The "Hide All Colors" and "Show All Colors" buttons only apply to colors that display in the list below. The amount of correct pixels is dependent on how many tiles of the template you have loaded since you last opened Wplace.live. If all tiles have been loaded, then the "correct pixel" count is accurate.`}).buildElement()
|
||||
.buildElement()
|
||||
.addHr().buildElement()
|
||||
.addForm({'class': 'bm-container'})
|
||||
|
|
|
|||
|
|
@ -163,6 +163,11 @@ export default class WindowMain extends Overlay {
|
|||
.addDiv({'class': 'bm-container bm-flex-between', 'style': 'margin-bottom: 0; flex-direction: column;'})
|
||||
.addDiv({'class': 'bm-flex-between'})
|
||||
// .addButton({'class': 'bm-button-circle', 'innerHTML': '🖌'}).buildElement()
|
||||
.addButton({'class': 'bm-button-circle', 'innerHTML': '⚙️', 'title': 'Settings'}, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
instance.settingsManager.buildWindow();
|
||||
}
|
||||
}).buildElement()
|
||||
.addButton({'class': 'bm-button-circle', 'innerHTML': '🧙', 'title': 'Template Wizard'}, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
const templateManager = instance.apiManager?.templateManager;
|
||||
|
|
|
|||
36
src/WindowSettings.css
Normal file
36
src/WindowSettings.css
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/* @since 0.91.22 */
|
||||
|
||||
/* Highlight pattern container */
|
||||
#bm-window-settings .bm-highlight-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
width: 25%;
|
||||
min-width: 3ch;
|
||||
max-width: 30ch;
|
||||
}
|
||||
|
||||
/* Highlight pattern button */
|
||||
#bm-window-settings .bm-highlight-grid > button {
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
background-color: white;
|
||||
border: #333 1px solid;
|
||||
border-radius: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Highlight pattern button in 'Incorrect' mode */
|
||||
#bm-window-settings .bm-highlight-grid > button[data-status="Incorrect"] {
|
||||
background-color: brown;
|
||||
}
|
||||
|
||||
/* Highlight pattern button in 'Template' mode */
|
||||
#bm-window-settings .bm-highlight-grid > button[data-status="Template"] {
|
||||
background-color: darkslategray;
|
||||
}
|
||||
|
||||
/* Highlight pattern button when hovered/focused */
|
||||
#bm-window-settings .bm-highlight-grid > button:hover,
|
||||
#bm-window-settings .bm-highlight-grid > button:focus {
|
||||
opacity: 0.8;
|
||||
}
|
||||
86
src/WindowSettings.js
Normal file
86
src/WindowSettings.js
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import Overlay from "./Overlay";
|
||||
|
||||
/** The overlay builder for the settings window in Blue Marble.
|
||||
* The logic for this window is managed in {@link SettingsManager}
|
||||
* @description This class handles the overlay UI for the settings window of the Blue Marble userscript.
|
||||
* @class WindowSettings
|
||||
* @since 0.91.11
|
||||
* @see {@link Overlay} for examples
|
||||
*/
|
||||
export default class WindowSettings extends Overlay {
|
||||
|
||||
/** Constructor for the Settings window
|
||||
* @param {string} name - The name of the userscript
|
||||
* @param {string} version - The version of the userscript
|
||||
* @since 0.91.11
|
||||
* @see {@link Overlay#constructor} for examples
|
||||
*/
|
||||
constructor(name, version) {
|
||||
super(name, version); // Executes the code in the Overlay constructor
|
||||
this.window = null; // Contains the *window* DOM tree
|
||||
this.windowID = 'bm-window-settings'; // The ID attribute for this window
|
||||
this.windowParent = document.body; // The parent of the window DOM tree
|
||||
}
|
||||
|
||||
/** Spawns a Settings window.
|
||||
* If another settings window already exists, we DON'T spawn another!
|
||||
* Parent/child relationships in the DOM structure below are indicated by indentation.
|
||||
* @since 0.91.11
|
||||
*/
|
||||
buildWindow() {
|
||||
|
||||
// If a settings window already exists, close it
|
||||
if (document.querySelector(`#${this.windowID}`)) {
|
||||
document.querySelector(`#${this.windowID}`).remove();
|
||||
return;
|
||||
}
|
||||
|
||||
this.window = this.addDiv({'id': this.windowID, 'class': 'bm-window'})
|
||||
.addDragbar()
|
||||
.addButton({'class': 'bm-button-circle', 'textContent': '▼', 'aria-label': 'Minimize window "Color Filter"', 'data-button-status': 'expanded'}, (instance, button) => {
|
||||
button.onclick = () => instance.handleMinimization(button);
|
||||
button.ontouchend = () => {button.click()}; // Needed only to negate weird interaction with dragbar
|
||||
}).buildElement()
|
||||
.addDiv().buildElement() // Contains the minimized h1 element
|
||||
.addDiv({'class': 'bm-flex-center'})
|
||||
.addButton({'class': 'bm-button-circle', 'textContent': '✖', 'aria-label': 'Close window "Color Filter"'}, (instance, button) => {
|
||||
button.onclick = () => {document.querySelector(`#${this.windowID}`)?.remove();};
|
||||
button.ontouchend = () => {button.click();}; // Needed only to negate weird interaction with dragbar
|
||||
}).buildElement()
|
||||
.buildElement()
|
||||
.buildElement()
|
||||
.addDiv({'class': 'bm-window-content'})
|
||||
.addDiv({'class': 'bm-container bm-center-vertically'})
|
||||
.addHeader(1, {'textContent': 'Settings'}).buildElement()
|
||||
.buildElement()
|
||||
.addHr().buildElement()
|
||||
.addDiv({'class': 'bm-container bm-scrollable'}, (instance, div) => {
|
||||
// Each category in the settings window
|
||||
this.buildHighlight();
|
||||
}).buildElement()
|
||||
.buildElement()
|
||||
.buildElement().buildOverlay(this.windowParent);
|
||||
|
||||
// Creates dragging capability on the drag bar for dragging the window
|
||||
this.handleDrag(`#${this.windowID}.bm-window`, `#${this.windowID} .bm-dragbar`);
|
||||
}
|
||||
|
||||
/** Displays an error when a settings category fails to load.
|
||||
* @param {string} name - The name of the category
|
||||
*/
|
||||
#errorOverrideFailure(name) {
|
||||
this.window = this.addDiv({'class': 'bm-container'})
|
||||
.addHeader(2, {'textContent': name}).buildElement()
|
||||
.addHr().buildElement()
|
||||
.addP({'innerHTML': `An error occured loading the ${name} category. <code>SettingsManager</code> failed to override the ${name} function inside <code>WindowSettings</code>.`}).buildElement()
|
||||
.buildElement();
|
||||
}
|
||||
|
||||
/** Builds the highlight section of the window.
|
||||
* This should be overriden by {@link SettingsManager}
|
||||
* @since 0.91.11
|
||||
*/
|
||||
buildHighlight() {
|
||||
this.#errorOverrideFailure('Pixel Highlight');
|
||||
}
|
||||
}
|
||||
|
|
@ -6,4 +6,5 @@
|
|||
@import './confettiManager.css';
|
||||
@import './overlay.css';
|
||||
@import './WindowFilter.css';
|
||||
@import './WindowSettings.css';
|
||||
@import './WindowWizard.css';
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import TemplateManager from './templateManager.js';
|
|||
import { consoleLog, consoleWarn } from './utils.js';
|
||||
import WindowMain from './WindowMain.js';
|
||||
import WindowTelemetry from './WindowTelemetry.js';
|
||||
import SettingsManager from './settingsManager.js';
|
||||
|
||||
const name = GM_info.script.name.toString(); // Name of userscript
|
||||
const version = GM_info.script.version.toString(); // Version of userscript
|
||||
|
|
@ -186,19 +187,22 @@ if (!!(robotoMonoInjectionPoint.indexOf('@font-face') + 1)) {
|
|||
document.head?.appendChild(stylesheetLink);
|
||||
}
|
||||
|
||||
const userSettings = JSON.parse(GM_getValue('bmUserSettings', '{}')); // Loads the user settings
|
||||
|
||||
// CONSTRUCTORS
|
||||
const observers = new Observers(); // Constructs a new Observers object
|
||||
const windowMain = new WindowMain(name, version); // Constructs a new Overlay object for the main overlay
|
||||
const templateManager = new TemplateManager(name, version, windowMain); // Constructs a new TemplateManager object
|
||||
const apiManager = new ApiManager(templateManager); // Constructs a new ApiManager object
|
||||
const settingsManager = new SettingsManager(name, version, userSettings); // Constructs a new SettingsManager
|
||||
|
||||
windowMain.setSettingsManager(settingsManager); // Sets the settings manager
|
||||
windowMain.setApiManager(apiManager); // Sets the API manager
|
||||
|
||||
const storageTemplates = JSON.parse(GM_getValue('bmTemplates', '{}'));
|
||||
console.log(storageTemplates);
|
||||
templateManager.importJSON(storageTemplates); // Loads the templates
|
||||
|
||||
const userSettings = JSON.parse(GM_getValue('bmUserSettings', '{}')); // Loads the user settings
|
||||
|
||||
console.log(userSettings);
|
||||
console.log(Object.keys(userSettings).length);
|
||||
|
|
|
|||
144
src/settingsManager.js
Normal file
144
src/settingsManager.js
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
import WindowSettings from "./WindowSettings";
|
||||
|
||||
/** SettingsManager class for handling user settings and making them persist between sessions.
|
||||
* Logic for {@link WindowSettings} is managed here.
|
||||
* @class SettingsManager
|
||||
* @since 0.91.11
|
||||
* @examples
|
||||
* {
|
||||
* "uuid": "497dcba3-ecbf-4587-a2dd-5eb0665e6880",
|
||||
* "telemetry": 1,
|
||||
* "flags": ["willHighlight", "openWindowed"],
|
||||
* "highlight": [[1,0,-1],[1,-1,0],[2,1,0],[1,0,1]],
|
||||
* "filter": [-2,0,4,5,6,29,63]
|
||||
* }
|
||||
*/
|
||||
export default class SettingsManager extends WindowSettings {
|
||||
|
||||
/** Constructor for the SettingsManager class
|
||||
* @param {string} name - The name of the userscript
|
||||
* @param {string} version - The version of the userscript
|
||||
* @param {Object} userSettings - The user settings as an object
|
||||
* @since 0.91.11
|
||||
*/
|
||||
constructor(name, version, userSettings) {
|
||||
super(name, version); // Executes WindowSettings constructor
|
||||
|
||||
this.userSettings = userSettings; // User settings as an Object
|
||||
|
||||
this.lastUpdateTime = 0; // When this unix timestamp is within the last 5 seconds, we should save this.userSettings to storage
|
||||
}
|
||||
|
||||
// This is one of the most insane OOP setups I have ever laid my eyes on
|
||||
|
||||
/** Builds the "highlight" category of the settings window
|
||||
* @since 0.91.18
|
||||
* @see WindowSettings#buildHighlight
|
||||
*/
|
||||
buildHighlight() {
|
||||
|
||||
// Constructs the category and adds it to the window
|
||||
this.window = this.addDiv({'class': 'bm-container'})
|
||||
.addHeader(2, {'textContent': 'Pixel Highlight'}).buildElement()
|
||||
.addHr().buildElement()
|
||||
.addDiv({'style': 'margin-left: 1.5ch;'})
|
||||
.addP({'id': 'bm-highlight-grid-label', 'textContent': 'Create a custom pattern:'}).buildElement()
|
||||
.addDiv({'class': 'bm-highlight-grid', 'role': 'group', 'aria-labelledby': 'bm-highlight-grid-label'})
|
||||
.addButton({'data-status': 'Disabled', 'aria-label': 'Sub-pixel disabled'}, (instance, button) => {button.onclick = () => this.#updateHighlightSettings(button, [-1, -1]);}).buildElement()
|
||||
.addButton({'data-status': 'Incorrect', 'aria-label': 'Sub-pixel disabled'}, (instance, button) => {button.onclick = () => this.#updateHighlightSettings(button, [0, -1]);}).buildElement()
|
||||
.addButton({'data-status': 'Disabled', 'aria-label': 'Sub-pixel disabled'}, (instance, button) => {button.onclick = () => this.#updateHighlightSettings(button, [1, -1]);}).buildElement()
|
||||
.addButton({'data-status': 'Incorrect', 'aria-label': 'Sub-pixel disabled'}, (instance, button) => {button.onclick = () => this.#updateHighlightSettings(button, [-1, 0]);}).buildElement()
|
||||
.addButton({'data-status': 'Template', 'aria-label': 'Sub-pixel disabled'}, (instance, button) => {button.onclick = () => this.#updateHighlightSettings(button, [0, 0]);}).buildElement()
|
||||
.addButton({'data-status': 'Incorrect', 'aria-label': 'Sub-pixel disabled'}, (instance, button) => {button.onclick = () => this.#updateHighlightSettings(button, [1, 0]);}).buildElement()
|
||||
.addButton({'data-status': 'Disabled', 'aria-label': 'Sub-pixel disabled'}, (instance, button) => {button.onclick = () => this.#updateHighlightSettings(button, [-1, 1]);}).buildElement()
|
||||
.addButton({'data-status': 'Incorrect', 'aria-label': 'Sub-pixel disabled'}, (instance, button) => {button.onclick = () => this.#updateHighlightSettings(button, [0, 1]);}).buildElement()
|
||||
.addButton({'data-status': 'Disabled', 'aria-label': 'Sub-pixel disabled'}, (instance, button) => {button.onclick = () => this.#updateHighlightSettings(button, [1, 1]);}).buildElement()
|
||||
.buildElement()
|
||||
.buildElement()
|
||||
.buildElement();
|
||||
|
||||
// TODO: First-time load of highlight settings from user storage
|
||||
}
|
||||
|
||||
/** Updates the display of the highlight buttons in the settings window.
|
||||
* Additionally, it will update user settings with the new selection.
|
||||
* @param {HTMLButtonElement} button - The button that was pressed
|
||||
* @param {Array<number, number>} coords - The relative coordinates of the button
|
||||
*/
|
||||
#updateHighlightSettings(button, coords) {
|
||||
|
||||
console.log(coords);
|
||||
|
||||
button.disabled = true; // Disabled the button until we are done
|
||||
|
||||
const status = button.dataset['status']; // Obtains the current status of the button
|
||||
|
||||
/** Obtains the old highlight storage, or sets it to default. @type {Array<number[]>} */
|
||||
const userStorageOld = this.userSettings?.highlight || [[1, 0, 1], [2, 0, 0], [1, -1, 0], [1, 1, 0], [1, 0, -1]];
|
||||
|
||||
let userStorageChange = [2, 0, 0]; // The new change to the user storage
|
||||
|
||||
const userStorageNew = userStorageOld; // The old storage with the new change
|
||||
|
||||
console.log(userStorageOld);
|
||||
|
||||
// For each different type of status...
|
||||
switch (status) {
|
||||
|
||||
// If the button was in the "Disabled" state
|
||||
case 'Disabled':
|
||||
|
||||
// Change to "Incorrect"
|
||||
button.dataset['status'] = 'Incorrect';
|
||||
button.ariaLabel = 'Sub-pixel incorrect';
|
||||
userStorageChange = [1, ...coords];
|
||||
break;
|
||||
|
||||
// If the button was in the "Incorrect" state
|
||||
case 'Incorrect':
|
||||
|
||||
// Change to "Template"
|
||||
button.dataset['status'] = 'Template';
|
||||
button.ariaLabel = 'Sub-pixel template';
|
||||
userStorageChange = [2, ...coords];
|
||||
break;
|
||||
|
||||
// If the button was in the "Template" state
|
||||
case 'Template':
|
||||
|
||||
// Change to "Disabled"
|
||||
button.dataset['status'] = 'Disabled';
|
||||
button.ariaLabel = 'Sub-pixel disabled';
|
||||
userStorageChange = [0, ...coords];
|
||||
break;
|
||||
}
|
||||
|
||||
console.log(userStorageChange);
|
||||
|
||||
// Finds the index of the pixel to change
|
||||
const indexOfChange = userStorageOld.findIndex(([, x, y]) => ((x == userStorageChange[1]) && (y == userStorageChange[2])));
|
||||
|
||||
console.log(indexOfChange);
|
||||
|
||||
// If the new sub-pixel state is NOT disabled
|
||||
if (userStorageChange[0] != 0) {
|
||||
|
||||
// If a sub-pixel was found...
|
||||
if (indexOfChange != -1) {
|
||||
userStorageNew[indexOfChange] = userStorageChange;
|
||||
} else {
|
||||
userStorageNew.push(userStorageChange);
|
||||
}
|
||||
} else if (indexOfChange != -1) {
|
||||
// Else, it is disabled. We want to remove it if it exists.
|
||||
userStorageNew.splice(indexOfChange, 1); // Removes 1 index from the array at the index of the pixel change
|
||||
}
|
||||
|
||||
console.log(userStorageNew);
|
||||
|
||||
this.userSettings['highlight'] = userStorageNew;
|
||||
// TODO: Add timer update here
|
||||
|
||||
button.disabled = false; // Reenables the button since we are done
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue