feat(ui): redesign modern game dashboard and add 2k/4k full-screen fluid scaling

This commit is contained in:
2026-09-17 12:59:30 +00:00
parent 84c28addfe
commit 258b1a9cb1
4 changed files with 357 additions and 34 deletions
+67 -5
View File
@@ -214,14 +214,34 @@ window.GameEngine = class GameEngine {
const statScore = document.getElementById('profile-stat-score');
const statMaterials = document.getElementById('profile-stat-materials');
// Modern Dashboard Hero Profile elements
const heroName = document.getElementById('hero-profile-name');
const heroCloud = document.getElementById('hero-cloud-badge');
const heroCoins = document.getElementById('hero-stat-coins');
const heroLevel = document.getElementById('hero-stat-level');
const heroScore = document.getElementById('hero-stat-score');
if (window.PvZAuth) {
const user = window.PvZAuth.getCurrentUser();
const isGuest = window.PvZAuth.isGuest();
const uData = window.PvZAuth.getUserData();
const uData = window.PvZAuth.getUserData() || {};
const currentCoins = uData.coins !== undefined ? uData.coins : (this.economy ? this.economy.totalCoins : 0);
const currentLevelNum = uData.level !== undefined ? uData.level : (this.currentLevel || 1);
const currentScoreNum = uData.highScore !== undefined ? uData.highScore : (this.highScore || 0);
if (badgeName) badgeName.textContent = isGuest ? '👤 Гость' : `👤 ${user}`;
if (btnAuth) btnAuth.textContent = isGuest ? 'Войти' : 'Профиль';
if (heroName) heroName.textContent = isGuest ? 'Гость' : user;
if (heroCloud) {
heroCloud.textContent = isGuest ? 'Локально' : 'Облако';
heroCloud.className = isGuest ? 'badge-offline' : 'badge-online';
}
if (heroCoins) heroCoins.textContent = currentCoins.toLocaleString('ru-RU');
if (heroLevel) heroLevel.textContent = `Ур. ${currentLevelNum}`;
if (heroScore) heroScore.textContent = currentScoreNum.toLocaleString('ru-RU');
if (btnLogoutNav) {
if (isGuest) btnLogoutNav.classList.add('hidden');
else btnLogoutNav.classList.remove('hidden');
@@ -238,9 +258,9 @@ window.GameEngine = class GameEngine {
if (registerView) registerView.classList.add('hidden');
if (userTitle) userTitle.textContent = user;
if (statCoins) statCoins.textContent = (uData.coins || (this.economy ? this.economy.totalCoins : 0)).toLocaleString('ru-RU');
if (statLevel) statLevel.textContent = `Уровень ${uData.level || this.currentLevel || 1}`;
if (statScore) statScore.textContent = (uData.highScore || this.highScore || 0).toLocaleString('ru-RU');
if (statCoins) statCoins.textContent = currentCoins.toLocaleString('ru-RU');
if (statLevel) statLevel.textContent = `Уровень ${currentLevelNum}`;
if (statScore) statScore.textContent = currentScoreNum.toLocaleString('ru-RU');
if (statMaterials) {
const mats = uData.materials || (this.workshop ? this.workshop.materials : {});
const totalMats = (mats.bioHumus || 0) + (mats.scrapMetal || 0) + (mats.sunEssence || 0) + (mats.crystals || 0);
@@ -856,7 +876,39 @@ window.GameEngine = class GameEngine {
});
}
// Global Pause Hotkeys (Space, KeyP)
// Fullscreen Toggle
const btnFullscreen = document.getElementById('btn-fullscreen');
const toggleFullscreen = () => {
if (!document.fullscreenElement && !document.webkitFullscreenElement) {
const docEl = document.documentElement;
if (docEl.requestFullscreen) {
docEl.requestFullscreen().catch(() => {});
} else if (docEl.webkitRequestFullscreen) {
docEl.webkitRequestFullscreen();
}
} else {
if (document.exitFullscreen) {
document.exitFullscreen().catch(() => {});
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
}
};
if (btnFullscreen) {
btnFullscreen.addEventListener('click', toggleFullscreen);
}
const updateFullscreenBtn = () => {
if (btnFullscreen) {
const isFs = !!(document.fullscreenElement || document.webkitFullscreenElement);
btnFullscreen.textContent = isFs ? '⛶ Окно' : '⛶ Экран';
}
};
document.addEventListener('fullscreenchange', updateFullscreenBtn);
document.addEventListener('webkitfullscreenchange', updateFullscreenBtn);
// Global Hotkeys (Space, KeyP for Pause; KeyF for Fullscreen)
window.addEventListener('keydown', (e) => {
// Do not intercept hotkeys if user is typing in an input or textarea
if (['INPUT', 'TEXTAREA', 'SELECT'].includes(document.activeElement?.tagName)) return;
@@ -865,6 +917,9 @@ window.GameEngine = class GameEngine {
if (this.isRunning) {
this.togglePause();
}
} else if (e.code === 'KeyF') {
e.preventDefault();
toggleFullscreen();
}
});
@@ -969,6 +1024,13 @@ window.GameEngine = class GameEngine {
});
}
const startHeroProfile = document.getElementById('start-hero-profile');
if (startHeroProfile && btnAuthOpen) {
startHeroProfile.addEventListener('click', () => {
btnAuthOpen.click();
});
}
// Modal Close buttons
if (btnAuthClose && authModal) {
btnAuthClose.addEventListener('click', () => {