fixes and optimizations

This commit is contained in:
uwaa 2025-01-10 10:52:08 +00:00
parent 350e88221f
commit b79a921932

377
rot.js
View file

@ -2,220 +2,194 @@
// one rotten apple spoils the bunch // one rotten apple spoils the bunch
(() => { (() => {
let oldPushState = history.pushState; function getPromiseFromEvent(item, event) {
history.pushState = function pushState() { return new Promise((resolve) => {
let ret = oldPushState.apply(this, arguments); const listener = () => {
window.dispatchEvent(new Event('pushstate')); item.removeEventListener(event, listener);
window.dispatchEvent(new Event('locationchange')); resolve();
return ret; }
}; item.addEventListener(event, listener);
let oldReplaceState = history.replaceState;
history.replaceState = function replaceState() {
let ret = oldReplaceState.apply(this, arguments);
window.dispatchEvent(new Event('replacestate'));
window.dispatchEvent(new Event('locationchange'));
return ret;
};
window.addEventListener('popstate', () => {
window.dispatchEvent(new Event('locationchange'));
});
})();
function getPromiseFromEvent(item, event) {
return new Promise((resolve) => {
const listener = () => {
item.removeEventListener(event, listener);
resolve();
}
item.addEventListener(event, listener);
});
}
// MIT Licensed
// Author: jwilson8767
function waitUntil(selector) {
return new Promise((resolve, reject) => {
const el = document.querySelector(selector);
if (el) resolve(el);
new MutationObserver((mutationRecords, observer) => {
// Query for elements matching the specified selector
Array.from(document.querySelectorAll(selector)).forEach((element) => {
resolve(element);
//Once we have resolved we don't need the observer anymore.
observer.disconnect();
});
}).observe(document.documentElement, {
childList: true,
subtree: true
}); });
}); }
}
// MIT Licensed
// Author: jwilson8767
function waitUntil(selector) {
return new Promise((resolve, reject) => {
const el = document.querySelector(selector);
if (el) resolve(el);
new MutationObserver((mutationRecords, observer) => {
// Query for elements matching the specified selector
Array.from(document.querySelectorAll(selector)).forEach((element) => {
resolve(element);
//Once we have resolved we don't need the observer anymore.
observer.disconnect();
});
}).observe(document.documentElement, {
childList: true,
subtree: true
});
});
}
function sex(sex) { function sex(sex) {
return sex // Sex return sex // Sex
} }
function rand(list) { function rand(list) {
return list ? list[list.length * Math.random() | 0] : null; return list ? list[list.length * Math.random() | 0] : null;
} }
// Rot music player // Rot music player
const audio = document.createElement("audio"); const audio = document.createElement("audio");
audio.loop = true; audio.loop = true;
audio.id = "user-music"; audio.id = "user-music";
audio.style = "display:none;"; audio.style = "display:none;";
localStorage.audiovolume = (audio.volume = localStorage.audiovolume ? localStorage.audiovolume / 100 : 0.5) * 100; localStorage.audiovolume = (audio.volume = localStorage.audiovolume ? localStorage.audiovolume / 100 : 0.5) * 100;
function setMusic(url) { function setMusic(url) {
if (audio.src == url || (!url && audio.src === "")) if (audio.src == url || (!url && audio.src === window.location.toString()))
return; return;
if (!audio.paused || audio.src != "") {
console.log("Stopping music");
audio.pause(); audio.pause();
// This line will cause a lot of errors. // This line will cause a lot of errors.
// Setting src to "" will cause any pending .play()s to fail. // Setting src to "" will cause any pending .play()s to fail.
audio.src = ""; audio.src = "";
if (url) {
console.log("Setting music: " + url);
audio.src = url;
playMusic();
}
} }
if (url) { function playMusic() {
console.log("Setting music: " + url); //Starts playing the music if it isn't muted and isn't already playing
audio.src = url; if (audio.src && audio.src != "" && audio.paused && !audio.muted)
playMusic(); audio.play().catch(() => getPromiseFromEvent(window, 'click').then(audio.play));
} }
}
function playMusic() { function setImage(url) {
//Starts playing the music if it isn't muted and isn't already playing if (url) {
if (audio.src && audio.src != "" && audio.paused && !audio.muted) console.log("Setting background: " + url);
audio.play().catch(() => getPromiseFromEvent(window, 'click').then(audio.play)); document.getElementById("app-loaded").style.setProperty("--body-background-image", "url(" + url + ")");
} }
}
function setImage(url) { //Audio control events
if (!url) function volumeSet(number) {
url = '/static/background.jpg'; localStorage.audiovolume = Math.round((audio.volume = number) * 100);
updateVolumeLabel();
}
function volumeAdd(number) {
volumeSet(Math.min(1, Math.max(0, audio.volume + number)));
}
function updateVolumeLabel() {
document.getElementById("user-audio-percentage").innerHTML = Math.round(audio.volume * 100) + "%";
}
console.log("Setting background: " + url); //Initialize audio controls
document.getElementById("app-loaded").style.setProperty("--body-background-image", "url(" + url + ")"); waitUntil("#music-controls").then((controls) => {
} updateVolumeLabel();
controls.querySelector("#music-up").onclick = () => volumeAdd(0.05);
//Audio control events controls.querySelector("#music-down").onclick = () => volumeAdd(-0.05);
function volumeSet(number) {
localStorage.audiovolume = Math.round((audio.volume = number) * 100);
updateVolumeLabel();
}
function volumeAdd(number) {
volumeSet(Math.min(1, Math.max(0, audio.volume + number)));
}
function updateVolumeLabel() {
document.getElementById("user-audio-percentage").innerHTML = Math.round(audio.volume * 100) + "%";
}
//Initialize audio controls
waitUntil("#music-controls").then((controls) => {
updateVolumeLabel();
controls.querySelector("#music-up").onclick = () => volumeAdd(0.05);
controls.querySelector("#music-down").onclick = () => volumeAdd(-0.05);
})
waitUntil("#music-slider").then((slider) => {
updateVolumeLabel();
slider.oninput = () => volumeSet(slider.value / 100);
})
waitUntil("#music-mute").then((box) => {
audio.muted = box.checked = localStorage.audiomuted === "true";
box.addEventListener('click', () => {
localStorage.audiomuted = audio.muted = box.checked;
playMusic();
}) })
});
//Theme application waitUntil("#music-slider").then((slider) => {
function applyMainTheme() { updateVolumeLabel();
console.log("Applying main theme"); slider.oninput = () => volumeSet(slider.value / 100);
setTimeout(() => { })
let pageMusic = document.querySelector('meta[name="pageMusic"]')?.content || document.getElementById("pageMusic")?.getAttribute("href");
setMusic(pageMusic);
playMusic();
let pageImage = document.querySelector('meta[name="pageImage"]')?.content || document.getElementById("pageImage")?.getAttribute("href"); waitUntil("#music-mute").then((box) => {
setImage(pageImage); audio.muted = box.checked = localStorage.audiomuted === "true";
}, 1000); box.addEventListener('click', () => {
} localStorage.audiomuted = audio.muted = box.checked;
playMusic();
})
});
function applyUserTheme() { //Theme application
console.log("Applying user theme"); function applyMainTheme() {
setMusic(null); console.log("Applying main theme");
setTimeout(() => { setTimeout(() => {
let ptp = findProfileThemingPost(); let pageMusic = document.querySelector('meta[name="pageMusic"]')?.content || document.getElementById("pageMusic")?.getAttribute("href");
if (ptp) { setMusic(pageMusic);
//Configured by post playMusic();
let musicContainer = ptp.querySelector(".audio-container")
if (musicContainer)
setMusic(rand(musicContainer.children).src);
else
setMusic(null);
let imageContainer = ptp.querySelector(".image-container") let pageImage = document.querySelector('meta[name="pageImage"]')?.content || document.getElementById("pageImage")?.getAttribute("href");
if (imageContainer) setImage(pageImage);
setImage(rand(imageContainer.getElementsByTagName("img")).src); }, 1000);
else
setImage(null);
return;
}
let fields = [...document.getElementsByClassName("user-profile-field-name")]
if (fields.length != 0) {
//Configured by fields
let musicFields = fields.filter((x) => x.title.toLowerCase().replace(/\s+/g, '') == "music")
if (musicFields.length > 0)
setMusic(rand(musicFields).nextElementSibling.title);
else
setMusic(null);
let imageFields = fields.filter((x) => x.title.toLowerCase().replace(/\s+/g, '') == "image")
if (imageFields.length > 0)
setImage(rand(imageFields).nextElementSibling.title);
else
setImage(null);
return;
}
}, 1000);
}
function findProfileThemingPost() {
try {
let pinnedPosts = document.getElementsByClassName("pin");
if (pinnedPosts.length == 0)
return null;
let ptp = [...pinnedPosts].find( // I hate this. It keeps getting worse.
(x) => x.nextElementSibling
.querySelector(".StatusBody")
.querySelector(".text")
.innerHTML
.replace(/(<([^>]+)>)/ig, '')
.search(/profile theming post/ig) != -1
)
if (!ptp)
return null;
return ptp.nextElementSibling.querySelector(".StatusBody");
} catch (e) {
//Future-proofing
console.error(e);
return null;
} }
}
//Switch-based monkey patching router bullshit function applyUserTheme() {
{ console.log("Applying user theme");
let lastPath = window.location.pathname; setMusic(null);
addEventListener('locationchange', (event) => { setTimeout(() => {
let ptp = findProfileThemingPost();
if (ptp) {
//Configured by post
let musicContainer = ptp.querySelector(".audio-container")
if (musicContainer)
setMusic(rand(musicContainer.children).src);
else
setMusic(null);
let imageContainer = ptp.querySelector(".image-container")
if (imageContainer)
setImage(rand(imageContainer.getElementsByTagName("img")).src);
else
setImage(null);
return;
}
let fields = [...document.getElementsByClassName("user-profile-field-name")]
if (fields.length != 0) {
//Configured by fields
let musicFields = fields.filter((x) => x.title.toLowerCase().replace(/\s+/g, '') == "music")
if (musicFields.length > 0)
setMusic(rand(musicFields).nextElementSibling.title);
else
setMusic(null);
let imageFields = fields.filter((x) => x.title.toLowerCase().replace(/\s+/g, '') == "image")
if (imageFields.length > 0)
setImage(rand(imageFields).nextElementSibling.title);
else
setImage(null);
return;
}
}, 1000);
}
function findProfileThemingPost() {
try {
let pinnedPosts = document.getElementsByClassName("pin");
if (pinnedPosts.length == 0)
return null;
let ptp = [...pinnedPosts].find( // I hate this. It keeps getting worse.
(x) => x.nextElementSibling
.querySelector(".StatusBody")
.querySelector(".text")
.innerHTML
.replace(/(<([^>]+)>)/ig, '')
.search(/profile theming post/ig) != -1
)
if (!ptp)
return null;
return ptp.nextElementSibling.querySelector(".StatusBody");
} catch (e) {
//Future-proofing
console.error(e);
return null;
}
}
//Switch-based monkey patching router bullshit
let lastPath = null;
function updateRot() {
let newPath = window.location.pathname; let newPath = window.location.pathname;
if (lastPath == newPath) if (lastPath == newPath)
return; return;
@ -266,7 +240,28 @@ function findProfileThemingPost() {
applyMainTheme(); applyMainTheme();
break; break;
} }
}
//Monkey patches
addEventListener('locationchange', updateRot);
const oldPushState = history.pushState;
history.pushState = function pushState() {
const ret = oldPushState.apply(this, arguments);
updateRot();
return ret;
};
const oldReplaceState = history.replaceState;
history.replaceState = function replaceState() {
const ret = oldReplaceState.apply(this, arguments);
updateRot();
return ret;
};
window.addEventListener('popstate', () => {
updateRot();
}); });
} })();
console.log("rot.js loaded"); console.log("rot.js loaded");