mirror of
https://github.com/SwingTheVine/Wplace-BlueMarble.git
synced 2026-05-06 11:39:27 +00:00
344 lines
32 KiB
HTML
344 lines
32 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>main.js - Documentation</title>
|
|
|
|
<script src="scripts/prettify/prettify.js"></script>
|
|
<script src="scripts/prettify/lang-css.js"></script>
|
|
<!--[if lt IE 9]>
|
|
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
<![endif]-->
|
|
<link type="text/css" rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
|
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
|
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
|
</head>
|
|
<body>
|
|
|
|
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
|
<label for="nav-trigger" class="navicon-button x">
|
|
<div class="navicon"></div>
|
|
</label>
|
|
|
|
<label for="nav-trigger" class="overlay"></label>
|
|
|
|
<nav>
|
|
<li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="ApiManager.html">ApiManager</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="ConfettiManager.html">ConfettiManager</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Observers.html">Observers</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Overlay.html">Overlay</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="SettingsManager.html">SettingsManager</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Template.html">Template</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="TemplateManager.html">TemplateManager</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowCredits.html">WindowCredits</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowFilter.html">WindowFilter</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowMain.html">WindowMain</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowSettings.html">WindowSettings</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowTelemetry.html">WindowTelemetry</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowWizard.html">WindowWizard</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="module.exports_module.exports.html">exports</a></span></li><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addBr">addBr</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addButton">addButton</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addButtonHelp">addButtonHelp</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addCaption">addCaption</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addCheckbox">addCheckbox</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addDetails">addDetails</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addDiv">addDiv</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addDragbar">addDragbar</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addFieldset">addFieldset</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addForm">addForm</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addHeader">addHeader</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addHr">addHr</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addImg">addImg</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addInput">addInput</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addInputFile">addInputFile</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addLegend">addLegend</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addLi">addLi</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addMenu">addMenu</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addOl">addOl</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addOption">addOption</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addP">addP</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addSelect">addSelect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addSmall">addSmall</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addSpan">addSpan</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addSummary">addSummary</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTable">addTable</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTbody">addTbody</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTd">addTd</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTextarea">addTextarea</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTfoot">addTfoot</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTh">addTh</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addThead">addThead</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTimer">addTimer</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTr">addTr</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addUl">addUl</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#base64ToUint8">base64ToUint8</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildElement">buildElement</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildHighlight">buildHighlight</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildOverlay">buildOverlay</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildTemplate">buildTemplate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildWindow">buildWindow</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildWindowed">buildWindowed</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#calculateCanvasTransparency">calculateCanvasTransparency</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#calculateCoordsFromChunked">calculateCoordsFromChunked</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#calculateRelativeLuminance">calculateRelativeLuminance</a></span></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#colorpalette">colorpalette</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#colorpaletteForBlueMarble">colorpaletteForBlueMarble</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#consoleError">consoleError</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#consoleLog">consoleLog</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#consoleWarn">consoleWarn</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#convertTemplateToBlob">convertTemplateToBlob</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#createConfetti">createConfetti</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#createJSON">createJSON</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#createObserverBody">createObserverBody</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#createTemplate">createTemplate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#createTemplateTiles">createTemplateTiles</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#deleteTemplate">deleteTemplate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#disableTemplate">disableTemplate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#downloadAllTemplates">downloadAllTemplates</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#downloadAllTemplatesFromStorage">downloadAllTemplatesFromStorage</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#downloadTemplate">downloadTemplate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#encodedToNumber">encodedToNumber</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#escapeHTML">escapeHTML</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#getClipboardData">getClipboardData</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#getObserverBody">getObserverBody</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#getWplaceVersion">getWplaceVersion</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#handleDisplayError">handleDisplayError</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#handleDrag">handleDrag</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#handleMinimization">handleMinimization</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#hexToRGB">hexToRGB</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#importJSON">importJSON</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#inject">inject</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#localizeDate">localizeDate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#localizeDuration">localizeDuration</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#localizeNumber">localizeNumber</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#localizePercent">localizePercent</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#numberToEncoded">numberToEncoded</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#observe">observe</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#observeBlack">observeBlack</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#rgbToHex">rgbToHex</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#selectAllCoordinateInputs">selectAllCoordinateInputs</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#setApiManager">setApiManager</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#setSettingsManager">setSettingsManager</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#setWindowMain">setWindowMain</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#sleep">sleep</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#toggleFlag">toggleFlag</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#uint8ToBase64">uint8ToBase64</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#updateColorList">updateColorList</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#updateInnerHTML">updateInnerHTML</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#updateUserStorage">updateUserStorage</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#viewCanvasInNewTab">viewCanvasInNewTab</a></span></li>
|
|
</nav>
|
|
|
|
<div id="main">
|
|
|
|
<h1 class="page-title">main.js</h1>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<section>
|
|
<article>
|
|
<pre class="prettyprint source linenums"><code>/** @file The main file. Everything in the userscript is executed from here.
|
|
* @since 0.0.0
|
|
*/
|
|
|
|
import Observers from './observers.js';
|
|
import ApiManager from './apiManager.js';
|
|
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
|
|
const consoleStyle = 'color: cornflowerblue;'; // The styling for the console logs
|
|
|
|
/** Injects code into the client
|
|
* This code will execute outside of TamperMonkey's sandbox
|
|
* @param {*} callback - The code to execute
|
|
* @since 0.11.15
|
|
*/
|
|
function inject(callback) {
|
|
const script = document.createElement('script');
|
|
script.setAttribute('bm-name', name); // Passes in the name value
|
|
script.setAttribute('bm-cStyle', consoleStyle); // Passes in the console style value
|
|
script.textContent = `(${callback})();`;
|
|
document.documentElement?.appendChild(script);
|
|
script.remove();
|
|
}
|
|
|
|
/** What code to execute instantly in the client (webpage) to spy on fetch calls.
|
|
* This code will execute outside of TamperMonkey's sandbox.
|
|
* @since 0.11.15
|
|
*/
|
|
inject(() => {
|
|
|
|
const script = document.currentScript; // Gets the current script HTML Script Element
|
|
const name = script?.getAttribute('bm-name') || 'Blue Marble'; // Gets the name value that was passed in. Defaults to "Blue Marble" if nothing was found
|
|
const consoleStyle = script?.getAttribute('bm-cStyle') || ''; // Gets the console style value that was passed in. Defaults to no styling if nothing was found
|
|
const fetchedBlobQueue = new Map(); // Blobs being processed
|
|
|
|
window.addEventListener('message', (event) => {
|
|
const { source, endpoint, blobID, blobData, blink } = event.data;
|
|
|
|
const elapsed = Date.now() - blink;
|
|
|
|
// Since this code does not run in the userscript, we can't use consoleLog().
|
|
console.groupCollapsed(`%c${name}%c: ${fetchedBlobQueue.size} Recieved IMAGE message about blob "${blobID}"`, consoleStyle, '');
|
|
console.log(`Blob fetch took %c${String(Math.floor(elapsed/60000)).padStart(2,'0')}:${String(Math.floor(elapsed/1000) % 60).padStart(2,'0')}.${String(elapsed % 1000).padStart(3,'0')}%c MM:SS.mmm`, consoleStyle, '');
|
|
console.log(fetchedBlobQueue);
|
|
console.groupEnd();
|
|
|
|
// The modified blob won't have an endpoint, so we ignore any message without one.
|
|
if ((source == 'blue-marble') && !!blobID && !!blobData && !endpoint) {
|
|
|
|
const callback = fetchedBlobQueue.get(blobID); // Retrieves the blob based on the UUID
|
|
|
|
// If the blobID is a valid function...
|
|
if (typeof callback === 'function') {
|
|
|
|
callback(blobData); // ...Retrieve the blob data from the blobID function
|
|
} else {
|
|
// ...else the blobID is unexpected. We don't know what it is, but we know for sure it is not a blob. This means we ignore it.
|
|
|
|
consoleWarn(`%c${name}%c: Attempted to retrieve a blob (%s) from queue, but the blobID was not a function! Skipping...`, consoleStyle, '', blobID);
|
|
}
|
|
|
|
fetchedBlobQueue.delete(blobID); // Delete the blob from the queue, because we don't need to process it again
|
|
}
|
|
});
|
|
|
|
// Spys on "spontaneous" fetch requests made by the client
|
|
const originalFetch = window.fetch; // Saves a copy of the original fetch
|
|
|
|
// Overrides fetch
|
|
window.fetch = async function(...args) {
|
|
|
|
const response = await originalFetch.apply(this, args); // Sends a fetch
|
|
const cloned = response.clone(); // Makes a copy of the response
|
|
|
|
// Retrieves the endpoint name. Unknown endpoint = "ignore"
|
|
const endpointName = ((args[0] instanceof Request) ? args[0]?.url : args[0]) || 'ignore';
|
|
|
|
// Check Content-Type to only process JSON
|
|
const contentType = cloned.headers.get('content-type') || '';
|
|
if (contentType.includes('application/json')) {
|
|
|
|
|
|
// Since this code does not run in the userscript, we can't use consoleLog().
|
|
console.log(`%c${name}%c: Sending JSON message about endpoint "${endpointName}"`, consoleStyle, '');
|
|
|
|
// Sends a message about the endpoint it spied on
|
|
cloned.json()
|
|
.then(jsonData => {
|
|
window.postMessage({
|
|
source: 'blue-marble',
|
|
endpoint: endpointName,
|
|
jsonData: jsonData
|
|
}, '*');
|
|
})
|
|
.catch(err => {
|
|
console.error(`%c${name}%c: Failed to parse JSON: `, consoleStyle, '', err);
|
|
});
|
|
} else if (contentType.includes('image/') && (!endpointName.includes('openfreemap') && !endpointName.includes('maps'))) {
|
|
// Fetch custom for all images but opensourcemap
|
|
|
|
const blink = Date.now(); // Current time
|
|
|
|
const blob = await cloned.blob(); // The original blob
|
|
|
|
// Since this code does not run in the userscript, we can't use consoleLog().
|
|
console.log(`%c${name}%c: ${fetchedBlobQueue.size} Sending IMAGE message about endpoint "${endpointName}"`, consoleStyle, '');
|
|
|
|
// Returns the manipulated blob
|
|
return new Promise((resolve) => {
|
|
const blobUUID = crypto.randomUUID(); // Generates a random UUID
|
|
|
|
// Store the blob while we wait for processing
|
|
fetchedBlobQueue.set(blobUUID, (blobProcessed) => {
|
|
// The response that triggers when the blob is finished processing
|
|
|
|
// Creates a new response
|
|
resolve(new Response(blobProcessed, {
|
|
headers: cloned.headers,
|
|
status: cloned.status,
|
|
statusText: cloned.statusText
|
|
}));
|
|
|
|
// Since this code does not run in the userscript, we can't use consoleLog().
|
|
console.log(`%c${name}%c: ${fetchedBlobQueue.size} Processed blob "${blobUUID}"`, consoleStyle, '');
|
|
});
|
|
|
|
window.postMessage({
|
|
source: 'blue-marble',
|
|
endpoint: endpointName,
|
|
blobID: blobUUID,
|
|
blobData: blob,
|
|
blink: blink
|
|
});
|
|
}).catch(exception => {
|
|
const elapsed = Date.now();
|
|
console.error(`%c${name}%c: Failed to Promise blob!`, consoleStyle, '');
|
|
console.groupCollapsed(`%c${name}%c: Details of failed blob Promise:`, consoleStyle, '');
|
|
console.log(`Endpoint: ${endpointName}\nThere are ${fetchedBlobQueue.size} blobs processing...\nBlink: ${blink.toLocaleString()}\nTime Since Blink: ${String(Math.floor(elapsed/60000)).padStart(2,'0')}:${String(Math.floor(elapsed/1000) % 60).padStart(2,'0')}.${String(elapsed % 1000).padStart(3,'0')} MM:SS.mmm`);
|
|
console.error(`Exception stack:`, exception);
|
|
console.groupEnd();
|
|
});
|
|
|
|
// cloned.blob().then(blob => {
|
|
// window.postMessage({
|
|
// source: 'blue-marble',
|
|
// endpoint: endpointName,
|
|
// blobData: blob
|
|
// }, '*');
|
|
// });
|
|
}
|
|
|
|
return response; // Returns the original response
|
|
};
|
|
});
|
|
|
|
// Imports the CSS file from dist folder on github
|
|
const cssOverlay = GM_getResourceText("CSS-BM-File");
|
|
GM_addStyle(cssOverlay);
|
|
|
|
// Injection point for the Roboto Mono font file (only if this is the Standalone version)
|
|
const robotoMonoInjectionPoint = 'robotoMonoInjectionPoint';
|
|
|
|
// If the Roboto Mono injection point contains '@font-face'...
|
|
if (!!(robotoMonoInjectionPoint.indexOf('@font-face') + 1)) {
|
|
// A very hacky way of doing truthy/falsy logic
|
|
|
|
console.log(`Loading Roboto Mono as a file...`);
|
|
GM_addStyle(robotoMonoInjectionPoint); // Add the Roboto Mono font-faces that were injected.
|
|
} else {
|
|
// Else, no Roboto Mono was found. We need to use a stylesheet.
|
|
|
|
// Imports the Roboto Mono font family as a stylesheet
|
|
var stylesheetLink = document.createElement('link');
|
|
stylesheetLink.href = 'https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap';
|
|
stylesheetLink.rel = 'preload';
|
|
stylesheetLink.as = 'style';
|
|
stylesheetLink.onload = function () {
|
|
this.onload = null;
|
|
this.rel = 'stylesheet';
|
|
};
|
|
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); // 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
|
|
|
|
templateManager.setWindowMain(windowMain);
|
|
templateManager.setSettingsManager(settingsManager); // Sets the settings manager
|
|
|
|
const storageTemplates = JSON.parse(GM_getValue('bmTemplates', '{}'));
|
|
console.log(storageTemplates);
|
|
templateManager.importJSON(storageTemplates); // Loads the templates
|
|
|
|
|
|
console.log(userSettings);
|
|
console.log(Object.keys(userSettings).length);
|
|
|
|
// If the user does not have a UUID yet, make a new one.
|
|
if (Object.keys(userSettings).length == 0) {
|
|
const uuid = crypto.randomUUID(); // Generates a random UUID
|
|
console.log(uuid);
|
|
GM.setValue('bmUserSettings', JSON.stringify({
|
|
'uuid': uuid
|
|
}));
|
|
}
|
|
|
|
setInterval(() => apiManager.sendHeartbeat(version), 1000 * 60 * 30); // Sends a heartbeat every 30 minutes
|
|
|
|
// The current "version" of the data collection agreement
|
|
// Increment by 1 to retrigger the telemetry window
|
|
const currentTelemetryVersion = 1;
|
|
|
|
// The last "version" of the data collection agreement that the user agreed too
|
|
const previousTelemetryVersion = userSettings?.telemetry;
|
|
console.log(`Telemetry is ${!(previousTelemetryVersion == undefined)}`);
|
|
|
|
// If the user has not agreed to the current data collection terms, we need to show the Telemetry window.
|
|
if ((previousTelemetryVersion == undefined) || (previousTelemetryVersion > currentTelemetryVersion)) {
|
|
const windowTelemetry = new WindowTelemetry(name, version, currentTelemetryVersion, userSettings?.uuid);
|
|
windowTelemetry.setApiManager(apiManager);
|
|
windowTelemetry.buildWindow(); // Asks the user if they want to enable telemetry
|
|
}
|
|
|
|
windowMain.buildWindow(); // Builds the main Blue Marble window
|
|
|
|
apiManager.spontaneousResponseListener(windowMain); // Reads spontaneous fetch responces
|
|
|
|
observeBlack(); // Observes the black palette color
|
|
|
|
consoleLog(`%c${name}%c (${version}) userscript has loaded!`, 'color: cornflowerblue;', '');
|
|
|
|
/** Observe the black color, and add the "Move" button.
|
|
* @since 0.66.3
|
|
*/
|
|
function observeBlack() {
|
|
const observer = new MutationObserver((mutations, observer) => {
|
|
|
|
const black = document.querySelector('#color-1'); // Attempt to retrieve the black color element for anchoring
|
|
|
|
if (!black) {return;} // Black color does not exist yet. Kills iteself
|
|
|
|
let move = document.querySelector('#bm-button-move'); // Tries to find the move button
|
|
|
|
// If the move button does not exist, we make a new one
|
|
if (!move) {
|
|
move = document.createElement('button');
|
|
move.id = 'bm-button-move';
|
|
move.textContent = 'Move ↑';
|
|
move.className = 'btn btn-soft';
|
|
move.onclick = function() {
|
|
const roundedBox = this.parentNode.parentNode.parentNode.parentNode; // Obtains the rounded box
|
|
const shouldMoveUp = (this.textContent == 'Move ↑');
|
|
roundedBox.parentNode.className = roundedBox.parentNode.className.replace(shouldMoveUp ? 'bottom' : 'top', shouldMoveUp ? 'top' : 'bottom'); // Moves the rounded box to the top
|
|
roundedBox.style.borderTopLeftRadius = shouldMoveUp ? '0px' : 'var(--radius-box)';
|
|
roundedBox.style.borderTopRightRadius = shouldMoveUp ? '0px' : 'var(--radius-box)';
|
|
roundedBox.style.borderBottomLeftRadius = shouldMoveUp ? 'var(--radius-box)' : '0px';
|
|
roundedBox.style.borderBottomRightRadius = shouldMoveUp ? 'var(--radius-box)' : '0px';
|
|
this.textContent = shouldMoveUp ? 'Move ↓' : 'Move ↑';
|
|
}
|
|
|
|
// Attempts to find the "Paint Pixel" element for anchoring
|
|
const paintPixel = black.parentNode.parentNode.parentNode.parentNode.querySelector('h2');
|
|
|
|
paintPixel.parentNode?.appendChild(move); // Adds the move button
|
|
}
|
|
});
|
|
|
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
}
|
|
</code></pre>
|
|
</article>
|
|
</section>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<br class="clear">
|
|
|
|
<footer>
|
|
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Mar 17 2026 01:31:43 GMT+0000 (Coordinated Universal Time) using the Minami theme.
|
|
</footer>
|
|
|
|
<script>prettyPrint();</script>
|
|
<script src="scripts/linenumber.js"></script>
|
|
</body>
|
|
</html>
|