mirror of
https://github.com/deadcxap/bs-overlay.git
synced 2026-07-02 05:43:39 +03:00
Add files via upload
This commit is contained in:
+97
-66
@@ -236,32 +236,29 @@
|
|||||||
.stat-item.acc-large #acc-num { font-size: 32px; color: #fff; }
|
.stat-item.acc-large #acc-num { font-size: 32px; color: #fff; }
|
||||||
.stat-item.acc-large #acc-grade { font-size: 32px; }
|
.stat-item.acc-large #acc-grade { font-size: 32px; }
|
||||||
|
|
||||||
/* === MENU MODE (BeatLeader) === */
|
/* === КОМПАКТНЫЙ BEATLEADER === */
|
||||||
#menu-overlay { width: 340px; }
|
#bl-wrapper {
|
||||||
|
|
||||||
#bl-profile {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
margin-bottom: 12px;
|
|
||||||
padding-bottom: 12px;
|
|
||||||
border-bottom: 1px dashed rgba(255,255,255,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#bl-avatar {
|
#bl-avatar {
|
||||||
width: 60px;
|
width: 75px;
|
||||||
height: 60px;
|
height: 75px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 2px solid var(--neon-cyan);
|
border: 2px solid rgba(255,255,255,0.2);
|
||||||
box-shadow: 0 0 10px rgba(0,255,255,0.4);
|
box-shadow: 0 0 10px var(--neon-cyan);
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
display: none;
|
display: none;
|
||||||
|
animation: rainbow 10s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
#bl-name-container {
|
#bl-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 2px;
|
justify-content: center;
|
||||||
|
gap: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#bl-name {
|
#bl-name {
|
||||||
@@ -269,17 +266,19 @@
|
|||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
color: var(--neon-magenta);
|
color: var(--neon-magenta);
|
||||||
text-shadow: 0 0 5px rgba(255,0,255,0.5);
|
text-shadow: 0 0 5px rgba(255,0,255,0.5);
|
||||||
|
margin-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bl-stat {
|
.bl-stat-compact {
|
||||||
display: flex;
|
font-size: 13px;
|
||||||
justify-content: space-between;
|
color: #ccc;
|
||||||
font-size: 15px;
|
}
|
||||||
border-bottom: 1px solid rgba(255,255,255,0.05);
|
|
||||||
padding-bottom: 6px;
|
.bl-stat-compact span {
|
||||||
margin-bottom: 6px;
|
color: var(--neon-cyan);
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 0 5px rgba(0,255,255,0.5);
|
||||||
}
|
}
|
||||||
.bl-stat span:last-child { color: var(--neon-cyan); text-shadow: 0 0 5px rgba(0,255,255,0.5); font-weight: bold; }
|
|
||||||
|
|
||||||
/* === SETTINGS MODAL (F1) === */
|
/* === SETTINGS MODAL (F1) === */
|
||||||
#settings-modal {
|
#settings-modal {
|
||||||
@@ -303,11 +302,33 @@
|
|||||||
#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.checkbox-row { flex-direction: row; align-items: center; gap: 10px; cursor: pointer; }
|
||||||
.setting-row input[type="text"], .setting-row input[type="number"], .setting-row select {
|
.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;
|
||||||
}
|
}
|
||||||
.setting-row input:focus, .setting-row select:focus { border-color: var(--neon-cyan); }
|
.setting-row input:focus { border-color: var(--neon-cyan); }
|
||||||
|
|
||||||
|
/* Сетка для Radio Button'ов (вместо Select) */
|
||||||
|
.radio-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.radio-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
padding: 6px 8px;
|
||||||
|
border: 1px solid #444;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
.radio-label:hover { border-color: var(--neon-cyan); }
|
||||||
|
.radio-label 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;
|
||||||
@@ -326,16 +347,15 @@
|
|||||||
|
|
||||||
<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-profile">
|
<div id="bl-wrapper">
|
||||||
<img id="bl-avatar" src="" alt="Avatar">
|
<img id="bl-avatar" src="" alt="Avatar">
|
||||||
<div id="bl-name-container">
|
<div id="bl-info">
|
||||||
<span style="font-size: 10px; color: #888; text-transform: uppercase;">Player Profile</span>
|
<div id="bl-name">Loading...</div>
|
||||||
<span id="bl-name">Loading...</span>
|
<div class="bl-stat-compact">Global: <span id="bl-global">#--</span></div>
|
||||||
|
<div class="bl-stat-compact">Local: <span id="bl-local">#--</span></div>
|
||||||
|
<div class="bl-stat-compact">PP: <span id="bl-pp">-- pp</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bl-stat"><span>Global Rank:</span> <span id="bl-global">#--</span></div>
|
|
||||||
<div class="bl-stat"><span>Local Rank:</span> <span id="bl-local">#--</span></div>
|
|
||||||
<div class="bl-stat"><span>Performance:</span> <span id="bl-pp">-- pp</span></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="playing-overlay" class="view-mode">
|
<div id="playing-overlay" class="view-mode">
|
||||||
@@ -387,13 +407,13 @@
|
|||||||
<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>Layout (Выравнивание)</label>
|
||||||
<select id="inp-layout">
|
<div class="radio-grid">
|
||||||
<option value="top-left">Top Left</option>
|
<label class="radio-label"><input type="radio" name="layout" value="top-left"> Top Left</label>
|
||||||
<option value="top-right">Top Right</option>
|
<label class="radio-label"><input type="radio" name="layout" value="top-right"> Top Right</label>
|
||||||
<option value="bottom-left">Bottom Left</option>
|
<label class="radio-label"><input type="radio" name="layout" value="bottom-left"> Bottom Left</label>
|
||||||
<option value="bottom-right">Bottom Right</option>
|
<label class="radio-label"><input type="radio" name="layout" value="bottom-right"> Bottom Right</label>
|
||||||
</select>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-row">
|
<div class="setting-row">
|
||||||
<label>Scale (0.5 - 2.0)</label>
|
<label>Scale (0.5 - 2.0)</label>
|
||||||
@@ -466,19 +486,25 @@
|
|||||||
if (saved) config = { ...config, ...JSON.parse(saved) };
|
if (saved) config = { ...config, ...JSON.parse(saved) };
|
||||||
|
|
||||||
document.getElementById('inp-ws').value = config.ws;
|
document.getElementById('inp-ws').value = config.ws;
|
||||||
document.getElementById('inp-layout').value = config.layout;
|
|
||||||
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;
|
||||||
|
|
||||||
|
// Устанавливаем радио-кнопку
|
||||||
|
const radio = document.querySelector(`input[name="layout"][value="${config.layout}"]`);
|
||||||
|
if(radio) radio.checked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
config.ws = document.getElementById('inp-ws').value;
|
config.ws = document.getElementById('inp-ws').value;
|
||||||
config.layout = document.getElementById('inp-layout').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;
|
||||||
|
|
||||||
|
// Читаем радио-кнопку
|
||||||
|
const checkedRadio = document.querySelector('input[name="layout"]:checked');
|
||||||
|
if(checkedRadio) config.layout = checkedRadio.value;
|
||||||
|
|
||||||
localStorage.setItem('bsCyberConfig', JSON.stringify(config));
|
localStorage.setItem('bsCyberConfig', JSON.stringify(config));
|
||||||
els.settings.classList.remove('show');
|
els.settings.classList.remove('show');
|
||||||
|
|
||||||
@@ -500,13 +526,16 @@
|
|||||||
els.app.style.left = isLeft ? '20px' : 'auto';
|
els.app.style.left = isLeft ? '20px' : 'auto';
|
||||||
els.app.style.right = isLeft ? 'auto' : '20px';
|
els.app.style.right = isLeft ? 'auto' : '20px';
|
||||||
|
|
||||||
// 2. ИСПРАВЛЕНИЕ: привязка к нужной грани внутри контейнера для нижних режимов
|
// 2. ИНВЕРСИЯ ВЕРТИКАЛИ ДЛЯ BOTTOM:
|
||||||
|
// Если режим bottom, переворачиваем flex-поток, чтобы стеклянная панель была у края экрана
|
||||||
|
els.playingOverlay.style.flexDirection = isTop ? 'column' : 'column-reverse';
|
||||||
|
|
||||||
els.menuOverlay.style.top = isTop ? '0' : 'auto';
|
els.menuOverlay.style.top = isTop ? '0' : 'auto';
|
||||||
els.menuOverlay.style.bottom = isTop ? 'auto' : '0';
|
els.menuOverlay.style.bottom = isTop ? 'auto' : '0';
|
||||||
els.playingOverlay.style.top = isTop ? '0' : 'auto';
|
els.playingOverlay.style.top = isTop ? '0' : 'auto';
|
||||||
els.playingOverlay.style.bottom = isTop ? 'auto' : '0';
|
els.playingOverlay.style.bottom = isTop ? 'auto' : '0';
|
||||||
|
|
||||||
// 3. Отзеркаливание контейнеров
|
// 3. Отзеркаливание контейнеров (Left / Right)
|
||||||
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';
|
||||||
|
|
||||||
@@ -520,7 +549,12 @@
|
|||||||
document.getElementById('bottom-stats').style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
document.getElementById('bottom-stats').style.alignItems = isLeft ? 'flex-start' : 'flex-end';
|
||||||
document.querySelector('.bottom-stat-row').style.flexDirection = isLeft ? 'row' : 'row-reverse';
|
document.querySelector('.bottom-stat-row').style.flexDirection = isLeft ? 'row' : 'row-reverse';
|
||||||
|
|
||||||
// 6. Направление заполнения полосок (если справа, заполняются справа налево)
|
// 6. Отзеркаливание плашки BeatLeader
|
||||||
|
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.textAlign = isLeft ? 'left' : 'right';
|
||||||
|
|
||||||
|
// 7. Направление заполнения прогресс-баров
|
||||||
els.hpFill.style.marginLeft = isLeft ? '0' : 'auto';
|
els.hpFill.style.marginLeft = isLeft ? '0' : 'auto';
|
||||||
els.progFill.style.marginLeft = isLeft ? '0' : 'auto';
|
els.progFill.style.marginLeft = isLeft ? '0' : 'auto';
|
||||||
}
|
}
|
||||||
@@ -570,38 +604,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// === ИСПРАВЛЕННЫЙ BEATLEADER API ===
|
|
||||||
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 < 60000) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
showDebug("Fetching BeatLeader data...");
|
showDebug("Fetching BeatLeader data...");
|
||||||
|
|
||||||
// Проверяем, ввел ли пользователь только цифры (Steam ID)
|
|
||||||
const isNumeric = /^\d+$/.test(config.blId);
|
const isNumeric = /^\d+$/.test(config.blId);
|
||||||
|
|
||||||
// ИСПОЛЬЗУЕМ ДОМЕН .xyz! Домен .com выдает ошибку CORS.
|
let originalUrl;
|
||||||
const url = isNumeric
|
if (isNumeric) {
|
||||||
? `https://api.beatleader.xyz/player/${config.blId}?stats=true`
|
originalUrl = `https://api.beatleader.xyz/player/${config.blId}?stats=true`;
|
||||||
: `https://api.beatleader.xyz/players?search=${config.blId}`;
|
} else {
|
||||||
|
originalUrl = `https://api.beatleader.xyz/players?search=${encodeURIComponent(config.blId)}`;
|
||||||
const res = await fetch(url);
|
|
||||||
|
|
||||||
if (!res.ok) throw new Error(`Network response was not ok: ${res.status}`);
|
|
||||||
const json = await res.json();
|
|
||||||
|
|
||||||
// Если искали по никнейму, API возвращает объект { data: [...] }
|
|
||||||
const player = json.data ? json.data[0] : json;
|
|
||||||
|
|
||||||
if (!player) {
|
|
||||||
throw new Error("Игрок не найден");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const proxiedUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent(originalUrl)}`;
|
||||||
|
const res = await fetch(proxiedUrl, { headers: { 'Accept': 'application/json' } });
|
||||||
|
|
||||||
|
if (!res.ok) throw new Error(`Network error: ${res.status}`);
|
||||||
|
|
||||||
|
const json = await res.json();
|
||||||
|
const player = json.data ? json.data[0] : json;
|
||||||
|
|
||||||
|
if (!player || !player.name) throw new Error("Player not found");
|
||||||
|
|
||||||
els.blName.textContent = player.name || "Unknown";
|
els.blName.textContent = player.name || "Unknown";
|
||||||
els.blGlobal.textContent = `#${(player.rank || 0).toLocaleString()}`;
|
els.blGlobal.textContent = player.rank ? `#${player.rank.toLocaleString()}` : "#--";
|
||||||
els.blLocal.textContent = `#${(player.countryRank || 0).toLocaleString()} (${player.country || 'N/A'})`;
|
els.blLocal.textContent = player.countryRank ? `#${player.countryRank.toLocaleString()} (${player.country || 'N/A'})` : "#-- (N/A)";
|
||||||
els.blPp.textContent = `${Math.round(player.pp || 0).toLocaleString()} pp`;
|
els.blPp.textContent = player.pp ? `${Math.round(player.pp).toLocaleString()}` : "--";
|
||||||
|
|
||||||
if (player.avatar) {
|
if (player.avatar) {
|
||||||
els.blAvatar.src = player.avatar;
|
els.blAvatar.src = player.avatar;
|
||||||
@@ -611,11 +642,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
lastBlFetch = Date.now();
|
lastBlFetch = Date.now();
|
||||||
showDebug("BeatLeader updated");
|
showDebug("BeatLeader updated ✓");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showDebug("BL Error: " + err.message);
|
showDebug("BL Error: " + err.message);
|
||||||
els.blName.textContent = "Error: Проверь ID/Ник";
|
els.blName.textContent = "Error loading profile";
|
||||||
console.error(err);
|
console.error("BeatLeader fetch failed:", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user