mirror of
https://github.com/SwingTheVine/Wplace-BlueMarble.git
synced 2026-03-11 17:15:38 +00:00
Filter Minimized Window UI Done
This commit is contained in:
parent
a20adef713
commit
0f34b78279
12 changed files with 346 additions and 108 deletions
33
dist/BlueMarble-For-GreasyFork.user.css
vendored
33
dist/BlueMarble-For-GreasyFork.user.css
vendored
|
|
@ -277,6 +277,12 @@ input[type=file] {
|
|||
font-size: 1.6em;
|
||||
font-family: monospace;
|
||||
}
|
||||
.bm-container {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
.bm-windowed h1 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* src/WindowFilter.css */
|
||||
#bm-window-filter p svg {
|
||||
|
|
@ -349,6 +355,33 @@ input[type=file] {
|
|||
#bm-window-filter .bm-filter-color.bm-color-hide {
|
||||
display: none;
|
||||
}
|
||||
.bm-windowed .bm-filter-flex {
|
||||
flex-direction: column;
|
||||
gap: 0.25em;
|
||||
}
|
||||
.bm-windowed .bm-filter-color {
|
||||
width: auto;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.bm-windowed .bm-filter-container-rgb {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
gap: 0.5ch;
|
||||
align-items: center;
|
||||
padding: 0.1em 0.5ch;
|
||||
border: none;
|
||||
border-radius: 1em;
|
||||
}
|
||||
#bm-window-filter.bm-windowed .bm-filter-container-rgb button {
|
||||
padding: 0.5em 0.25ch;
|
||||
}
|
||||
.bm-windowed .bm-filter-container-rgb svg {
|
||||
width: 3ch;
|
||||
}
|
||||
.bm-windowed .bm-filter-color h2 {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
/* src/WindowWizard.css */
|
||||
#bm-wizard-tlist {
|
||||
|
|
|
|||
142
dist/BlueMarble-For-GreasyFork.user.js
vendored
142
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.90.38
|
||||
// @version 0.90.59
|
||||
// @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
|
||||
|
|
@ -2775,7 +2775,7 @@ Did you try clicking the canvas first?`);
|
|||
this.updateInnerHTML("#bm-filter-tot-remaining", `<b>Remaining:</b> ${localizeNumber((this.allPixelsTotal || 0) - (this.allPixelsCorrectTotal || 0))} (${localizePercent(((this.allPixelsTotal || 0) - (this.allPixelsCorrectTotal || 0)) / (this.allPixelsTotal || 1))})`);
|
||||
this.updateInnerHTML("#bm-filter-tot-completed", `<b>Completed at:</b> <time datetime="${this.timeRemaining.toISOString().replace(/\.\d{3}Z$/, "Z")}">${this.timeRemainingLocalized}</time>`);
|
||||
__privateMethod(this, _WindowFilter_instances, buildColorList_fn).call(this, scrollableContainer);
|
||||
__privateMethod(this, _WindowFilter_instances, sortColorList_fn).call(this, "id", "ascending", false);
|
||||
__privateMethod(this, _WindowFilter_instances, sortColorList_fn).call(this, this.sortPrimary, this.sortSecondary, this.showUnused);
|
||||
}
|
||||
/** Spawns a windowed Color Filter window.
|
||||
* If another color filter window already exists, we DON'T spawn another!
|
||||
|
|
@ -2792,10 +2792,10 @@ Did you try clicking the canvas first?`);
|
|||
button.ontouchend = () => {
|
||||
button.click();
|
||||
};
|
||||
}).buildElement().addDiv().buildElement().addDiv({ "class": "bm-flex-center" }).addButton({ "class": "bm-button-circle", "textContent": "\u{1F5D7}", "aria-label": 'Switch to windowed mode for "Color Filter"' }, (instance, button) => {
|
||||
}).buildElement().addDiv().buildElement().addDiv({ "class": "bm-flex-center" }).addButton({ "class": "bm-button-circle", "textContent": "\u{1F5D6}", "aria-label": 'Switch to fullscreen mode for "Color Filter"' }, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
document.querySelector(`#${this.windowID}`)?.remove();
|
||||
this.buildWindowed();
|
||||
this.buildWindow();
|
||||
};
|
||||
button.ontouchend = () => {
|
||||
button.click();
|
||||
|
|
@ -2807,7 +2807,19 @@ Did you try clicking the canvas first?`);
|
|||
button.ontouchend = () => {
|
||||
button.click();
|
||||
};
|
||||
}).buildElement().buildElement().buildElement().buildElement().buildOverlay(this.windowParent);
|
||||
}).buildElement().buildElement().buildElement().addDiv({ "class": "bm-window-content" }).addDiv({ "class": "bm-container bm-center-vertically" }).addHeader(1, { "textContent": "Color Filter" }).buildElement().buildElement().addHr().buildElement().addDiv({ "class": "bm-container bm-flex-between bm-center-vertically", "style": "gap: 1.5ch;" }).addButton({ "textContent": "None" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _WindowFilter_instances, selectColorList_fn).call(this, false);
|
||||
}).buildElement().addButton({ "textContent": "Refresh" }, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
};
|
||||
}).buildElement().addButton({ "textContent": "All" }, (instance, button) => {
|
||||
button.onclick = () => __privateMethod(this, _WindowFilter_instances, selectColorList_fn).call(this, true);
|
||||
}).buildElement().buildElement().addDiv({ "class": "bm-container bm-scrollable" }).buildElement().buildElement().buildElement().buildOverlay(this.windowParent);
|
||||
this.handleDrag(`#${this.windowID}.bm-window`, `#${this.windowID} .bm-dragbar`);
|
||||
const scrollableContainer = document.querySelector(`#${this.windowID} .bm-container.bm-scrollable`);
|
||||
__privateMethod(this, _WindowFilter_instances, calculatePixelStatistics_fn).call(this);
|
||||
__privateMethod(this, _WindowFilter_instances, buildColorList_fn).call(this, scrollableContainer);
|
||||
__privateMethod(this, _WindowFilter_instances, sortColorList_fn).call(this, this.sortPrimary, this.sortSecondary, this.showUnused);
|
||||
}
|
||||
};
|
||||
_WindowFilter_instances = new WeakSet();
|
||||
|
|
@ -2816,6 +2828,8 @@ Did you try clicking the canvas first?`);
|
|||
* @since 0.88.222
|
||||
*/
|
||||
buildColorList_fn = function(parentElement) {
|
||||
const isWindowedMode = parentElement.closest(`#${this.windowID}`)?.classList.contains("bm-windowed");
|
||||
console.log(`Is Windowed Mode: ${isWindowedMode}`);
|
||||
const colorList = new Overlay(this.name, this.version);
|
||||
colorList.addDiv({ "class": "bm-filter-flex" });
|
||||
for (const color of this.palette) {
|
||||
|
|
@ -2841,45 +2855,89 @@ Did you try clicking the canvas first?`);
|
|||
}
|
||||
const colorIncorrect = parseInt(colorTotal) - parseInt(colorCorrect);
|
||||
const isColorHidden = !!(this.templateManager.shouldFilterColor.get(color.id) || false);
|
||||
colorList.addDiv({
|
||||
"class": "bm-container bm-filter-color bm-flex-between",
|
||||
"data-id": color.id,
|
||||
"data-name": color.name,
|
||||
"data-premium": +color.premium,
|
||||
"data-correct": !Number.isNaN(parseInt(colorCorrect)) ? colorCorrect : "0",
|
||||
"data-total": colorTotal,
|
||||
"data-percent": colorPercent.slice(-1) == "%" ? colorPercent.slice(0, -1) : "0",
|
||||
"data-incorrect": colorIncorrect || 0
|
||||
}).addDiv({ "class": "bm-flex-center", "style": "flex-direction: column;" }).addDiv({ "class": "bm-filter-container-rgb", "style": `background-color: rgb(${color.rgb?.map((channel) => Number(channel) || 0).join(",")});` }).addButton(
|
||||
{
|
||||
"class": "bm-button-trans " + bgEffectForButtons,
|
||||
"data-state": isColorHidden ? "hidden" : "shown",
|
||||
"aria-label": isColorHidden ? `Show the color ${color.name || ""} on templates.` : `Hide the color ${color.name || ""} on templates.`,
|
||||
"innerHTML": isColorHidden ? this.eyeClosed.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`) : this.eyeOpen.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`)
|
||||
},
|
||||
(instance, button) => {
|
||||
button.onclick = () => {
|
||||
button.style.textDecoration = "none";
|
||||
button.disabled = true;
|
||||
if (button.dataset["state"] == "shown") {
|
||||
button.innerHTML = this.eyeClosed.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset["state"] = "hidden";
|
||||
button.ariaLabel = `Show the color ${color.name || ""} on templates.`;
|
||||
this.templateManager.shouldFilterColor.set(color.id, true);
|
||||
} else {
|
||||
button.innerHTML = this.eyeOpen.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset["state"] = "shown";
|
||||
button.ariaLabel = `Hide the color ${color.name || ""} on templates.`;
|
||||
this.templateManager.shouldFilterColor.delete(color.id);
|
||||
if (isWindowedMode) {
|
||||
const styleBackgroundStar = `background-size: auto 100%; background-repeat: repeat-x; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><path d='M50,5L79,91L2,39L98,39L21,91' fill='${textColorForPaletteColorBackground}' fill-opacity='.1'/></svg>");`;
|
||||
colorList.addDiv({
|
||||
"class": "bm-container bm-filter-color bm-flex-between",
|
||||
// Dataset
|
||||
"data-id": color.id,
|
||||
"data-name": color.name,
|
||||
"data-premium": +color.premium,
|
||||
"data-correct": !Number.isNaN(parseInt(colorCorrect)) ? colorCorrect : "0",
|
||||
"data-total": colorTotal,
|
||||
"data-percent": colorPercent.slice(-1) == "%" ? colorPercent.slice(0, -1) : "0",
|
||||
"data-incorrect": colorIncorrect || 0
|
||||
}).addDiv({ "class": "bm-filter-container-rgb", "style": `background-color: rgb(${color.rgb?.map((channel) => Number(channel) || 0).join(",")});${color.premium ? styleBackgroundStar : ""}` }).addButton(
|
||||
{
|
||||
"class": "bm-button-trans " + bgEffectForButtons,
|
||||
"data-state": isColorHidden ? "hidden" : "shown",
|
||||
"aria-label": isColorHidden ? `Show the color ${color.name || ""} on templates.` : `Hide the color ${color.name || ""} on templates.`,
|
||||
"innerHTML": isColorHidden ? this.eyeClosed.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`) : this.eyeOpen.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`)
|
||||
},
|
||||
(instance, button) => {
|
||||
button.onclick = () => {
|
||||
button.style.textDecoration = "none";
|
||||
button.disabled = true;
|
||||
if (button.dataset["state"] == "shown") {
|
||||
button.innerHTML = this.eyeClosed.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset["state"] = "hidden";
|
||||
button.ariaLabel = `Show the color ${color.name || ""} on templates.`;
|
||||
this.templateManager.shouldFilterColor.set(color.id, true);
|
||||
} else {
|
||||
button.innerHTML = this.eyeOpen.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset["state"] = "shown";
|
||||
button.ariaLabel = `Hide the color ${color.name || ""} on templates.`;
|
||||
this.templateManager.shouldFilterColor.delete(color.id);
|
||||
}
|
||||
button.disabled = false;
|
||||
button.style.textDecoration = "";
|
||||
};
|
||||
if (!color.id) {
|
||||
button.disabled = true;
|
||||
}
|
||||
button.disabled = false;
|
||||
button.style.textDecoration = "";
|
||||
};
|
||||
if (!color.id) {
|
||||
button.disabled = true;
|
||||
}
|
||||
}
|
||||
).buildElement().buildElement().addSmall({ "textContent": color.id == -2 ? "???????" : colorValueHex }).buildElement().buildElement().addDiv({ "class": "bm-flex-between" }).addHeader(2, { "textContent": (color.premium ? "\u2605 " : "") + color.name }).buildElement().addDiv({ "class": "bm-flex-between", "style": "gap: 1.5ch;" }).addSmall({ "textContent": `#${color.id}` }).buildElement().addSmall({ "textContent": `${colorCorrectLocalized} / ${colorTotalLocalized}` }).buildElement().buildElement().addP({ "textContent": `${typeof colorIncorrect == "number" && !isNaN(colorIncorrect) ? colorIncorrect : "???"} incorrect pixels. Completed: ${colorPercent}` }).buildElement().buildElement().buildElement();
|
||||
).buildElement().addSmall({ "textContent": `#${color.id.toString().padStart(2, 0)}`, "style": `color: ${color.id == -1 || color.id == 0 ? "white" : textColorForPaletteColorBackground}` }).buildElement().addHeader(2, { "textContent": color.name, "style": `color: ${color.id == -1 || color.id == 0 ? "white" : textColorForPaletteColorBackground}` }).buildElement().addSmall({ "textContent": `${colorCorrectLocalized} / ${colorTotalLocalized}`, "style": `color: ${color.id == -1 || color.id == 0 ? "white" : textColorForPaletteColorBackground}; flex: 1 1 auto; text-align: right;` }).buildElement().buildElement().buildElement();
|
||||
} else {
|
||||
colorList.addDiv({
|
||||
"class": "bm-container bm-filter-color bm-flex-between",
|
||||
"data-id": color.id,
|
||||
"data-name": color.name,
|
||||
"data-premium": +color.premium,
|
||||
"data-correct": !Number.isNaN(parseInt(colorCorrect)) ? colorCorrect : "0",
|
||||
"data-total": colorTotal,
|
||||
"data-percent": colorPercent.slice(-1) == "%" ? colorPercent.slice(0, -1) : "0",
|
||||
"data-incorrect": colorIncorrect || 0
|
||||
}).addDiv({ "class": "bm-flex-center", "style": "flex-direction: column;" }).addDiv({ "class": "bm-filter-container-rgb", "style": `background-color: rgb(${color.rgb?.map((channel) => Number(channel) || 0).join(",")});` }).addButton(
|
||||
{
|
||||
"class": "bm-button-trans " + bgEffectForButtons,
|
||||
"data-state": isColorHidden ? "hidden" : "shown",
|
||||
"aria-label": isColorHidden ? `Show the color ${color.name || ""} on templates.` : `Hide the color ${color.name || ""} on templates.`,
|
||||
"innerHTML": isColorHidden ? this.eyeClosed.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`) : this.eyeOpen.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`)
|
||||
},
|
||||
(instance, button) => {
|
||||
button.onclick = () => {
|
||||
button.style.textDecoration = "none";
|
||||
button.disabled = true;
|
||||
if (button.dataset["state"] == "shown") {
|
||||
button.innerHTML = this.eyeClosed.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset["state"] = "hidden";
|
||||
button.ariaLabel = `Show the color ${color.name || ""} on templates.`;
|
||||
this.templateManager.shouldFilterColor.set(color.id, true);
|
||||
} else {
|
||||
button.innerHTML = this.eyeOpen.replace("<svg", `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset["state"] = "shown";
|
||||
button.ariaLabel = `Hide the color ${color.name || ""} on templates.`;
|
||||
this.templateManager.shouldFilterColor.delete(color.id);
|
||||
}
|
||||
button.disabled = false;
|
||||
button.style.textDecoration = "";
|
||||
};
|
||||
if (!color.id) {
|
||||
button.disabled = true;
|
||||
}
|
||||
}
|
||||
).buildElement().buildElement().addSmall({ "textContent": color.id == -2 ? "???????" : colorValueHex }).buildElement().buildElement().addDiv({ "class": "bm-flex-between" }).addHeader(2, { "textContent": (color.premium ? "\u2605 " : "") + color.name }).buildElement().addDiv({ "class": "bm-flex-between", "style": "gap: 1.5ch;" }).addSmall({ "textContent": `#${color.id.toString().padStart(2, 0)}` }).buildElement().addSmall({ "textContent": `${colorCorrectLocalized} / ${colorTotalLocalized}` }).buildElement().buildElement().addP({ "textContent": `${typeof colorIncorrect == "number" && !isNaN(colorIncorrect) ? colorIncorrect : "???"} incorrect pixels. Completed: ${colorPercent}` }).buildElement().buildElement().buildElement();
|
||||
}
|
||||
}
|
||||
colorList.buildOverlay(parentElement);
|
||||
};
|
||||
|
|
|
|||
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-1077-black?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Patches" src="https://img.shields.io/badge/Total_Patches-1098-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-5908-blue?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Comments" src="https://img.shields.io/badge/Lines_Of_Comments-5160-blue?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Compression" src="https://img.shields.io/badge/Compression-73.34%25-blue"></a>
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.90.38",
|
||||
"version": "0.90.59",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.90.38",
|
||||
"version": "0.90.59",
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"jsdoc": "^4.0.5",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.90.38",
|
||||
"version": "0.90.59",
|
||||
"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.90.38
|
||||
// @version 0.90.59
|
||||
// @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
|
||||
|
|
|
|||
|
|
@ -94,4 +94,45 @@
|
|||
/* Filter window hide unused colors */
|
||||
#bm-window-filter .bm-filter-color.bm-color-hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* WINDOWED MODE */
|
||||
|
||||
/* Filter flex in windowed mode */
|
||||
.bm-windowed .bm-filter-flex {
|
||||
flex-direction: column;
|
||||
gap: 0.25em;
|
||||
}
|
||||
|
||||
/* Filter color in windowed mode */
|
||||
.bm-windowed .bm-filter-color {
|
||||
width: auto;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Filter window container for RGB color display in windowed mode */
|
||||
.bm-windowed .bm-filter-container-rgb {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
gap: 0.5ch;
|
||||
align-items: center;
|
||||
padding: 0.1em 0.5ch;
|
||||
border: none;
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
/* Filter window hide color button */
|
||||
#bm-window-filter.bm-windowed .bm-filter-container-rgb button {
|
||||
padding: 0.5em 0.25ch;
|
||||
}
|
||||
|
||||
/* Filter window hide color button SVG in windowed mode */
|
||||
.bm-windowed .bm-filter-container-rgb svg {
|
||||
width: 3ch;
|
||||
}
|
||||
|
||||
/* Filter window header 2 in windowed mode */
|
||||
.bm-windowed .bm-filter-color h2 {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
|
@ -173,6 +173,8 @@ export default class WindowFilter extends Overlay {
|
|||
// Obtains the scrollable container to put the color filter in
|
||||
const scrollableContainer = document.querySelector(`#${this.windowID} .bm-container.bm-scrollable`);
|
||||
|
||||
// Calculates the pixel statistics
|
||||
// E.g. correct pixels per color
|
||||
this.#calculatePixelStatistics();
|
||||
|
||||
// Displays some template statistics to the user
|
||||
|
|
@ -184,7 +186,7 @@ export default class WindowFilter extends Overlay {
|
|||
|
||||
// These run when the user opens the Color Filter window
|
||||
this.#buildColorList(scrollableContainer);
|
||||
this.#sortColorList('id', 'ascending', false);
|
||||
this.#sortColorList(this.sortPrimary, this.sortSecondary, this.showUnused);
|
||||
}
|
||||
|
||||
/** Spawns a windowed Color Filter window.
|
||||
|
|
@ -209,10 +211,10 @@ export default class WindowFilter extends Overlay {
|
|||
}).buildElement()
|
||||
.addDiv().buildElement() // Contains the minimized h1 element
|
||||
.addDiv({'class': 'bm-flex-center'})
|
||||
.addButton({'class': 'bm-button-circle', 'textContent': '🗗', 'aria-label': 'Switch to windowed mode for "Color Filter"'}, (instance, button) => {
|
||||
.addButton({'class': 'bm-button-circle', 'textContent': '🗖', 'aria-label': 'Switch to fullscreen mode for "Color Filter"'}, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
document.querySelector(`#${this.windowID}`)?.remove();
|
||||
this.buildWindowed();
|
||||
this.buildWindow();
|
||||
};
|
||||
button.ontouchend = () => {button.click();}; // Needed only to negate weird interaction with dragbar
|
||||
}).buildElement()
|
||||
|
|
@ -223,9 +225,40 @@ export default class WindowFilter extends Overlay {
|
|||
.buildElement()
|
||||
.buildElement()
|
||||
.addDiv({'class': 'bm-window-content'})
|
||||
|
||||
.addDiv({'class': 'bm-container bm-center-vertically'})
|
||||
.addHeader(1, {'textContent': 'Color Filter'}).buildElement()
|
||||
.buildElement()
|
||||
.addHr().buildElement()
|
||||
.addDiv({'class': 'bm-container bm-flex-between bm-center-vertically', 'style': 'gap: 1.5ch;'})
|
||||
.addButton({'textContent': 'None'}, (instance, button) => {
|
||||
button.onclick = () => this.#selectColorList(false);
|
||||
}).buildElement()
|
||||
.addButton({'textContent': 'Refresh'}, (instance, button) => {
|
||||
button.onclick = () => {};
|
||||
}).buildElement()
|
||||
.addButton({'textContent': 'All'}, (instance, button) => {
|
||||
button.onclick = () => this.#selectColorList(true);
|
||||
}).buildElement()
|
||||
.buildElement()
|
||||
.addDiv({'class': 'bm-container bm-scrollable'})
|
||||
// Color list will appear here
|
||||
.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`);
|
||||
|
||||
// Obtains the scrollable container to put the color filter in
|
||||
const scrollableContainer = document.querySelector(`#${this.windowID} .bm-container.bm-scrollable`);
|
||||
|
||||
// Calculates the pixel statistics
|
||||
// E.g. correct pixels per color
|
||||
this.#calculatePixelStatistics();
|
||||
|
||||
// These run when the user opens the Color Filter window
|
||||
this.#buildColorList(scrollableContainer);
|
||||
this.#sortColorList(this.sortPrimary, this.sortSecondary, this.showUnused);
|
||||
}
|
||||
|
||||
/** Creates the color list container.
|
||||
|
|
@ -234,6 +267,12 @@ export default class WindowFilter extends Overlay {
|
|||
*/
|
||||
#buildColorList(parentElement) {
|
||||
|
||||
// Figures out if this window is fullscreen or windowed mode
|
||||
const isWindowedMode = parentElement.closest(`#${this.windowID}`)?.classList.contains('bm-windowed');
|
||||
// Note: `undefined` is expected to behave as if `false`
|
||||
|
||||
console.log(`Is Windowed Mode: ${isWindowedMode}`);
|
||||
|
||||
const colorList = new Overlay(this.name, this.version);
|
||||
colorList.addDiv({'class': 'bm-filter-flex'})
|
||||
// We leave it open so we can add children to the grid
|
||||
|
|
@ -292,60 +331,115 @@ export default class WindowFilter extends Overlay {
|
|||
|
||||
const isColorHidden = !!(this.templateManager.shouldFilterColor.get(color.id) || false);
|
||||
|
||||
// Construct the DOM tree for color in color list
|
||||
colorList.addDiv({'class': 'bm-container bm-filter-color bm-flex-between',
|
||||
'data-id': color.id,
|
||||
'data-name': color.name,
|
||||
'data-premium': +color.premium,
|
||||
'data-correct': !Number.isNaN(parseInt(colorCorrect)) ? colorCorrect : '0',
|
||||
'data-total': colorTotal,
|
||||
'data-percent': (colorPercent.slice(-1) == '%') ? colorPercent.slice(0, -1) : '0',
|
||||
'data-incorrect': colorIncorrect || 0
|
||||
})
|
||||
.addDiv({'class': 'bm-flex-center', 'style': 'flex-direction: column;'})
|
||||
.addDiv({'class': 'bm-filter-container-rgb', 'style': `background-color: rgb(${color.rgb?.map(channel => Number(channel) || 0).join(',')});`})
|
||||
.addButton({
|
||||
'class': 'bm-button-trans ' + bgEffectForButtons,
|
||||
'data-state': isColorHidden ? 'hidden' : 'shown',
|
||||
'aria-label': isColorHidden ? `Show the color ${color.name || ''} on templates.` : `Hide the color ${color.name || ''} on templates.`,
|
||||
'innerHTML': isColorHidden ? this.eyeClosed.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`) : this.eyeOpen.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`)},
|
||||
(instance, button) => {
|
||||
// Add the color to the color list DOM
|
||||
if (isWindowedMode) {
|
||||
|
||||
// When the button is clicked
|
||||
button.onclick = () => {
|
||||
button.style.textDecoration = 'none';
|
||||
button.disabled = true;
|
||||
if (button.dataset['state'] == 'shown') {
|
||||
button.innerHTML = this.eyeClosed.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset['state'] = 'hidden';
|
||||
button.ariaLabel = `Show the color ${color.name || ''} on templates.`;
|
||||
this.templateManager.shouldFilterColor.set(color.id, true);
|
||||
} else {
|
||||
button.innerHTML = this.eyeOpen.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset['state'] = 'shown';
|
||||
button.ariaLabel = `Hide the color ${color.name || ''} on templates.`;
|
||||
this.templateManager.shouldFilterColor.delete(color.id);
|
||||
// The star pattern for premium colors
|
||||
const styleBackgroundStar = `background-size: auto 100%; background-repeat: repeat-x; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><path d='M50,5L79,91L2,39L98,39L21,91' fill='${textColorForPaletteColorBackground}' fill-opacity='.1'/></svg>");`;
|
||||
|
||||
// Add windowed mode color DOM to color list
|
||||
colorList.addDiv({'class': 'bm-container bm-filter-color bm-flex-between',
|
||||
// Dataset
|
||||
'data-id': color.id,
|
||||
'data-name': color.name,
|
||||
'data-premium': +color.premium,
|
||||
'data-correct': !Number.isNaN(parseInt(colorCorrect)) ? colorCorrect : '0',
|
||||
'data-total': colorTotal,
|
||||
'data-percent': (colorPercent.slice(-1) == '%') ? colorPercent.slice(0, -1) : '0',
|
||||
'data-incorrect': colorIncorrect || 0
|
||||
}).addDiv({'class': 'bm-filter-container-rgb', 'style': `background-color: rgb(${color.rgb?.map(channel => Number(channel) || 0).join(',')});${color.premium ? styleBackgroundStar : ''}`})
|
||||
.addButton({
|
||||
'class': 'bm-button-trans ' + bgEffectForButtons,
|
||||
'data-state': isColorHidden ? 'hidden' : 'shown',
|
||||
'aria-label': isColorHidden ? `Show the color ${color.name || ''} on templates.` : `Hide the color ${color.name || ''} on templates.`,
|
||||
'innerHTML': isColorHidden ? this.eyeClosed.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`) : this.eyeOpen.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`)},
|
||||
(instance, button) => {
|
||||
|
||||
// When the button is clicked
|
||||
button.onclick = () => {
|
||||
button.style.textDecoration = 'none';
|
||||
button.disabled = true;
|
||||
if (button.dataset['state'] == 'shown') {
|
||||
button.innerHTML = this.eyeClosed.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset['state'] = 'hidden';
|
||||
button.ariaLabel = `Show the color ${color.name || ''} on templates.`;
|
||||
this.templateManager.shouldFilterColor.set(color.id, true);
|
||||
} else {
|
||||
button.innerHTML = this.eyeOpen.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset['state'] = 'shown';
|
||||
button.ariaLabel = `Hide the color ${color.name || ''} on templates.`;
|
||||
this.templateManager.shouldFilterColor.delete(color.id);
|
||||
}
|
||||
button.disabled = false;
|
||||
button.style.textDecoration = '';
|
||||
}
|
||||
button.disabled = false;
|
||||
button.style.textDecoration = '';
|
||||
}
|
||||
|
||||
// Disables the "hide color" button if the color is "Transparent" (or no ID exists)
|
||||
if (!color.id) {button.disabled = true;}
|
||||
}
|
||||
).buildElement()
|
||||
.buildElement()
|
||||
.addSmall({'textContent': (color.id == -2) ? '???????' : colorValueHex}).buildElement()
|
||||
.buildElement()
|
||||
.addDiv({'class': 'bm-flex-between'})
|
||||
.addHeader(2, {'textContent': (color.premium ? '★ ' : '') + color.name}).buildElement()
|
||||
.addDiv({'class': 'bm-flex-between', 'style': 'gap: 1.5ch;'})
|
||||
.addSmall({'textContent': `#${color.id}`}).buildElement()
|
||||
.addSmall({'textContent': `${colorCorrectLocalized} / ${colorTotalLocalized}`}).buildElement()
|
||||
.buildElement()
|
||||
.addP({'textContent': `${((typeof colorIncorrect == 'number') && !isNaN(colorIncorrect)) ? colorIncorrect : '???'} incorrect pixels. Completed: ${colorPercent}`}).buildElement()
|
||||
.buildElement()
|
||||
.buildElement()
|
||||
// Disables the "hide color" button if the color is "Transparent" (or no ID exists)
|
||||
if (!color.id) {button.disabled = true;}
|
||||
}
|
||||
).buildElement()
|
||||
.addSmall({'textContent': `#${color.id.toString().padStart(2, 0)}`, 'style': `color: ${((color.id == -1) || (color.id == 0)) ? 'white' : textColorForPaletteColorBackground}`}).buildElement()
|
||||
.addHeader(2, {'textContent': color.name, 'style': `color: ${((color.id == -1) || (color.id == 0)) ? 'white' : textColorForPaletteColorBackground}`}).buildElement()
|
||||
.addSmall({'textContent': `${colorCorrectLocalized} / ${colorTotalLocalized}`, 'style': `color: ${((color.id == -1) || (color.id == 0)) ? 'white' : textColorForPaletteColorBackground}; flex: 1 1 auto; text-align: right;`}).buildElement()
|
||||
.buildElement()
|
||||
.buildElement();
|
||||
} else {
|
||||
// Else we are in fullscreen mode.
|
||||
|
||||
// Add fullscreen mode color DOM to color list
|
||||
colorList.addDiv({'class': 'bm-container bm-filter-color bm-flex-between',
|
||||
'data-id': color.id,
|
||||
'data-name': color.name,
|
||||
'data-premium': +color.premium,
|
||||
'data-correct': !Number.isNaN(parseInt(colorCorrect)) ? colorCorrect : '0',
|
||||
'data-total': colorTotal,
|
||||
'data-percent': (colorPercent.slice(-1) == '%') ? colorPercent.slice(0, -1) : '0',
|
||||
'data-incorrect': colorIncorrect || 0
|
||||
}).addDiv({'class': 'bm-flex-center', 'style': 'flex-direction: column;'})
|
||||
.addDiv({'class': 'bm-filter-container-rgb', 'style': `background-color: rgb(${color.rgb?.map(channel => Number(channel) || 0).join(',')});`})
|
||||
.addButton({
|
||||
'class': 'bm-button-trans ' + bgEffectForButtons,
|
||||
'data-state': isColorHidden ? 'hidden' : 'shown',
|
||||
'aria-label': isColorHidden ? `Show the color ${color.name || ''} on templates.` : `Hide the color ${color.name || ''} on templates.`,
|
||||
'innerHTML': isColorHidden ? this.eyeClosed.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`) : this.eyeOpen.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`)},
|
||||
(instance, button) => {
|
||||
|
||||
// When the button is clicked
|
||||
button.onclick = () => {
|
||||
button.style.textDecoration = 'none';
|
||||
button.disabled = true;
|
||||
if (button.dataset['state'] == 'shown') {
|
||||
button.innerHTML = this.eyeClosed.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset['state'] = 'hidden';
|
||||
button.ariaLabel = `Show the color ${color.name || ''} on templates.`;
|
||||
this.templateManager.shouldFilterColor.set(color.id, true);
|
||||
} else {
|
||||
button.innerHTML = this.eyeOpen.replace('<svg', `<svg fill="${textColorForPaletteColorBackground}"`);
|
||||
button.dataset['state'] = 'shown';
|
||||
button.ariaLabel = `Hide the color ${color.name || ''} on templates.`;
|
||||
this.templateManager.shouldFilterColor.delete(color.id);
|
||||
}
|
||||
button.disabled = false;
|
||||
button.style.textDecoration = '';
|
||||
}
|
||||
|
||||
// Disables the "hide color" button if the color is "Transparent" (or no ID exists)
|
||||
if (!color.id) {button.disabled = true;}
|
||||
}
|
||||
).buildElement()
|
||||
.buildElement()
|
||||
.addSmall({'textContent': (color.id == -2) ? '???????' : colorValueHex}).buildElement()
|
||||
.buildElement()
|
||||
.addDiv({'class': 'bm-flex-between'})
|
||||
.addHeader(2, {'textContent': (color.premium ? '★ ' : '') + color.name}).buildElement()
|
||||
.addDiv({'class': 'bm-flex-between', 'style': 'gap: 1.5ch;'})
|
||||
.addSmall({'textContent': `#${color.id.toString().padStart(2, 0)}`}).buildElement()
|
||||
.addSmall({'textContent': `${colorCorrectLocalized} / ${colorTotalLocalized}`}).buildElement()
|
||||
.buildElement()
|
||||
.addP({'textContent': `${((typeof colorIncorrect == 'number') && !isNaN(colorIncorrect)) ? colorIncorrect : '???'} incorrect pixels. Completed: ${colorPercent}`}).buildElement()
|
||||
.buildElement()
|
||||
.buildElement();
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the colors to the color container in the filter window
|
||||
|
|
|
|||
|
|
@ -338,4 +338,16 @@ input[type="file"] {
|
|||
line-height: 1 !important;
|
||||
font-size: 1.6em;
|
||||
font-family: monospace;
|
||||
}
|
||||
}
|
||||
|
||||
/* WINDOWED MODE */
|
||||
|
||||
/* Containers for "sections" of elements in windowed mode */
|
||||
.bm-container {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
/* Header 1 in windowed mode */
|
||||
.bm-windowed h1 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue