Add Steam Deck UI mode, repo presets, and stronger hover glow (#2)

This commit is contained in:
rubiidev18alt 2026-03-11 19:32:58 -07:00 committed by GitHub
parent 3355244dc4
commit e44695860c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 168 additions and 13 deletions

View file

@ -13,9 +13,9 @@
<div class="title-bar">
<div class="title-bar-text">LegacyLauncher</div>
<div class="window-controls">
<div class="win-btn" onclick="minimizeWindow()"></div>
<div class="win-btn" id="maximize-btn" onclick="toggleMaximize()"></div>
<div class="win-btn close" onclick="closeWindow()">×</div>
<div class="win-btn nav-item" onclick="minimizeWindow()" tabindex="0" title="Minimize"></div>
<div class="win-btn nav-item" id="maximize-btn" onclick="toggleMaximize()" tabindex="0" title="Maximize / Restore"></div>
<div class="win-btn close nav-item" onclick="closeWindow()" tabindex="0" title="Close">×</div>
</div>
</div>
@ -201,6 +201,12 @@
<div class="mc-input-group">
<label class="mc-label">GitHub Repository Source:</label>
<input type="text" id="repo-input" class="mc-input nav-item" placeholder="user/repo" tabindex="0">
<label class="mc-label" style="margin-top: 10px;">Repository Preset:</label>
<select id="repo-preset-select" class="mc-input nav-item" onchange="applyRepoPreset()" tabindex="0" style="height: 48px; margin-top: 8px;">
<option value="custom">Custom</option>
<option value="smartcmd/MinecraftConsoles">smartcmd (default)</option>
<option value="cath0degaytube/MinecraftConsoles">cath0degaytube (no watermark)</option>
</select>
</div>
<div class="mc-input-group">
@ -254,6 +260,13 @@
</label>
</div>
<div class="mc-input-group">
<label class="mc-label" style="display: flex; align-items: center; cursor: pointer;">
<input type="checkbox" id="steamdeck-mode-checkbox" class="nav-item" style="width: 24px; height: 24px; margin-right: 12px; cursor: pointer;" tabindex="0">
Use Steam Deck Optimized UI Mode
</label>
</div>
<div class="flex gap-4 w-full mt-4">
<div id="btn-options-done" class="btn-mc flex-grow nav-item" onclick="saveOptions()" tabindex="0">DONE</div>
<div id="btn-options-cancel" class="btn-mc flex-grow nav-item" onclick="toggleOptions(false)" tabindex="0">CANCEL</div>

View file

@ -9,6 +9,10 @@ const DEFAULT_REPO = "smartcmd/MinecraftConsoles";
const DEFAULT_EXEC = "Minecraft.Client.exe";
const TARGET_FILE = "LCEWindows64.zip";
const LAUNCHER_REPO = "gradenGnostic/LegacyLauncher";
const REPO_PRESETS = {
default: 'smartcmd/MinecraftConsoles',
noWatermark: 'cath0degaytube/MinecraftConsoles'
};
let instances = [];
let currentInstanceId = null;
@ -108,21 +112,22 @@ const GamepadManager = {
const left = isPressed(14) || axisX < -threshold;
const right = isPressed(15) || axisX > threshold;
if (up) { this.navigate('up'); this.lastInputTime = now; }
else if (down) { this.navigate('down'); this.lastInputTime = now; }
else if (left) { this.navigate('left'); this.lastInputTime = now; }
else if (right) { this.navigate('right'); this.lastInputTime = now; }
if (up) { UiSoundManager.setInputSource('controller'); this.navigate('up'); this.lastInputTime = now; }
else if (down) { UiSoundManager.setInputSource('controller'); this.navigate('down'); this.lastInputTime = now; }
else if (left) { UiSoundManager.setInputSource('controller'); this.navigate('left'); this.lastInputTime = now; }
else if (right) { UiSoundManager.setInputSource('controller'); this.navigate('right'); this.lastInputTime = now; }
else if (isPressed(4)) { this.cycleActiveSelection(-1); this.lastInputTime = now; }
else if (isPressed(5)) { this.cycleActiveSelection(1); this.lastInputTime = now; }
else if (isPressed(4)) { UiSoundManager.setInputSource('controller'); this.cycleActiveSelection(-1); this.lastInputTime = now; }
else if (isPressed(5)) { UiSoundManager.setInputSource('controller'); this.cycleActiveSelection(1); this.lastInputTime = now; }
else if (isPressed(1)) { this.cancelCurrent(); this.lastInputTime = now; }
else if (isPressed(1)) { UiSoundManager.setInputSource('controller'); this.cancelCurrent(); this.lastInputTime = now; }
else if (isPressed(2)) { checkForUpdatesManual(); this.lastInputTime = now; }
else if (isPressed(2)) { UiSoundManager.setInputSource('controller'); checkForUpdatesManual(); this.lastInputTime = now; }
}
const aPressed = isPressed(0);
if (aPressed && !this.lastAPressed) {
UiSoundManager.setInputSource('controller');
this.clickActive();
}
this.lastAPressed = aPressed;
@ -218,7 +223,24 @@ const GamepadManager = {
if (active && active.classList.contains('nav-item')) {
active.classList.add('active-bump');
setTimeout(() => active.classList.remove('active-bump'), 100);
if (active.id === 'version-select-box') {
this.cycleActiveSelection(1);
return;
}
if (active.id === 'classic-version-select-box') {
const classicSelect = document.getElementById('classic-version-select');
if (classicSelect) {
classicSelect.selectedIndex = (classicSelect.selectedIndex + 1) % classicSelect.options.length;
syncVersionFromClassic();
}
return;
}
if (active.id === 'compat-select-box') {
this.cycleActiveSelection(1);
return;
}
if (active.tagName === 'INPUT' && active.type === 'checkbox') {
active.checked = !active.checked;
active.dispatchEvent(new Event('change'));
@ -313,6 +335,15 @@ const UiSoundManager = {
lastPlayedAt: {},
cooldownMs: 70,
lastHoverItem: null,
inputSource: 'mouse',
setInputSource(source) {
this.inputSource = source;
},
shouldPlay() {
return this.inputSource === 'controller';
},
init() {
Object.entries(this.files).forEach(([key, file]) => {
@ -321,6 +352,11 @@ const UiSoundManager = {
this.cache[key].volume = key === 'cursor' ? 0.45 : 0.6;
});
const markMouseInput = () => this.setInputSource('mouse');
['mousemove', 'mousedown', 'touchstart', 'wheel', 'keydown'].forEach((ev) => {
document.addEventListener(ev, markMouseInput, { passive: true });
});
document.addEventListener('focusin', (e) => {
if (e.target?.classList?.contains('nav-item')) this.play('cursor');
});
@ -349,6 +385,7 @@ const UiSoundManager = {
},
play(name) {
if (!this.shouldPlay()) return;
const now = Date.now();
if (this.lastPlayedAt[name] && now - this.lastPlayedAt[name] < this.cooldownMs) return;
this.lastPlayedAt[name] = now;
@ -534,6 +571,24 @@ function focusPrimaryPlayButton() {
setTimeout(() => target.classList.remove('controller-active'), 180);
}
function syncRepoPresetFromInput() {
const presetSelect = document.getElementById('repo-preset-select');
const repoInput = document.getElementById('repo-input');
if (!presetSelect || !repoInput) return;
if (repoInput.value.trim() === REPO_PRESETS.default) presetSelect.value = REPO_PRESETS.default;
else if (repoInput.value.trim() === REPO_PRESETS.noWatermark) presetSelect.value = REPO_PRESETS.noWatermark;
else presetSelect.value = 'custom';
}
function applyRepoPreset() {
const presetSelect = document.getElementById('repo-preset-select');
const repoInput = document.getElementById('repo-input');
if (!presetSelect || !repoInput) return;
if (presetSelect.value === 'custom') return;
repoInput.value = presetSelect.value;
}
window.onload = async () => {
try {
await migrateLegacyConfig();
@ -546,13 +601,17 @@ window.onload = async () => {
const serverCheck = document.getElementById('server-checkbox');
const installInput = document.getElementById('install-path-input');
if (repoInput) repoInput.value = currentInstance.repo;
if (repoInput) {
repoInput.value = currentInstance.repo;
repoInput.addEventListener('input', syncRepoPresetFromInput);
}
if (execInput) execInput.value = currentInstance.execPath;
if (usernameInput) usernameInput.value = await Store.get('legacy_username', "");
if (ipInput) ipInput.value = currentInstance.ip;
if (portInput) portInput.value = currentInstance.port;
if (serverCheck) serverCheck.checked = currentInstance.isServer;
if (installInput) installInput.value = currentInstance.installPath;
syncRepoPresetFromInput();
if (process.platform === 'linux' || process.platform === 'darwin') {
const compatContainer = document.getElementById('compat-option-container');
@ -572,6 +631,7 @@ window.onload = async () => {
// Initialize features
await loadTheme();
await loadSteamDeckMode();
fetchGitHubData();
checkForLauncherUpdates();
loadSplashText();
@ -731,6 +791,7 @@ async function switchInstance(id) {
await saveInstancesToStore();
document.getElementById('repo-input').value = currentInstance.repo;
syncRepoPresetFromInput();
document.getElementById('exec-input').value = currentInstance.execPath;
document.getElementById('ip-input').value = currentInstance.ip;
document.getElementById('port-input').value = currentInstance.port;
@ -1250,6 +1311,9 @@ function toggleOptions(show) {
// Sync classic theme checkbox to current state
const cb = document.getElementById('classic-theme-checkbox');
if (cb) cb.checked = document.body.classList.contains('classic-theme');
const steamDeckCb = document.getElementById('steamdeck-mode-checkbox');
if (steamDeckCb) steamDeckCb.checked = document.body.classList.contains('steamdeck-mode');
syncRepoPresetFromInput();
document.activeElement?.blur(); modal.style.display = 'flex'; modal.style.opacity = '1';
UiSoundManager.play('popupOpen');
}
@ -1364,8 +1428,11 @@ async function saveOptions() {
currentInstance.customCompatPath = customProtonPath;
}
const isClassic = document.getElementById('classic-theme-checkbox')?.checked || false;
const isSteamDeckMode = document.getElementById('steamdeck-mode-checkbox')?.checked || false;
await Store.set('legacy_classic_theme', isClassic);
await Store.set('legacy_steamdeck_mode', isSteamDeckMode);
applyTheme(isClassic);
applySteamDeckMode(isSteamDeckMode);
await saveInstancesToStore(); toggleOptions(false); fetchGitHubData(); updatePlayButtonText(); showToast("Settings Saved");
}
@ -1596,6 +1663,19 @@ async function loadTheme() {
applyTheme(isClassic);
}
async function loadSteamDeckMode() {
const autoSteamDeck = isSteamDeckEnvironment();
const saved = await Store.get('legacy_steamdeck_mode', null);
const enabled = saved === null ? autoSteamDeck : saved;
const cb = document.getElementById('steamdeck-mode-checkbox');
if (cb) cb.checked = enabled;
applySteamDeckMode(enabled);
}
function applySteamDeckMode(enabled) {
document.body.classList.toggle('steamdeck-mode', !!enabled);
}
function applyTheme(isClassic) {
document.body.classList.toggle('classic-theme', isClassic);
if (isClassic) {
@ -1806,6 +1886,7 @@ window.checkForUpdatesManual = checkForUpdatesManual;
window.browseInstallDir = browseInstallDir;
window.openGameDir = openGameDir;
window.toggleMusic = toggleMusic;
window.applyRepoPreset = applyRepoPreset;
window.getInstallDir = getInstallDir;
window.showToast = showToast;
window.toggleInstances = toggleInstances;

View file

@ -19,6 +19,13 @@ document.addEventListener('DOMContentLoaded', () => {
if (skinInput) skinInput.addEventListener('change', (e) => handleSkinFile(e.target.files[0]));
if (dropZone) {
dropZone.addEventListener('click', () => skinInput?.click());
dropZone.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
skinInput?.click();
}
});
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.classList.add('border-green-500');

View file

@ -94,6 +94,15 @@ body {
background: #c42b1c;
}
.win-btn.nav-item:focus {
transform: scale(1.08);
z-index: 1001;
box-shadow: 0 0 0 1px rgba(255,255,255,0.95), 0 0 8px rgba(255,255,255,0.55) !important;
background: #444;
color: #fff;
}
.main-wrapper {
display: flex;
flex-grow: 1;
@ -364,6 +373,11 @@ body {
filter: brightness(1.08);
}
.nav-item:hover {
outline: 1px solid rgba(255,255,255,0.92) !important;
box-shadow: 0 0 0 1px rgba(255,255,255,0.85), 0 0 12px rgba(255, 255, 255, 0.52), 0 0 24px rgba(90, 170, 255, 0.22) !important;
}
.nav-item.active-bump {
transform: scale(0.95) !important;
transition: transform 0.1s !important;
@ -402,6 +416,46 @@ body {
text-shadow: 2px 2px 0 #000;
}
/* Steam Deck optimized mode */
body.steamdeck-mode .title-bar {
height: 40px;
}
body.steamdeck-mode .title-bar-text {
font-size: 18px;
}
body.steamdeck-mode .btn-mc {
min-height: 68px;
font-size: 28px;
}
body.steamdeck-mode .btn-play {
min-height: 110px;
font-size: 52px;
}
body.steamdeck-mode .version-select-box {
height: 64px;
font-size: 26px;
}
body.steamdeck-mode .mc-input,
body.steamdeck-mode #repo-preset-select,
body.steamdeck-mode .mc-label,
body.steamdeck-mode .classic-link {
font-size: 20px !important;
}
body.steamdeck-mode .nav-item:focus {
transform: scale(1.06);
box-shadow: 0 0 0 2px rgba(255,255,255,0.95), 0 0 22px rgba(255,255,255,0.7), 0 0 34px rgba(90,170,255,0.36) !important;
}
body.steamdeck-mode .sidebar {
width: 420px;
}
.version-row {
display: flex;
width: 500px;