cohost-userscripts/winterify.user.js
2024-04-26 17:34:38 -07:00

91 lines
3 KiB
JavaScript

// ==UserScript==
// @name winterify cohost
// @namespace datagirl.xyz
// @match https://cohost.org/*
// @grant none
// @version 1.6.1
// @author snow flurry
// @description 11/14/2022, 1:16:16 PM
// ==/UserScript==
// Changelog:
// 1.5:
// - Use a MutationObserver instead of Interval (less brute forcing)
// - Removed foreground snow effect
(() => {
// if you want snowfall mode to run by default, set this to true.
const defaultOn = true;
const divId = 'userscript-snowfall';
function makeWinter() {
let activateBtn = document.createElement("button");
activateBtn.innerHTML = "❄️";
activateBtn.id = "userscript-winterify-activate";
activateBtn.style.padding = "0.5em 0.75em";
// only create the snowfall if it doesn't already exist
// (so we don't mess up the DOM more than we already are)
let snowfall = document.getElementById(divId);
if (snowfall == null) {
let snowfall = document.createElement("div");
snowfall.id = divId;
snowfall.style.position = "fixed";
snowfall.style.top = snowfall.style.bottom = snowfall.style.left = snowfall.style.right = "0";
snowfall.style.pointerEvents = "none";
const setBg = (snowfall, isDark) => {
// this darkens the background, but the 20% opacity (hopefully!) doesn't darken it too much.
darkMode = isDark ? "" : "#000";
snowfall.style.background = `url('https://staging.cohostcdn.org/attachment/cc9ae945-a270-4059-8992-70f74128c332/snowfall_anim.gif') ${darkMode}`;
};
snowfall.style.opacity = "0.2";
snowfall.style.zIndex = "-1";
snowfall.style.display = defaultOn ? "block" : "none";
setBg(snowfall);
// try to respond to light and dark modes
if (window.matchMedia) {
const darkMatch = window.matchMedia('(prefers-color-scheme: dark)');
setBg(snowfall, darkMatch.matches);
darkMatch.addEventListener('change', (ev) => {
setBg(snowfall, ev.matches);
});
// and append it to the body
document.body.append(snowfall);
} else {
// assume dark, I guess?
setBg(snowfall, true);
}
activateBtn.addEventListener("click", function(ev) {
let snowfall = document.getElementById(divId);
ev.target.innerHTML = "❄️";
snowfall.style.display = (snowfall.style.display == "none") ? "block" : "none";
});
let nav = document.querySelector("nav");
if (nav != null) {
nav.prepend(activateBtn);
}
}
}
// TODO: this feels like a bad idea, but I wasn't able to find a better way
// to handle this by messing with __reactContainer$[bytes]. If you know of a
// better way, send an ask on cohost (@flurry) pls!
const app = document.getElementById("app");
const observer = new MutationObserver(() => {
if (document.getElementById(divId) == null) {
makeWinter();
}
});
observer.observe(app, { subtree: true, childList: true });
})();