forked from mirrors/akkoma-fe
better integration of rot, music control redesign
Big big credit goes to leafus for new slider code, html, css rewrite, making it look good, etc :D
This commit is contained in:
parent
911e6f160c
commit
236b597ed5
3 changed files with 237 additions and 42 deletions
|
@ -16,7 +16,8 @@
|
||||||
<link rel="shortcut icon" type=image/png href=/favicon.png>
|
<link rel="shortcut icon" type=image/png href=/favicon.png>
|
||||||
<link rel="apple-touch-icon" type=image/png href=/favicon.png>
|
<link rel="apple-touch-icon" type=image/png href=/favicon.png>
|
||||||
<link rel=stylesheet href=/static/custom.css>
|
<link rel=stylesheet href=/static/custom.css>
|
||||||
<script defer=defer src="/static/js/rot.js"></script>
|
<link rel=stylesheet href="/static/rot/rot.css">
|
||||||
|
<script defer=defer src="/static/rot/rot.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="hidden">
|
<body class="hidden">
|
||||||
<noscript>Please enable JavaScript.</noscript>
|
<noscript>Please enable JavaScript.</noscript>
|
||||||
|
|
100
static/rot/rot.css
Normal file
100
static/rot/rot.css
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
.music-controls-title {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mutebutton {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: var(--panelRadius);
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mutebutton input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mutecheck {
|
||||||
|
display: inline-block;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: var(--btnRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SVG for unmuted state */
|
||||||
|
.mutecheck::before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='%23cdd6f4' d='M2.003 11.716c.037-1.843.056-2.764.668-3.552a3 3 0 0 1 .413-.431c.752-.636 1.746-.636 3.733-.636c.71 0 1.065 0 1.403-.092q.105-.03.209-.067c.33-.121.627-.33 1.22-.746c2.338-1.645 3.508-2.467 4.489-2.11c.188.069.37.168.533.29c.848.635.913 2.115 1.042 5.073c.048 1.096.08 2.034.08 2.555s-.032 1.46-.08 2.555c-.13 2.958-.194 4.438-1.042 5.073a2.1 2.1 0 0 1-.533.29c-.982.357-2.15-.465-4.49-2.11c-.592-.416-.889-.625-1.22-.746a3 3 0 0 0-.208-.067c-.338-.092-.693-.092-1.403-.092c-1.987 0-2.98 0-3.733-.636a3 3 0 0 1-.413-.43c-.612-.79-.63-1.71-.668-3.552a14 14 0 0 1 0-.57'/%3E%3Cpath fill='%23cdd6f4' fill-rule='evenodd' d='M19.49 5.552a.66.66 0 0 1 .97.094l-.529.471l.53-.47l.002.002l.003.004l.007.009l.079.112q.072.107.186.305c.149.264.339.652.526 1.171C21.64 8.291 22 9.851 22 12s-.36 3.71-.736 4.75c-.187.52-.377.907-.526 1.172a5 5 0 0 1-.265.417l-.007.009l-.003.003l-.001.002s-.001.001-.531-.47l.53.471a.66.66 0 0 1-.971.094a.77.77 0 0 1-.09-1.035l.03-.041q.04-.06.125-.207a6 6 0 0 0 .422-.943c.314-.871.644-2.253.644-4.222s-.33-3.35-.644-4.222a6 6 0 0 0-.422-.942a3 3 0 0 0-.157-.253m-1.641 1.833c.333-.197.753-.07.938.286l-.603.357l.603-.357l.001.002l.002.003l.003.007l.01.018l.024.053q.028.063.07.17c.053.145.12.35.185.62c.13.54.252 1.337.252 2.425c0 1.089-.122 1.886-.252 2.426c-.065.27-.132.475-.186.619a3 3 0 0 1-.094.223l-.009.018l-.003.007l-.002.003v.002s-.001.001-.604-.356l.603.357c-.185.355-.605.483-.938.286c-.33-.196-.45-.638-.272-.991l.004-.01l.035-.085c.032-.086.08-.23.13-.438c.1-.416.208-1.09.208-2.06c0-.971-.108-1.645-.208-2.06a4 4 0 0 0-.165-.524l-.004-.01a.76.76 0 0 1 .272-.991' clip-rule='evenodd'/%3E%3C/svg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SVG for muted state */
|
||||||
|
input:checked ~ .mutecheck::before {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='%23f38ba8' fill-rule='evenodd' d='M13.47 8.47a.75.75 0 0 1 1.06 0L17 10.94l2.47-2.47a.75.75 0 1 1 1.06 1.06L18.06 12l2.47 2.47a.75.75 0 0 1-1.06 1.06L17 13.06l-2.47 2.47a.75.75 0 0 1-1.06-1.06L15.94 12l-2.47-2.47a.75.75 0 0 1 0-1.06'/%3E%3Cpath fill='%23f38ba8' d='M3.681 8.164c-.621.788-.64 1.71-.678 3.552a14 14 0 0 0 0 .569c.038 1.842.057 2.763.678 3.551c.113.144.28.315.42.431c.763.636 1.771.636 3.788.636c.72 0 1.081 0 1.425.093q.107.029.211.066c.336.121.637.33 1.238.746c2.374 1.645 3.56 2.467 4.557 2.11a2.1 2.1 0 0 0 .541-.29c.786-.58.91-1.863 1.024-4.331l-1.294 1.294a2.25 2.25 0 1 1-3.182-3.182L13.818 12l-1.409-1.409a2.25 2.25 0 1 1 3.182-3.182l1.294 1.294c-.115-2.468-.238-3.751-1.024-4.331a2.1 2.1 0 0 0-.54-.29c-.997-.357-2.184.465-4.558 2.11c-.601.416-.902.625-1.238.746a3 3 0 0 1-.211.067c-.344.092-.704.092-1.425.092c-2.017 0-3.025 0-3.789.636c-.14.116-.306.287-.419.43'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked ~ .mutecheck {
|
||||||
|
background: color-mix(in srgb, var(--cRed) 5%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-slider {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: 24px;
|
||||||
|
margin: 0 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-track {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 100%;
|
||||||
|
height: 4px;
|
||||||
|
background-color: var(--btn);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-fill {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 20%;
|
||||||
|
background-color: var(--selectedMenuFaintLink);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-thumb {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 20%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
background-color: var(--link);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audioControl {
|
||||||
|
border-radius: var(--panelRadius);
|
||||||
|
padding: 6px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-percentage {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
|
@ -13,29 +13,6 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// MIT Licensed
|
|
||||||
// Author: jwilson8767
|
|
||||||
function waitUntil(selector) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const el = document.querySelector(selector);
|
|
||||||
if (el) {
|
|
||||||
resolve(el);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@ -77,9 +54,18 @@
|
||||||
volumeSet(Math.min(1, Math.max(0, audio.volume + number)));
|
volumeSet(Math.min(1, Math.max(0, audio.volume + number)));
|
||||||
}
|
}
|
||||||
function updateVolumeLabel() {
|
function updateVolumeLabel() {
|
||||||
let txtElm = document.getElementById("user-audio-percentage");
|
const percentage = `${Math.round(audio.volume * 100)}%`;
|
||||||
|
const txtElm = document.querySelector('.volume-percentage');
|
||||||
if (txtElm)
|
if (txtElm)
|
||||||
txtElm.innerHTML = Math.round(audio.volume * 100) + "%";
|
txtElm.innerHTML = percentage;
|
||||||
|
|
||||||
|
const slider = document.querySelector('.volume-slider');
|
||||||
|
if (slider) {
|
||||||
|
const thumb = slider.querySelector('.volume-thumb');
|
||||||
|
const fill = slider.querySelector('.volume-fill');
|
||||||
|
if (thumb) thumb.style.left = percentage;
|
||||||
|
if (fill) fill.style.width = percentage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Registers a mutation observer for an element. Upon triggering and the callback
|
//Registers a mutation observer for an element. Upon triggering and the callback
|
||||||
|
@ -254,22 +240,6 @@
|
||||||
else
|
else
|
||||||
audio.volume = 0.2; //Default volume
|
audio.volume = 0.2; //Default volume
|
||||||
|
|
||||||
//Initialize audio controls and event listeners
|
|
||||||
waitUntil("#music-up").then((btn) => btn.addEventListener('click', () => volumeAdd(0.05)));
|
|
||||||
waitUntil("#music-down").then((btn) => btn.addEventListener('click', () => volumeAdd(-0.05)));
|
|
||||||
|
|
||||||
waitUntil("#music-slider").then((slider) => slider.addEventListener('input', () => 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();
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
waitUntil("#user-audio-percentage").then(updateVolumeLabel);
|
|
||||||
|
|
||||||
//Monkey patches and event listeners
|
//Monkey patches and event listeners
|
||||||
const oldPushState = history.pushState;
|
const oldPushState = history.pushState;
|
||||||
history.pushState = function pushState() {
|
history.pushState = function pushState() {
|
||||||
|
@ -287,6 +257,130 @@
|
||||||
|
|
||||||
addEventListener('locationchange', updateRot);
|
addEventListener('locationchange', updateRot);
|
||||||
addEventListener('popstate', updateRot);
|
addEventListener('popstate', updateRot);
|
||||||
|
|
||||||
|
function createAudioControls() {
|
||||||
|
let NavPanel = document.querySelector('.NavPanel');
|
||||||
|
let sideDrawer = document.querySelector('.side-drawer');
|
||||||
|
if (!NavPanel && !sideDrawer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (document.querySelector('.audioControl'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Initialize audio controls and event listeners
|
||||||
|
console.log("Adding music controls");
|
||||||
|
const panel = document.createElement("div");
|
||||||
|
panel.className = "panel panel-default";
|
||||||
|
|
||||||
|
const panelHeading = document.createElement("div");
|
||||||
|
panelHeading.className = "panel-heading";
|
||||||
|
panel.appendChild(panelHeading);
|
||||||
|
|
||||||
|
const title = document.createElement("div");
|
||||||
|
title.className = "title";
|
||||||
|
title.innerText = "Music Controls";
|
||||||
|
panelHeading.appendChild(title);
|
||||||
|
|
||||||
|
const panelBody = document.createElement("div");
|
||||||
|
panelBody.className = "panel-body";
|
||||||
|
panel.appendChild(panelBody);
|
||||||
|
|
||||||
|
const audioControl = document.createElement("div");
|
||||||
|
audioControl.className = "audioControl";
|
||||||
|
panelBody.appendChild(audioControl);
|
||||||
|
|
||||||
|
const mutebutton = document.createElement("label");
|
||||||
|
mutebutton.className = "mutebutton";
|
||||||
|
audioControl.appendChild(mutebutton);
|
||||||
|
|
||||||
|
const musicmute = document.createElement("input");
|
||||||
|
musicmute.className = "music-mute";
|
||||||
|
musicmute.setAttribute("type", "checkbox");
|
||||||
|
musicmute.checked = true;
|
||||||
|
mutebutton.appendChild(musicmute);
|
||||||
|
|
||||||
|
const mutecheck = document.createElement("span");
|
||||||
|
mutecheck.className = "mutecheck";
|
||||||
|
mutecheck.title = "Mute music";
|
||||||
|
mutebutton.appendChild(mutecheck);
|
||||||
|
|
||||||
|
const volumeSlider = document.createElement("div");
|
||||||
|
volumeSlider.className = "volume-slider";
|
||||||
|
audioControl.appendChild(volumeSlider);
|
||||||
|
|
||||||
|
const volumeTrack = document.createElement("div");
|
||||||
|
volumeTrack.className = "volume-track";
|
||||||
|
volumeSlider.appendChild(volumeTrack);
|
||||||
|
|
||||||
|
const volumeFill = document.createElement("div");
|
||||||
|
volumeFill.className = "volume-fill";
|
||||||
|
volumeTrack.appendChild(volumeFill);
|
||||||
|
|
||||||
|
const volumeThumb = document.createElement("div");
|
||||||
|
volumeThumb.className = "volume-thumb";
|
||||||
|
volumeSlider.appendChild(volumeThumb);
|
||||||
|
|
||||||
|
const volumePercentage = document.createElement("div");
|
||||||
|
volumePercentage.className = "volume-percentage";
|
||||||
|
audioControl.appendChild(volumePercentage);
|
||||||
|
|
||||||
|
if (NavPanel)
|
||||||
|
NavPanel.insertAdjacentElement('afterend', panel);
|
||||||
|
else if (sideDrawer)
|
||||||
|
sideDrawer.insertAdjacentElement('beforeend', audioControl);
|
||||||
|
|
||||||
|
{
|
||||||
|
let isDragging = false;
|
||||||
|
|
||||||
|
function updateVolume(e) {
|
||||||
|
const rect = volumeSlider.getBoundingClientRect();
|
||||||
|
let x = Math.max(0, Math.min(e.clientX - rect.left, rect.width));
|
||||||
|
let percentage = (x / rect.width) * 100;
|
||||||
|
|
||||||
|
// Update actual volume
|
||||||
|
volumeSet(percentage / 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseDown(e) {
|
||||||
|
isDragging = true;
|
||||||
|
updateVolume(e);
|
||||||
|
document.addEventListener('mousemove', onMouseMove);
|
||||||
|
document.addEventListener('mouseup', onMouseUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseMove(e) {
|
||||||
|
if (isDragging) {
|
||||||
|
updateVolume(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseUp() {
|
||||||
|
isDragging = false;
|
||||||
|
document.removeEventListener('mousemove', onMouseMove);
|
||||||
|
document.removeEventListener('mouseup', onMouseUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
volumeSlider.addEventListener('mousedown', onMouseDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
audio.muted = musicmute.checked = localStorage.audiomuted === "true";
|
||||||
|
musicmute.addEventListener('click', () => {
|
||||||
|
localStorage.audiomuted = audio.muted = musicmute.checked;
|
||||||
|
playMusic();
|
||||||
|
})
|
||||||
|
|
||||||
|
updateVolumeLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
createAudioControls();
|
||||||
|
window.addEventListener('resize', createAudioControls);
|
||||||
|
|
||||||
|
new MutationObserver((mutationRecords, observer) => {
|
||||||
|
createAudioControls();
|
||||||
|
}).observe(document.body, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
console.log("rot.js loaded");
|
console.log("rot.js loaded");
|
Loading…
Reference in a new issue