mirror of
https://github.com/deadcxap/bs-overlay.git
synced 2026-07-02 05:43:39 +03:00
Add files via upload
more fixes, change settings btn to F2
This commit is contained in:
+216
-57
@@ -35,7 +35,7 @@
|
|||||||
#app-container {
|
#app-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
display: flex;
|
display: flex; /* Скрывается/показывается через JS */
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
@@ -72,17 +72,47 @@
|
|||||||
|
|
||||||
#header-row {
|
#header-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === КОНТЕЙНЕРЫ ДЛЯ ИЗОБРАЖЕНИЙ === */
|
||||||
|
#cover-wrapper, #bl-avatar-wrapper {
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cover-wrapper { width: 90px; height: 90px; }
|
||||||
|
#bl-avatar-wrapper { width: 75px; height: 75px; display: none; }
|
||||||
|
|
||||||
#cover {
|
#cover {
|
||||||
width: 90px;
|
width: 100%; height: 100%;
|
||||||
height: 90px;
|
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 1px solid rgba(255,255,255,0.2);
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bl-avatar {
|
||||||
|
width: 100%; height: 100%;
|
||||||
|
border-radius: 12px;
|
||||||
|
object-fit: cover;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-glow-wrapper::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cover-wrapper::after { border-radius: 10px; border: 1px solid rgba(255,255,255,0.2); }
|
||||||
|
#bl-avatar-wrapper::after { border-radius: 12px; border: 2px solid rgba(255,255,255,0.2); }
|
||||||
|
|
||||||
|
.avatar-glow-wrapper.active-glow::after {
|
||||||
box-shadow: 0 0 10px var(--neon-cyan);
|
box-shadow: 0 0 10px var(--neon-cyan);
|
||||||
|
border-color: var(--neon-cyan);
|
||||||
animation: rainbow 10s linear infinite;
|
animation: rainbow 10s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,11 +164,12 @@
|
|||||||
text-shadow: 1px 1px 2px #000;
|
text-shadow: 1px 1px 2px #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === ШИРОКИЙ PROGRESS BAR === */
|
||||||
#stats-row {
|
#stats-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
border-top: 1px dashed rgba(255,255,255,0.1);
|
border-top: 1px dashed rgba(255,255,255,0.1);
|
||||||
margin-top: 5px;
|
margin-top: 2px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,6 +214,7 @@
|
|||||||
border: 1px solid rgba(255, 0, 255, 0.4);
|
border: 1px solid rgba(255, 0, 255, 0.4);
|
||||||
box-shadow: 0 0 10px rgba(255, 0, 255, 0.2);
|
box-shadow: 0 0 10px rgba(255, 0, 255, 0.2);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#hp-bar-fill {
|
#hp-bar-fill {
|
||||||
@@ -249,17 +281,6 @@
|
|||||||
gap: 15px;
|
gap: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#bl-avatar {
|
|
||||||
width: 75px;
|
|
||||||
height: 75px;
|
|
||||||
border-radius: 12px;
|
|
||||||
border: 2px solid rgba(255,255,255,0.2);
|
|
||||||
box-shadow: 0 0 10px var(--neon-cyan);
|
|
||||||
object-fit: cover;
|
|
||||||
display: none;
|
|
||||||
animation: rainbow 10s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bl-info {
|
#bl-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -286,6 +307,7 @@
|
|||||||
text-shadow: 0 0 5px rgba(0,255,255,0.5);
|
text-shadow: 0 0 5px rgba(0,255,255,0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === МЕНЮ НАСТРОЕК === */
|
||||||
#settings-modal {
|
#settings-modal {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 50%; left: 50%;
|
top: 50%; left: 50%;
|
||||||
@@ -299,14 +321,14 @@
|
|||||||
display: none;
|
display: none;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
width: 320px;
|
width: 360px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.2s, transform 0.2s;
|
transition: opacity 0.2s, transform 0.2s;
|
||||||
}
|
}
|
||||||
#settings-modal.show { display: flex; opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
#settings-modal.show { display: flex; opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
||||||
#settings-modal h2 { margin: 0; color: var(--neon-cyan); text-align: center; font-size: 18px; }
|
#settings-modal h2 { margin: 0; color: var(--neon-cyan); text-align: center; font-size: 18px; }
|
||||||
.setting-row { display: flex; flex-direction: column; gap: 5px; }
|
.setting-row { display: flex; flex-direction: column; gap: 5px; }
|
||||||
.setting-row.checkbox-row { flex-direction: row; align-items: center; gap: 10px; cursor: pointer; }
|
|
||||||
.setting-row input[type="text"], .setting-row input[type="number"] {
|
.setting-row input[type="text"], .setting-row input[type="number"] {
|
||||||
background: rgba(0,0,0,0.5); color: #fff; border: 1px solid #444;
|
background: rgba(0,0,0,0.5); color: #fff; border: 1px solid #444;
|
||||||
padding: 8px; font-family: 'Orbitron', sans-serif; border-radius: 4px; outline: none;
|
padding: 8px; font-family: 'Orbitron', sans-serif; border-radius: 4px; outline: none;
|
||||||
@@ -333,6 +355,26 @@
|
|||||||
.radio-label:hover { border-color: var(--neon-cyan); }
|
.radio-label:hover { border-color: var(--neon-cyan); }
|
||||||
.radio-label input { margin: 0; cursor: pointer; accent-color: var(--neon-cyan); }
|
.radio-label input { margin: 0; cursor: pointer; accent-color: var(--neon-cyan); }
|
||||||
|
|
||||||
|
.modules-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.checkbox-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 11px;
|
||||||
|
background: rgba(0,0,0,0.4);
|
||||||
|
padding: 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #333;
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
.checkbox-row:hover { border-color: var(--neon-cyan); }
|
||||||
|
.checkbox-row input { margin: 0; cursor: pointer; accent-color: var(--neon-cyan); }
|
||||||
|
|
||||||
.setting-row button {
|
.setting-row button {
|
||||||
background: transparent; color: var(--neon-cyan); border: 1px solid var(--neon-cyan); padding: 10px;
|
background: transparent; color: var(--neon-cyan); border: 1px solid var(--neon-cyan); padding: 10px;
|
||||||
font-weight: bold; cursor: pointer; border-radius: 4px; margin-top: 5px;
|
font-weight: bold; cursor: pointer; border-radius: 4px; margin-top: 5px;
|
||||||
@@ -352,7 +394,9 @@
|
|||||||
<div id="app-container">
|
<div id="app-container">
|
||||||
<div id="menu-overlay" class="view-mode glass-panel">
|
<div id="menu-overlay" class="view-mode glass-panel">
|
||||||
<div id="bl-wrapper">
|
<div id="bl-wrapper">
|
||||||
|
<div id="bl-avatar-wrapper" class="avatar-glow-wrapper active-glow">
|
||||||
<img id="bl-avatar" src="" alt="Avatar">
|
<img id="bl-avatar" src="" alt="Avatar">
|
||||||
|
</div>
|
||||||
<div id="bl-info">
|
<div id="bl-info">
|
||||||
<div id="bl-name">Loading...</div>
|
<div id="bl-name">Loading...</div>
|
||||||
<div class="bl-stat-compact">Global: <span id="bl-global">#--</span></div>
|
<div class="bl-stat-compact">Global: <span id="bl-global">#--</span></div>
|
||||||
@@ -363,9 +407,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="playing-overlay" class="view-mode">
|
<div id="playing-overlay" class="view-mode">
|
||||||
<div class="glass-panel">
|
<div class="glass-panel" id="top-glass-panel">
|
||||||
<div id="header-row">
|
<div id="header-row">
|
||||||
|
<div id="cover-wrapper" class="avatar-glow-wrapper active-glow">
|
||||||
<img id="cover" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==" alt="Cover">
|
<img id="cover" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==" alt="Cover">
|
||||||
|
</div>
|
||||||
<div id="text-block">
|
<div id="text-block">
|
||||||
<div id="title">Waiting for song...</div>
|
<div id="title">Waiting for song...</div>
|
||||||
<div id="artist-mapper">-</div>
|
<div id="artist-mapper">-</div>
|
||||||
@@ -377,7 +423,8 @@
|
|||||||
<span id="key">BSR: -</span>
|
<span id="key">BSR: -</span>
|
||||||
<span id="map-date"></span>
|
<span id="map-date"></span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="stats-row">
|
<div id="stats-row">
|
||||||
<div id="progress-wrapper">
|
<div id="progress-wrapper">
|
||||||
<div id="progress-fill"></div>
|
<div id="progress-fill"></div>
|
||||||
@@ -385,8 +432,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="hp-bar-wrapper">
|
<div id="hp-bar-wrapper">
|
||||||
<div id="hp-bar-fill"></div>
|
<div id="hp-bar-fill"></div>
|
||||||
@@ -408,13 +453,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="settings-modal">
|
<div id="settings-modal">
|
||||||
<h2>SYSTEM SETUP</h2>
|
<h2>SYSTEM SETUP [F2]</h2>
|
||||||
<div class="setting-row">
|
<div class="setting-row">
|
||||||
<label>WebSocket URL</label>
|
<label style="font-size: 12px; color: #ccc;">WebSocket URL</label>
|
||||||
<input type="text" id="inp-ws" placeholder="ws://127.0.0.1:2947/socket">
|
<input type="text" id="inp-ws" placeholder="ws://127.0.0.1:2947/socket">
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-row">
|
<div class="setting-row">
|
||||||
<label>Layout (Выравнивание)</label>
|
<label style="font-size: 12px; color: #ccc;">Layout (Выравнивание)</label>
|
||||||
<div class="radio-grid">
|
<div class="radio-grid">
|
||||||
<label class="radio-label"><input type="radio" name="layout" value="top-left"> Top Left</label>
|
<label class="radio-label"><input type="radio" name="layout" value="top-left"> Top Left</label>
|
||||||
<label class="radio-label"><input type="radio" name="layout" value="top-right"> Top Right</label>
|
<label class="radio-label"><input type="radio" name="layout" value="top-right"> Top Right</label>
|
||||||
@@ -423,17 +468,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-row">
|
<div class="setting-row">
|
||||||
<label>Scale (0.5 - 2.0)</label>
|
<label style="font-size: 12px; color: #ccc;">Scale (0.5 - 2.0)</label>
|
||||||
<input type="number" step="0.1" id="inp-scale">
|
<input type="number" step="0.1" id="inp-scale">
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-row">
|
<div class="setting-row">
|
||||||
<label>BeatLeader ID / Nickname</label>
|
<label style="font-size: 12px; color: #ccc;">BeatLeader ID / Nickname</label>
|
||||||
<input type="text" id="inp-bl" placeholder="Например: 76561198029377687">
|
<input type="text" id="inp-bl" placeholder="Например: 76561198029377687">
|
||||||
</div>
|
</div>
|
||||||
<label class="setting-row checkbox-row">
|
|
||||||
<input type="checkbox" id="inp-show-bl">
|
<div class="setting-row">
|
||||||
Показывать BeatLeader в меню
|
<label style="font-size: 12px; color: #ccc; margin-top: 5px;">Модули отображения (Вкл/Выкл)</label>
|
||||||
</label>
|
<div class="modules-grid">
|
||||||
|
<label class="checkbox-row"><input type="checkbox" id="inp-show-bl"> BeatLeader Меню</label>
|
||||||
|
<label class="checkbox-row"><input type="checkbox" id="inp-show-cover"> Обложка трека</label>
|
||||||
|
<label class="checkbox-row"><input type="checkbox" id="inp-show-songinfo"> Инфо трека (Текст)</label>
|
||||||
|
<label class="checkbox-row"><input type="checkbox" id="inp-show-progress"> Прогресс-бар</label>
|
||||||
|
<label class="checkbox-row"><input type="checkbox" id="inp-show-hp"> HP Бар (Здоровье)</label>
|
||||||
|
<label class="checkbox-row"><input type="checkbox" id="inp-show-stats"> Miss / Combo</label>
|
||||||
|
<label class="checkbox-row"><input type="checkbox" id="inp-show-acc"> Точность (Acc)</label>
|
||||||
|
<label class="checkbox-row"><input type="checkbox" id="inp-glow-avatar"> Неоновое свечение</label>
|
||||||
|
<label class="checkbox-row"><input type="checkbox" id="inp-show-debug"> Debug сообщения</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="setting-row">
|
<div class="setting-row">
|
||||||
<button onclick="saveSettings()">APPLY & RECONNECT</button>
|
<button onclick="saveSettings()">APPLY & RECONNECT</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -446,6 +503,10 @@
|
|||||||
app: document.getElementById('app-container'),
|
app: document.getElementById('app-container'),
|
||||||
menuOverlay: document.getElementById('menu-overlay'),
|
menuOverlay: document.getElementById('menu-overlay'),
|
||||||
playingOverlay: document.getElementById('playing-overlay'),
|
playingOverlay: document.getElementById('playing-overlay'),
|
||||||
|
topGlassPanel: document.getElementById('top-glass-panel'),
|
||||||
|
headerRow: document.getElementById('header-row'),
|
||||||
|
textBlock: document.getElementById('text-block'),
|
||||||
|
statsRow: document.getElementById('stats-row'),
|
||||||
progFill: document.getElementById('progress-fill'),
|
progFill: document.getElementById('progress-fill'),
|
||||||
time: document.getElementById('time-prog'),
|
time: document.getElementById('time-prog'),
|
||||||
title: document.getElementById('title'),
|
title: document.getElementById('title'),
|
||||||
@@ -454,15 +515,21 @@
|
|||||||
bpm: document.getElementById('bpm'),
|
bpm: document.getElementById('bpm'),
|
||||||
key: document.getElementById('key'),
|
key: document.getElementById('key'),
|
||||||
date: document.getElementById('map-date'),
|
date: document.getElementById('map-date'),
|
||||||
|
coverWrapper: document.getElementById('cover-wrapper'),
|
||||||
cover: document.getElementById('cover'),
|
cover: document.getElementById('cover'),
|
||||||
|
bottomStats: document.getElementById('bottom-stats'),
|
||||||
|
bottomStatRow: document.querySelector('.bottom-stat-row'),
|
||||||
|
accLarge: document.querySelector('.acc-large'),
|
||||||
accNum: document.getElementById('acc-num'),
|
accNum: document.getElementById('acc-num'),
|
||||||
accGrade: document.getElementById('acc-grade'),
|
accGrade: document.getElementById('acc-grade'),
|
||||||
combo: document.getElementById('combo-val'),
|
combo: document.getElementById('combo-val'),
|
||||||
miss: document.getElementById('miss-val'),
|
miss: document.getElementById('miss-val'),
|
||||||
|
hpBarWrapper: document.getElementById('hp-bar-wrapper'),
|
||||||
hpVal: document.getElementById('hp-val'),
|
hpVal: document.getElementById('hp-val'),
|
||||||
hpFill: document.getElementById('hp-bar-fill'),
|
hpFill: document.getElementById('hp-bar-fill'),
|
||||||
debug: document.getElementById('debug'),
|
debug: document.getElementById('debug'),
|
||||||
settings: document.getElementById('settings-modal'),
|
settings: document.getElementById('settings-modal'),
|
||||||
|
blAvatarWrapper: document.getElementById('bl-avatar-wrapper'),
|
||||||
blAvatar: document.getElementById('bl-avatar'),
|
blAvatar: document.getElementById('bl-avatar'),
|
||||||
blName: document.getElementById('bl-name'),
|
blName: document.getElementById('bl-name'),
|
||||||
blGlobal: document.getElementById('bl-global'),
|
blGlobal: document.getElementById('bl-global'),
|
||||||
@@ -470,7 +537,23 @@
|
|||||||
blPp: document.getElementById('bl-pp')
|
blPp: document.getElementById('bl-pp')
|
||||||
};
|
};
|
||||||
|
|
||||||
let config = { ws: 'ws://127.0.0.1:2947/socket', layout: 'top-left', scale: 1.0, blId: '', showBL: true };
|
let config = {
|
||||||
|
ws: 'ws://127.0.0.1:2947/socket',
|
||||||
|
layout: 'top-left',
|
||||||
|
scale: 1.0,
|
||||||
|
blId: '',
|
||||||
|
showBL: true,
|
||||||
|
showDebugUI: true,
|
||||||
|
glowAvatar: true,
|
||||||
|
// Новые модули
|
||||||
|
showCover: true,
|
||||||
|
showSongInfo: true,
|
||||||
|
showProgress: true,
|
||||||
|
showHp: true,
|
||||||
|
showStats: true,
|
||||||
|
showAcc: true
|
||||||
|
};
|
||||||
|
|
||||||
let ws = null;
|
let ws = null;
|
||||||
let reconnectAttempts = 0;
|
let reconnectAttempts = 0;
|
||||||
let reconnectTimeout = null;
|
let reconnectTimeout = null;
|
||||||
@@ -480,13 +563,16 @@
|
|||||||
let blFailCount = 0;
|
let blFailCount = 0;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
els.app.style.display = 'none';
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
applyLayout();
|
applyLayout();
|
||||||
|
applyModules();
|
||||||
|
applyGlow();
|
||||||
connectWS();
|
connectWS();
|
||||||
setMode('menu');
|
|
||||||
|
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
if (e.key === 'F1') els.settings.classList.toggle('show');
|
if (e.key === 'F2') els.settings.classList.toggle('show');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,7 +583,18 @@
|
|||||||
document.getElementById('inp-ws').value = config.ws;
|
document.getElementById('inp-ws').value = config.ws;
|
||||||
document.getElementById('inp-scale').value = config.scale;
|
document.getElementById('inp-scale').value = config.scale;
|
||||||
document.getElementById('inp-bl').value = config.blId;
|
document.getElementById('inp-bl').value = config.blId;
|
||||||
|
|
||||||
document.getElementById('inp-show-bl').checked = config.showBL !== false;
|
document.getElementById('inp-show-bl').checked = config.showBL !== false;
|
||||||
|
document.getElementById('inp-show-debug').checked = config.showDebugUI !== false;
|
||||||
|
document.getElementById('inp-glow-avatar').checked = config.glowAvatar !== false;
|
||||||
|
|
||||||
|
// Новые чекбоксы модулей
|
||||||
|
document.getElementById('inp-show-cover').checked = config.showCover !== false;
|
||||||
|
document.getElementById('inp-show-songinfo').checked = config.showSongInfo !== false;
|
||||||
|
document.getElementById('inp-show-progress').checked = config.showProgress !== false;
|
||||||
|
document.getElementById('inp-show-hp').checked = config.showHp !== false;
|
||||||
|
document.getElementById('inp-show-stats').checked = config.showStats !== false;
|
||||||
|
document.getElementById('inp-show-acc').checked = config.showAcc !== false;
|
||||||
|
|
||||||
const radio = document.querySelector(`input[name="layout"][value="${config.layout}"]`);
|
const radio = document.querySelector(`input[name="layout"][value="${config.layout}"]`);
|
||||||
if(radio) radio.checked = true;
|
if(radio) radio.checked = true;
|
||||||
@@ -507,7 +604,18 @@
|
|||||||
config.ws = document.getElementById('inp-ws').value;
|
config.ws = document.getElementById('inp-ws').value;
|
||||||
config.scale = parseFloat(document.getElementById('inp-scale').value) || 1.0;
|
config.scale = parseFloat(document.getElementById('inp-scale').value) || 1.0;
|
||||||
config.blId = document.getElementById('inp-bl').value.trim();
|
config.blId = document.getElementById('inp-bl').value.trim();
|
||||||
|
|
||||||
config.showBL = document.getElementById('inp-show-bl').checked;
|
config.showBL = document.getElementById('inp-show-bl').checked;
|
||||||
|
config.showDebugUI = document.getElementById('inp-show-debug').checked;
|
||||||
|
config.glowAvatar = document.getElementById('inp-glow-avatar').checked;
|
||||||
|
|
||||||
|
// Сохраняем состояние модулей
|
||||||
|
config.showCover = document.getElementById('inp-show-cover').checked;
|
||||||
|
config.showSongInfo = document.getElementById('inp-show-songinfo').checked;
|
||||||
|
config.showProgress = document.getElementById('inp-show-progress').checked;
|
||||||
|
config.showHp = document.getElementById('inp-show-hp').checked;
|
||||||
|
config.showStats = document.getElementById('inp-show-stats').checked;
|
||||||
|
config.showAcc = document.getElementById('inp-show-acc').checked;
|
||||||
|
|
||||||
const checkedRadio = document.querySelector('input[name="layout"]:checked');
|
const checkedRadio = document.querySelector('input[name="layout"]:checked');
|
||||||
if(checkedRadio) config.layout = checkedRadio.value;
|
if(checkedRadio) config.layout = checkedRadio.value;
|
||||||
@@ -516,8 +624,9 @@
|
|||||||
els.settings.classList.remove('show');
|
els.settings.classList.remove('show');
|
||||||
|
|
||||||
applyLayout();
|
applyLayout();
|
||||||
|
applyModules();
|
||||||
|
applyGlow();
|
||||||
connectWS();
|
connectWS();
|
||||||
setMode('menu');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyLayout() {
|
function applyLayout() {
|
||||||
@@ -542,13 +651,14 @@
|
|||||||
els.app.style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
els.app.style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
||||||
els.playingOverlay.style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
els.playingOverlay.style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
||||||
|
|
||||||
document.getElementById('header-row').style.flexDirection = isLeft ? 'row' : 'row-reverse';
|
els.headerRow.style.flexDirection = isLeft ? 'row' : 'row-reverse';
|
||||||
document.getElementById('text-block').style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
els.textBlock.style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
||||||
document.getElementById('text-block').style.textAlign = isLeft ? 'left' : 'right';
|
els.textBlock.style.textAlign = isLeft ? 'left' : 'right';
|
||||||
document.getElementById('stats-row').style.justifyContent = isLeft ? 'flex-start' : 'flex-end';
|
|
||||||
|
|
||||||
document.getElementById('bottom-stats').style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
els.statsRow.style.justifyContent = isLeft ? 'flex-start' : 'flex-end';
|
||||||
document.querySelector('.bottom-stat-row').style.flexDirection = isLeft ? 'row' : 'row-reverse';
|
|
||||||
|
els.bottomStats.style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
||||||
|
els.bottomStatRow.style.flexDirection = isLeft ? 'row' : 'row-reverse';
|
||||||
|
|
||||||
document.getElementById('bl-wrapper').style.flexDirection = isLeft ? 'row' : 'row-reverse';
|
document.getElementById('bl-wrapper').style.flexDirection = isLeft ? 'row' : 'row-reverse';
|
||||||
document.getElementById('bl-info').style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
document.getElementById('bl-info').style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
||||||
@@ -560,11 +670,46 @@
|
|||||||
els.progFill.style.marginLeft = isLeft ? '0' : 'auto';
|
els.progFill.style.marginLeft = isLeft ? '0' : 'auto';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyModules() {
|
||||||
|
// Управление отображением обложки и текста
|
||||||
|
els.coverWrapper.style.display = config.showCover ? 'flex' : 'none';
|
||||||
|
els.textBlock.style.display = config.showSongInfo ? 'flex' : 'none';
|
||||||
|
|
||||||
|
// Если и обложка и текст выключены - скрываем весь верхний ряд
|
||||||
|
const showHeader = config.showCover || config.showSongInfo;
|
||||||
|
els.headerRow.style.display = showHeader ? 'flex' : 'none';
|
||||||
|
|
||||||
|
// Прогресс бар
|
||||||
|
els.statsRow.style.display = config.showProgress ? 'flex' : 'none';
|
||||||
|
|
||||||
|
// Если выключено вообще всё внутри стеклянной панели - скрываем саму панель
|
||||||
|
const showTopPanel = showHeader || config.showProgress;
|
||||||
|
els.topGlassPanel.style.display = showTopPanel ? 'flex' : 'none';
|
||||||
|
|
||||||
|
// HP Бар
|
||||||
|
els.hpBarWrapper.style.display = config.showHp ? 'flex' : 'none';
|
||||||
|
|
||||||
|
// Статистика внизу (Мисс/Комбо и Точность)
|
||||||
|
els.bottomStatRow.style.display = config.showStats ? 'flex' : 'none';
|
||||||
|
els.accLarge.style.display = config.showAcc ? 'flex' : 'none';
|
||||||
|
|
||||||
|
// Если выключены обе нижние статистики - скрываем их общий контейнер
|
||||||
|
const showBottomStats = config.showStats || config.showAcc;
|
||||||
|
els.bottomStats.style.display = showBottomStats ? 'flex' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyGlow() {
|
||||||
|
if(els.blAvatarWrapper) els.blAvatarWrapper.classList.toggle('active-glow', config.glowAvatar !== false);
|
||||||
|
if(els.coverWrapper) els.coverWrapper.classList.toggle('active-glow', config.glowAvatar !== false);
|
||||||
|
}
|
||||||
|
|
||||||
function showDebug(msg) {
|
function showDebug(msg) {
|
||||||
|
console.log("[BS+ Overlay]", msg);
|
||||||
|
if (config.showDebugUI === false) return;
|
||||||
|
|
||||||
clearTimeout(debugTimeout);
|
clearTimeout(debugTimeout);
|
||||||
els.debug.textContent = msg;
|
els.debug.textContent = msg;
|
||||||
els.debug.style.opacity = 1;
|
els.debug.style.opacity = 1;
|
||||||
console.log("[BS+ Overlay]", msg);
|
|
||||||
debugTimeout = setTimeout(() => els.debug.style.opacity = 0, 5000);
|
debugTimeout = setTimeout(() => els.debug.style.opacity = 0, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,13 +729,22 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getGrade(acc) {
|
function getGrade(acc) {
|
||||||
if (acc >= 0.9) return { grade: 'SS', color: 'var(--neon-cyan)' };
|
let grade = 'E';
|
||||||
if (acc >= 0.8) return { grade: 'S', color: '#fff' };
|
if (acc >= 0.9) grade = 'SS';
|
||||||
if (acc >= 0.65) return { grade: 'A', color: 'var(--neon-lime)' };
|
else if (acc >= 0.8) grade = 'S';
|
||||||
if (acc >= 0.5) return { grade: 'B', color: '#ffeb3b' };
|
else if (acc >= 0.65) grade = 'A';
|
||||||
if (acc >= 0.35) return { grade: 'C', color: '#ff9800' };
|
else if (acc >= 0.5) grade = 'B';
|
||||||
if (acc >= 0.2) return { grade: 'D', color: 'var(--neon-red)' };
|
else if (acc >= 0.35) grade = 'C';
|
||||||
return { grade: 'E', color: 'darkred' };
|
else if (acc >= 0.2) grade = 'D';
|
||||||
|
|
||||||
|
let color = '#e0e0e0';
|
||||||
|
if (acc >= 0.95) color = '#b046ff';
|
||||||
|
else if (acc >= 0.90) color = '#ff3b3b';
|
||||||
|
else if (acc >= 0.85) color = '#ff9800';
|
||||||
|
else if (acc >= 0.80) color = '#00e5ff';
|
||||||
|
else if (acc >= 0.70) color = '#39ff14';
|
||||||
|
|
||||||
|
return { grade, color };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDifficultyStyle(diff) {
|
function getDifficultyStyle(diff) {
|
||||||
@@ -612,7 +766,6 @@
|
|||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
els.key.textContent = `BSR: ${data.id}`;
|
els.key.textContent = `BSR: ${data.id}`;
|
||||||
|
|
||||||
// Форматирование даты
|
|
||||||
if (data.uploaded) {
|
if (data.uploaded) {
|
||||||
const date = new Date(data.uploaded);
|
const date = new Date(data.uploaded);
|
||||||
els.date.textContent = date.toLocaleDateString();
|
els.date.textContent = date.toLocaleDateString();
|
||||||
@@ -625,7 +778,7 @@
|
|||||||
|
|
||||||
async function fetchBL(force = false) {
|
async function fetchBL(force = false) {
|
||||||
if (!config.blId || !config.showBL) return;
|
if (!config.blId || !config.showBL) return;
|
||||||
if (!force && Date.now() - lastBlFetch < 60000) return;
|
if (!force && Date.now() - lastBlFetch < 900000) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const isNumeric = /^\d+$/.test(config.blId);
|
const isNumeric = /^\d+$/.test(config.blId);
|
||||||
@@ -653,9 +806,9 @@
|
|||||||
|
|
||||||
if (player.avatar) {
|
if (player.avatar) {
|
||||||
els.blAvatar.src = player.avatar;
|
els.blAvatar.src = player.avatar;
|
||||||
els.blAvatar.style.display = 'block';
|
els.blAvatarWrapper.style.display = 'block';
|
||||||
} else {
|
} else {
|
||||||
els.blAvatar.style.display = 'none';
|
els.blAvatarWrapper.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
lastBlFetch = Date.now();
|
lastBlFetch = Date.now();
|
||||||
@@ -673,11 +826,17 @@
|
|||||||
function connectWS() {
|
function connectWS() {
|
||||||
if (ws) { ws.onclose = null; ws.close(); }
|
if (ws) { ws.onclose = null; ws.close(); }
|
||||||
clearTimeout(reconnectTimeout);
|
clearTimeout(reconnectTimeout);
|
||||||
|
els.app.style.display = 'none';
|
||||||
|
|
||||||
showDebug(`Connecting to ${config.ws}...`);
|
showDebug(`Connecting to ${config.ws}...`);
|
||||||
try { ws = new WebSocket(config.ws); } catch (e) { handleDisconnect(); return; }
|
try { ws = new WebSocket(config.ws); } catch (e) { handleDisconnect(); return; }
|
||||||
|
|
||||||
ws.onopen = () => { showDebug('✅ WebSocket Connected'); reconnectAttempts = 0; };
|
ws.onopen = () => {
|
||||||
|
showDebug('✅ WebSocket Connected');
|
||||||
|
reconnectAttempts = 0;
|
||||||
|
els.app.style.display = 'flex';
|
||||||
|
setMode('menu');
|
||||||
|
};
|
||||||
ws.onclose = () => handleDisconnect();
|
ws.onclose = () => handleDisconnect();
|
||||||
ws.onerror = () => handleDisconnect();
|
ws.onerror = () => handleDisconnect();
|
||||||
|
|
||||||
@@ -710,7 +869,6 @@
|
|||||||
if (m.BSRKey) {
|
if (m.BSRKey) {
|
||||||
els.key.textContent = `BSR: ${m.BSRKey}`;
|
els.key.textContent = `BSR: ${m.BSRKey}`;
|
||||||
els.date.textContent = ``;
|
els.date.textContent = ``;
|
||||||
// Даже если ключ есть, пробуем обновить дату
|
|
||||||
if (m.level_id?.startsWith('custom_level_')) fetchBSR(m.level_id.substring(13));
|
if (m.level_id?.startsWith('custom_level_')) fetchBSR(m.level_id.substring(13));
|
||||||
} else if (m.level_id?.startsWith('custom_level_')) {
|
} else if (m.level_id?.startsWith('custom_level_')) {
|
||||||
fetchBSR(m.level_id.substring(13));
|
fetchBSR(m.level_id.substring(13));
|
||||||
@@ -756,13 +914,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleDisconnect() {
|
function handleDisconnect() {
|
||||||
|
els.app.style.display = 'none';
|
||||||
if (reconnectAttempts < 10) {
|
if (reconnectAttempts < 10) {
|
||||||
const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30000);
|
const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30000);
|
||||||
showDebug(`❌ WS Lost. Reconnecting in ${delay/1000}s...`);
|
showDebug(`❌ WS Lost. Reconnecting in ${delay/1000}s...`);
|
||||||
reconnectAttempts++;
|
reconnectAttempts++;
|
||||||
reconnectTimeout = setTimeout(connectWS, delay);
|
reconnectTimeout = setTimeout(connectWS, delay);
|
||||||
} else {
|
} else {
|
||||||
showDebug(`❌ Max reconnects reached. F1 to reconfigure.`);
|
showDebug(`❌ Max reconnects reached. F2 to reconfigure.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user