mirror of
https://github.com/SwingTheVine/Wplace-BlueMarble.git
synced 2026-05-11 20:40:45 +00:00
Merge
This commit is contained in:
commit
11590007a7
9 changed files with 156 additions and 98 deletions
2
dist/BlueMarble.user.css
vendored
2
dist/BlueMarble.user.css
vendored
|
|
@ -1 +1 @@
|
|||
#bm-l{position:fixed;background-color:#153063e6;color:#fff;padding:10px;border-radius:8px;z-index:9000;transition:all .3s ease;max-width:300px;width:auto}#bm-4,#bm-l hr,#bm-3,#bm-1{transition:opacity .2s ease,height .2s ease}div#bm-l{font-family:Roboto Mono,Courier New,Monaco,DejaVu Sans Mono,monospace,Arial;letter-spacing:.05em}#bm-g{margin-bottom:.5em;background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="5" height="5"><circle cx="3" cy="3" r="1.5" fill="CornflowerBlue" /></svg>') repeat;cursor:grab;width:100%;height:1em}#bm-g.dragging{cursor:grabbing}#bm-7{margin-bottom:.5em}#bm-7[style*="text-align: center"]{display:flex;flex-direction:column;align-items:center;justify-content:center}#bm-l[style*="padding: 5px"]{width:auto!important;max-width:300px;min-width:200px}#bm-l img{display:inline-block;height:2.5em;margin-right:1ch;vertical-align:middle;transition:opacity .2s ease}#bm-7[style*="text-align: center"] img{display:block;margin:0 auto}#bm-g{transition:margin-bottom .2s ease}#bm-l h1{display:inline-block;font-size:x-large;font-weight:700;vertical-align:middle}#bm-3 input[type=checkbox]{vertical-align:middle;margin-right:.5ch}#bm-3 label{margin-right:.5ch}.bm-p{border:white 1px solid;height:1.5em;width:1.5em;margin-top:2px;text-align:center;line-height:1em;padding:0!important}#bm-c{vertical-align:middle}#bm-c svg{width:50%;margin:0 auto;fill:#111}div:has(>#bm-button-teleport){display:flex;gap:.5ch}#bm-button-favorite svg,#bm-button-template svg{height:1em;margin:2px auto 0;text-align:center;line-height:1em;vertical-align:bottom}#bm-8 input[type=number]{appearance:auto;-moz-appearance:textfield;width:5.5ch;margin-left:1ch;background-color:#0003;padding:0 .5ch;font-size:small}#bm-8 input[type=number]::-webkit-outer-spin-button,#bm-8 input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}#bm-0{display:flex;flex-direction:row;flex-wrap:wrap;align-content:center;justify-content:center;align-items:center;gap:1ch}div:has(>#bm-2)>button{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#bm-a{font-size:small;background-color:#0003;padding:0 .5ch;height:3.75em;width:100%}#bm-1{display:flex;justify-content:space-between}#bm-l small{font-size:x-small;color:#d3d3d3}#bm-4,#bm-3,#bm-8,#bm-0,div:has(>#bm-2),#bm-a{margin-top:.5em}#bm-l button{background-color:#144eb9;border-radius:1em;padding:0 .75ch}#bm-l button:hover,#bm-l button:focus-visible{background-color:#1061e5}#bm-l button:active,#bm-l button:disabled{background-color:#2e97ff}#bm-l button:disabled{text-decoration:line-through}
|
||||
#bm-l{position:fixed;background-color:#153063e6;color:#fff;padding:10px;border-radius:8px;z-index:9000;transition:all .3s ease;max-width:300px;width:auto;will-change:transform;backface-visibility:hidden;-webkit-backface-visibility:hidden;transform-style:preserve-3d;-webkit-transform-style:preserve-3d}#bm-4,#bm-l hr,#bm-3,#bm-1{transition:opacity .2s ease,height .2s ease}div#bm-l{font-family:Roboto Mono,Courier New,Monaco,DejaVu Sans Mono,monospace,Arial;letter-spacing:.05em}#bm-g{margin-bottom:.5em;background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="5" height="5"><circle cx="3" cy="3" r="1.5" fill="CornflowerBlue" /></svg>') repeat;cursor:grab;width:100%;height:1em}#bm-g.dragging{cursor:grabbing}#bm-l:has(#bm-g.dragging){pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}#bm-g.dragging{pointer-events:auto}#bm-7{margin-bottom:.5em}#bm-7[style*="text-align: center"]{display:flex;flex-direction:column;align-items:center;justify-content:center}#bm-l[style*="padding: 5px"]{width:auto!important;max-width:300px;min-width:200px}#bm-l img{display:inline-block;height:2.5em;margin-right:1ch;vertical-align:middle;transition:opacity .2s ease}#bm-7[style*="text-align: center"] img{display:block;margin:0 auto}#bm-g{transition:margin-bottom .2s ease}#bm-l h1{display:inline-block;font-size:x-large;font-weight:700;vertical-align:middle}#bm-3 input[type=checkbox]{vertical-align:middle;margin-right:.5ch}#bm-3 label{margin-right:.5ch}.bm-p{border:white 1px solid;height:1.5em;width:1.5em;margin-top:2px;text-align:center;line-height:1em;padding:0!important}#bm-c{vertical-align:middle}#bm-c svg{width:50%;margin:0 auto;fill:#111}div:has(>#bm-button-teleport){display:flex;gap:.5ch}#bm-button-favorite svg,#bm-button-template svg{height:1em;margin:2px auto 0;text-align:center;line-height:1em;vertical-align:bottom}#bm-8 input[type=number]{appearance:auto;-moz-appearance:textfield;width:5.5ch;margin-left:1ch;background-color:#0003;padding:0 .5ch;font-size:small}#bm-8 input[type=number]::-webkit-outer-spin-button,#bm-8 input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}#bm-0{display:flex;flex-direction:row;flex-wrap:wrap;align-content:center;justify-content:center;align-items:center;gap:1ch}div:has(>#bm-2)>button{width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#bm-2,input[type=file][id*=template]{display:none!important;visibility:hidden!important;position:absolute!important;left:-9999px!important;top:-9999px!important;width:0!important;height:0!important;opacity:0!important;z-index:-9999!important;pointer-events:none!important}#bm-a{font-size:small;background-color:#0003;padding:0 .5ch;height:3.75em;width:100%}#bm-1{display:flex;justify-content:space-between}#bm-l small{font-size:x-small;color:#d3d3d3}#bm-4,#bm-3,#bm-8,#bm-0,div:has(>#bm-2),#bm-a{margin-top:.5em}#bm-l button{background-color:#144eb9;border-radius:1em;padding:0 .75ch}#bm-l button:hover,#bm-l button:focus-visible{background-color:#1061e5}#bm-l button:active,#bm-l button:disabled{background-color:#2e97ff}#bm-l button:disabled{text-decoration:line-through}
|
||||
|
|
|
|||
8
dist/BlueMarble.user.js
vendored
8
dist/BlueMarble.user.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -39,7 +39,7 @@
|
|||
</table>
|
||||
|
||||
<h1>Blue Marble</h1>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Latest Version" src="https://img.shields.io/badge/Latest_Version-0.71.0-lightblue?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Latest Version" src="https://img.shields.io/badge/Latest_Version-0.72.0-lightblue?style=flat"></a>
|
||||
<a href="https://github.com/SwingTheVine/Wplace-BlueMarble/releases" target="_blank" rel="noopener noreferrer"><img alt="Latest Release" src="https://img.shields.io/github/v/release/SwingTheVine/Wplace-BlueMarble?sort=semver&style=flat&label=Latest%20Release&color=blue"></a>
|
||||
<a href="https://github.com/SwingTheVine/Wplace-BlueMarble/blob/main/LICENSE.txt" target="_blank" rel="noopener noreferrer"><img alt="Software License: MPL-2.0" src="https://img.shields.io/badge/Software_License-MPL--2.0-slateblue?style=flat"></a>
|
||||
<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>
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Patches" src="https://img.shields.io/badge/Total_Patches-455-black?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Lines of Code" src="https://tokei.rs/b1/github/SwingTheVine/Wplace-BlueMarble?category=code"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Comments" src="https://tokei.rs/b1/github/SwingTheVine/Wplace-BlueMarble?category=comments"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Compression" src="https://img.shields.io/badge/Compression-76.02%25-blue"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Compression" src="https://img.shields.io/badge/Compression-75.07%25-blue"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Build" src="https://github.com/SwingTheVine/Wplace-BlueMarble/actions/workflows/build.yml/badge.svg"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="CodeQL" src="https://github.com/SwingTheVine/Wplace-BlueMarble/actions/workflows/github-code-scanning/codeql/badge.svg"></a>
|
||||
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.70.4",
|
||||
"version": "0.71.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.70.4",
|
||||
"version": "0.71.0",
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"terser": "^5.43.1"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.71.0",
|
||||
"version": "0.72.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "node build/build.js",
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
// ==UserScript==
|
||||
// @name Blue Marble
|
||||
// @namespace https://github.com/SwingTheVine/
|
||||
// @version 0.71.0
|
||||
// @version 0.72.0
|
||||
// @description A userscript to automate and/or enhance the user experience on Wplace.live. Make sure to comply with the site's Terms of Service, and rules! This script is not affiliated with Wplace.live in any way, use at your own risk. This script is not affiliated with TamperMonkey. The author of this userscript is not responsible for any damages, issues, loss of data, or punishment that may occur as a result of using this script. This script is provided "as is" under the MPL-2.0 license. The "Blue Marble" icon is licensed under CC0 1.0 Universal (CC0 1.0) Public Domain Dedication. The image is owned by NASA.
|
||||
// @author SwingTheVine
|
||||
// @license MPL-2.0
|
||||
// @supportURL https://discord.gg/tpeBPy46hf
|
||||
// @homepageURL https://github.com/SwingTheVine/Wplace-BlueMarble
|
||||
// @icon https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/a3ff8840069a733d4cf4c27b8336beddf3706b60/dist/assets/Favicon.png
|
||||
// @icon https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/6b6a45cba9943e5960c9887654aa704a90c02636/dist/assets/Favicon.png
|
||||
// @updateURL https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/BlueMarble.user.js
|
||||
// @downloadURL https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/BlueMarble.user.js
|
||||
// @run-at document-start
|
||||
// @match *://*.wplace.live/*
|
||||
// @grant GM_getResourceText
|
||||
// @grant GM_addStyle
|
||||
// @resource CSS-BM-File https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/a3ff8840069a733d4cf4c27b8336beddf3706b60/dist/BlueMarble.user.css
|
||||
// @resource CSS-BM-File https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/6b6a45cba9943e5960c9887654aa704a90c02636/dist/BlueMarble.user.css
|
||||
// ==/UserScript==
|
||||
|
||||
// Wplace --> https://wplace.live
|
||||
|
|
|
|||
157
src/Overlay.js
157
src/Overlay.js
|
|
@ -430,8 +430,9 @@ export default class Overlay {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Adds a file input to the overlay. This includes a container and a button.
|
||||
/** Adds a file input to the overlay with enhanced visibility controls.
|
||||
* This input element will have properties shared between all file input elements in the overlay.
|
||||
* Uses multiple hiding methods to prevent browser native text from appearing during minimize/maximize.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the file input that are NOT shared between all overlay file input elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLDivElement, HTMLInputElement, HTMLButtonElement):void} [callback=()=>{}] - Additional JS modification to the file input.
|
||||
|
|
@ -451,7 +452,10 @@ export default class Overlay {
|
|||
*/
|
||||
addInputFile(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {'type': 'file', 'style': 'display: none;'}; // Shared file input DOM properties
|
||||
const properties = {
|
||||
'type': 'file',
|
||||
'style': 'display: none !important; visibility: hidden !important; position: absolute !important; left: -9999px !important; width: 0 !important; height: 0 !important; opacity: 0 !important;'
|
||||
}; // Complete file input hiding to prevent native browser text interference
|
||||
const text = additionalProperties['textContent'] ?? ''; // Retrieves the text content
|
||||
|
||||
delete additionalProperties['textContent']; // Deletes the text content before applying the additional properties to the file input
|
||||
|
|
@ -463,11 +467,15 @@ export default class Overlay {
|
|||
this.buildElement(); // Signifies that we are done adding children to the button
|
||||
this.buildElement(); // Signifies that we are done adding children to the container
|
||||
|
||||
// Prevent file input from being accessible or visible by screen-readers and tabbing
|
||||
input.setAttribute('tabindex', '-1');
|
||||
input.setAttribute('aria-hidden', 'true');
|
||||
|
||||
button.addEventListener('click', () => {
|
||||
input.click(); // Clicks the file input
|
||||
});
|
||||
|
||||
// Changes the button text content (and trims the file name)
|
||||
// Update button text when file is selected
|
||||
input.addEventListener('change', () => {
|
||||
button.style.maxWidth = `${button.offsetWidth}px`;
|
||||
if (input.files.length > 0) {
|
||||
|
|
@ -534,13 +542,19 @@ export default class Overlay {
|
|||
}
|
||||
|
||||
/** Handles dragging of the overlay.
|
||||
* Uses requestAnimationFrame for smooth animations and GPU-accelerated transforms.
|
||||
* @param {string} moveMe - The ID of the element to be moved
|
||||
* @param {string} iMoveThings - The ID of the element to be moved
|
||||
* @param {string} iMoveThings - The ID of the drag handle element
|
||||
* @since 0.8.2
|
||||
*/
|
||||
handleDrag(moveMe, iMoveThings) {
|
||||
let isDragging = false;
|
||||
let offsetX, offsetY = 0;
|
||||
let animationFrame = null;
|
||||
let currentX = 0;
|
||||
let currentY = 0;
|
||||
let targetX = 0;
|
||||
let targetY = 0;
|
||||
|
||||
// Retrieves the elements (allows either '#id' or 'id' to be passed in)
|
||||
moveMe = document.querySelector(moveMe?.[0] == '#' ? moveMe : '#' + moveMe);
|
||||
|
|
@ -552,67 +566,110 @@ export default class Overlay {
|
|||
return; // Kills itself
|
||||
}
|
||||
|
||||
// What to do when the mouse is pressed down on the element that moves things
|
||||
iMoveThings.addEventListener('mousedown', function(event) {
|
||||
// Smooth animation loop using requestAnimationFrame for optimal performance
|
||||
const updatePosition = () => {
|
||||
if (isDragging) {
|
||||
// Only update DOM if position changed significantly (reduce repaints)
|
||||
const deltaX = Math.abs(currentX - targetX);
|
||||
const deltaY = Math.abs(currentY - targetY);
|
||||
|
||||
if (deltaX > 0.5 || deltaY > 0.5) {
|
||||
currentX = targetX;
|
||||
currentY = targetY;
|
||||
|
||||
// Use CSS transform for GPU acceleration instead of left/top
|
||||
moveMe.style.transform = `translate(${currentX}px, ${currentY}px)`;
|
||||
moveMe.style.left = '0px';
|
||||
moveMe.style.top = '0px';
|
||||
moveMe.style.right = '';
|
||||
}
|
||||
|
||||
animationFrame = requestAnimationFrame(updatePosition);
|
||||
}
|
||||
};
|
||||
|
||||
// Cache initial position to avoid expensive getBoundingClientRect calls during drag
|
||||
let initialRect = null;
|
||||
|
||||
const startDrag = (clientX, clientY) => {
|
||||
isDragging = true;
|
||||
offsetX = event.clientX - moveMe.getBoundingClientRect().left;
|
||||
offsetY = event.clientY - moveMe.getBoundingClientRect().top;
|
||||
document.body.style.userSelect = 'none'; // Prevents text selection while dragging
|
||||
iMoveThings.classList.add('dragging'); // Adds a class to indicate a dragging state
|
||||
initialRect = moveMe.getBoundingClientRect();
|
||||
offsetX = clientX - initialRect.left;
|
||||
offsetY = clientY - initialRect.top;
|
||||
|
||||
// Get current position from transform or use element position
|
||||
const computedStyle = window.getComputedStyle(moveMe);
|
||||
const transform = computedStyle.transform;
|
||||
|
||||
if (transform && transform !== 'none') {
|
||||
const matrix = new DOMMatrix(transform);
|
||||
currentX = matrix.m41;
|
||||
currentY = matrix.m42;
|
||||
} else {
|
||||
currentX = initialRect.left;
|
||||
currentY = initialRect.top;
|
||||
}
|
||||
|
||||
targetX = currentX;
|
||||
targetY = currentY;
|
||||
|
||||
document.body.style.userSelect = 'none';
|
||||
iMoveThings.classList.add('dragging');
|
||||
|
||||
// Start animation loop
|
||||
if (animationFrame) {
|
||||
cancelAnimationFrame(animationFrame);
|
||||
}
|
||||
updatePosition();
|
||||
};
|
||||
|
||||
const endDrag = () => {
|
||||
isDragging = false;
|
||||
if (animationFrame) {
|
||||
cancelAnimationFrame(animationFrame);
|
||||
animationFrame = null;
|
||||
}
|
||||
document.body.style.userSelect = '';
|
||||
iMoveThings.classList.remove('dragging');
|
||||
};
|
||||
|
||||
// Mouse down - start dragging
|
||||
iMoveThings.addEventListener('mousedown', function(event) {
|
||||
event.preventDefault();
|
||||
startDrag(event.clientX, event.clientY);
|
||||
});
|
||||
|
||||
// What to do when the touch starts on the element that moves things
|
||||
// Touch start - start dragging
|
||||
iMoveThings.addEventListener('touchstart', function(event) {
|
||||
isDragging = true;
|
||||
const touch = event?.touches?.[0];
|
||||
if (!touch) {return;}
|
||||
offsetX = touch.clientX - moveMe.getBoundingClientRect().left; // Distance between the left edge of the overlay, and the cursor
|
||||
offsetY = touch.clientY - moveMe.getBoundingClientRect().top; // Distance between the top edge of the overlay, and the cursor
|
||||
document.body.style.userSelect = 'none'; // Prevents text selection while dragging
|
||||
iMoveThings.classList.add('dragging'); // Adds a class to indicate a dragging state
|
||||
}, { passive: false }); // Prevents scrolling from being captured
|
||||
startDrag(touch.clientX, touch.clientY);
|
||||
event.preventDefault();
|
||||
}, { passive: false });
|
||||
|
||||
// What to do when the mouse is moved while dragging
|
||||
// Mouse move - update target position
|
||||
document.addEventListener('mousemove', function(event) {
|
||||
if (isDragging) {
|
||||
moveMe.style.left = (event.clientX - offsetX) + 'px'; // Binds the overlay to the left side of the screen, and sets it's position to the cursor
|
||||
moveMe.style.top = (event.clientY - offsetY) + 'px'; // Binds the overlay to the top of the screen, and sets it's position to the cursor
|
||||
moveMe.style.right = ''; // Destroys the right property to unbind the overlay from the right side of the screen
|
||||
if (isDragging && initialRect) {
|
||||
targetX = event.clientX - offsetX;
|
||||
targetY = event.clientY - offsetY;
|
||||
}
|
||||
});
|
||||
}, { passive: true });
|
||||
|
||||
// What to do when the touch moves while dragging
|
||||
// Touch move - update target position
|
||||
document.addEventListener('touchmove', function(event) {
|
||||
if (isDragging) {
|
||||
if (isDragging && initialRect) {
|
||||
const touch = event?.touches?.[0];
|
||||
if (!touch) {return;}
|
||||
moveMe.style.left = (touch.clientX - offsetX) + 'px'; // Binds the overlay to the left side of the screen, and sets it's position to the cursor
|
||||
moveMe.style.top = (touch.clientY - offsetY) + 'px'; // Binds the overlay to the top of the screen, and sets it's position to the cursor
|
||||
moveMe.style.right = ''; // Destroys the right property to unbind the overlay from the right side of the screen
|
||||
event.preventDefault(); // prevent scrolling while dragging
|
||||
targetX = touch.clientX - offsetX;
|
||||
targetY = touch.clientY - offsetY;
|
||||
event.preventDefault();
|
||||
}
|
||||
}, { passive: false }); // Prevents scrolling from being captured
|
||||
}, { passive: false });
|
||||
|
||||
// What to do when the mouse is released
|
||||
document.addEventListener('mouseup', function() {
|
||||
isDragging = false;
|
||||
document.body.style.userSelect = ''; // Restores text selection capability after dragging
|
||||
iMoveThings.classList.remove('dragging'); // Removes the dragging class
|
||||
});
|
||||
|
||||
// What to do when the touch ends
|
||||
document.addEventListener('touchend', function() {
|
||||
isDragging = false;
|
||||
document.body.style.userSelect = ''; // Restores text selection capability after dragging
|
||||
iMoveThings.classList.remove('dragging'); // Removes the dragging class
|
||||
});
|
||||
|
||||
// What to do when the touch is cancelled
|
||||
document.addEventListener('touchcancel', function() {
|
||||
isDragging = false;
|
||||
document.body.style.userSelect = ''; // Restores text selection capability after dragging
|
||||
iMoveThings.classList.remove('dragging'); // Removes the dragging class
|
||||
});
|
||||
// End drag events
|
||||
document.addEventListener('mouseup', endDrag);
|
||||
document.addEventListener('touchend', endDrag);
|
||||
document.addEventListener('touchcancel', endDrag);
|
||||
}
|
||||
|
||||
/** Handles status display.
|
||||
|
|
|
|||
34
src/main.js
34
src/main.js
|
|
@ -1,19 +1,5 @@
|
|||
/** The main file. Everything in the userscript is executed from here.
|
||||
* @since 0.0.0
|
||||
*
|
||||
* VERSION HISTORY:
|
||||
* 0.71.0 - Added minimize/maximize functionality and pixel counting system
|
||||
* Features added:
|
||||
* - Interactive minimize/maximize overlay with click-to-toggle functionality
|
||||
* - Fixed overlay dimensions: 60px width × 76px height in minimized state
|
||||
* - Smart element visibility control (hides all UI except icon and drag bar when minimized)
|
||||
* - Icon repositioning system (3px right offset) for better visual alignment in minimized state
|
||||
* - Comprehensive pixel counting system for template statistics
|
||||
* - Real-time pixel count display in template creation and rendering status messages
|
||||
* - Intelligent pixel counting for actively rendered templates with tile-based filtering
|
||||
* - Internationalized number formatting for large pixel counts (e.g., "1,234,567 pixels")
|
||||
* - Automatic state management with proper cleanup when switching between modes
|
||||
* - Enhanced user experience with visual feedback and status updates
|
||||
*/
|
||||
|
||||
import Overlay from './Overlay.js';
|
||||
|
|
@ -247,19 +233,6 @@ function observeBlack() {
|
|||
* Creates a responsive overlay UI that can toggle between full-featured and minimized states.
|
||||
*
|
||||
* Parent/child relationships in the DOM structure below are indicated by indentation.
|
||||
*
|
||||
* OVERLAY STATES:
|
||||
* - MAXIMIZED: Full UI with all controls, inputs, and status information visible
|
||||
* - MINIMIZED: Compact 60×76px interface showing only the Blue Marble icon and drag functionality
|
||||
*
|
||||
* FEATURES:
|
||||
* - Click-to-toggle functionality on the Blue Marble icon
|
||||
* - Automatic element visibility management
|
||||
* - Fixed dimensions for consistent minimized appearance
|
||||
* - Proper cleanup and restoration of all UI elements
|
||||
* - Visual feedback through alt-text updates
|
||||
* - Status message integration
|
||||
*
|
||||
* @since 0.58.3
|
||||
*/
|
||||
function buildOverlayMain() {
|
||||
|
|
@ -285,13 +258,6 @@ function buildOverlayMain() {
|
|||
* - Resets icon positioning to default alignment
|
||||
* - Shows success message when returning to maximized state
|
||||
*
|
||||
* IMPLEMENTATION DETAILS:
|
||||
* - Uses CSS display property manipulation for element visibility
|
||||
* - Maintains drag functionality in both states
|
||||
* - Updates accessibility text (alt attribute) based on current state
|
||||
* - Provides user feedback through status messages
|
||||
* - Ensures proper cleanup of all style overrides when switching states
|
||||
*
|
||||
* @param {Event} event - The click event object (implicit)
|
||||
*/
|
||||
img.addEventListener('click', () => {
|
||||
|
|
|
|||
|
|
@ -11,12 +11,18 @@
|
|||
transition: all 0.3s ease;
|
||||
max-width: 300px;
|
||||
width: auto;
|
||||
/* Performance optimizations for smooth dragging */
|
||||
will-change: transform;
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
transform-style: preserve-3d;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
/* Smooth transitions for minimize/maximize functionality */
|
||||
#bm-contain-userinfo,
|
||||
#bm-overlay hr,
|
||||
#bm-contain-automation,
|
||||
#bm-contain-automation,
|
||||
#bm-contain-buttons-action {
|
||||
transition: opacity 0.2s ease, height 0.2s ease;
|
||||
}
|
||||
|
|
@ -49,6 +55,20 @@ div#bm-overlay {
|
|||
cursor: grabbing;
|
||||
}
|
||||
|
||||
/* Disable interactions during drag for better performance */
|
||||
#bm-overlay:has(#bm-bar-drag.dragging) {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
/* Keep drag bar interactive when dragging */
|
||||
#bm-bar-drag.dragging {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* The container for the overlay header */
|
||||
#bm-contain-header {
|
||||
margin-bottom: 0.5em;
|
||||
|
|
@ -188,6 +208,21 @@ div:has(> #bm-input-file-template) > button {
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Force complete invisibility of file input to prevent native browser text */
|
||||
#bm-input-file-template,
|
||||
input[type="file"][id*="template"] {
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
position: absolute !important;
|
||||
left: -9999px !important;
|
||||
top: -9999px !important;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
opacity: 0 !important;
|
||||
z-index: -9999 !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
/* Output status area */
|
||||
#bm-output-status {
|
||||
font-size: small;
|
||||
|
|
|
|||
Loading…
Reference in a new issue