feat: add password protection UI and fix launch flow

- Password management UI in settings (set/change/remove password)
- Shield icon on play button for protected identities
- Interactive password popup on launch with inline error display
- Fix: re-throw password errors instead of falling to local tokens
- Fix: password popup properly cleans up on success/cancel
- Fix: expose updatePasswordShieldIcon for cross-module access

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
sanasol
2026-02-28 16:45:46 +01:00
parent ee53911a06
commit 0b861904ba
7 changed files with 809 additions and 17 deletions

View File

@@ -77,6 +77,7 @@
<button class="identity-btn" onclick="toggleIdentityDropdown()">
<i class="fas fa-id-badge"></i>
<span id="currentIdentityName">Player</span>
<i id="passwordShieldIcon" class="fas fa-unlock password-shield unprotected" data-tooltip="Click to protect identity" onclick="event.stopPropagation(); openPasswordModal()"></i>
<i class="fas fa-chevron-down"></i>
</button>
<div class="identity-dropdown" id="identityDropdown">
@@ -830,6 +831,41 @@
</p>
</div>
</div>
<div class="uuid-advanced-section" style="margin-top: 12px;">
<button id="passwordSectionToggle" class="uuid-advanced-toggle">
<i class="fas fa-chevron-right uuid-advanced-chevron"></i>
<span>Password Protection</span>
</button>
<div id="passwordSectionContent" class="uuid-advanced-content" style="display: none;">
<h3 class="uuid-section-title">Protect Your Identity</h3>
<p class="uuid-custom-hint" style="margin-bottom: 12px;">
<i class="fas fa-shield-alt"></i>
<span>Set a password to prevent others from using your UUID</span>
</p>
<div id="passwordStatusMsg" class="uuid-custom-hint" style="margin-bottom: 8px; color: #93a3b8;"></div>
<div id="passwordSetForm">
<div class="uuid-custom-form" style="margin-bottom: 8px;">
<input type="password" id="currentPasswordInput" class="uuid-input"
placeholder="Current password" style="display: none;" />
</div>
<div class="uuid-custom-form" style="margin-bottom: 8px;">
<input type="password" id="newPasswordInput" class="uuid-input"
placeholder="New password (min 6 chars)" />
</div>
<div class="uuid-custom-form">
<button id="setPasswordBtn" class="uuid-set-btn" onclick="handleSetPassword()">
<i class="fas fa-lock"></i>
<span>Set Password</span>
</button>
<button id="removePasswordBtn" class="uuid-cancel-btn" onclick="handleRemovePassword()" style="display: none;">
<i class="fas fa-unlock"></i>
<span>Remove Password</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -861,6 +897,59 @@
</div>
</div>
<!-- Password Protection Modal -->
<div id="passwordModal" class="uuid-modal" style="display: none;">
<div class="uuid-modal-content" style="max-width: 420px;">
<div class="uuid-modal-header">
<h2 class="uuid-modal-title">
<i class="fas fa-shield-alt mr-2"></i>
<span>Identity Protection</span>
</h2>
<button class="modal-close-btn" onclick="closePasswordModal()">
<i class="fas fa-times"></i>
</button>
</div>
<div class="uuid-modal-body" style="padding: 16px 20px;">
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px; padding: 12px; background: rgba(255,255,255,0.03); border-radius: 8px; border: 1px solid rgba(255,255,255,0.06);">
<i class="fas fa-user" style="color: #22c55e; font-size: 1.2em;"></i>
<div style="flex:1; min-width:0;">
<div id="pwModalName" style="font-weight: 600; font-size: 1em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">Player</div>
<div id="pwModalUuid" style="font-size: 0.7em; color: #6b7280; font-family: monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;"></div>
</div>
<div id="pwModalStatusBadge" style="flex-shrink:0;"></div>
</div>
<div id="pwModalStatusText" style="margin-bottom: 14px; font-size: 0.85em; color: #93a3b8; text-align: center;"></div>
<div id="pwModalSetForm">
<div style="margin-bottom: 10px;">
<input type="password" id="pwModalCurrentPassword" class="uuid-input"
placeholder="Current password" style="display: none; width: 100%;" />
</div>
<div style="margin-bottom: 10px;">
<input type="password" id="pwModalNewPassword" class="uuid-input"
placeholder="New password (min 6 chars)" style="width: 100%;" />
</div>
<div style="display: flex; gap: 8px;">
<button id="pwModalSetBtn" class="uuid-set-btn" style="flex:1;" onclick="handlePasswordModalSet()">
<i class="fas fa-lock"></i>
<span>Set Password</span>
</button>
<button id="pwModalRemoveBtn" class="uuid-cancel-btn" style="display: none;" onclick="handlePasswordModalRemove()">
<i class="fas fa-unlock"></i>
<span>Remove</span>
</button>
</div>
</div>
<div id="pwModalUsernameInfo" style="margin-top: 14px; padding: 10px; background: rgba(34,197,94,0.06); border-radius: 6px; border: 1px solid rgba(34,197,94,0.15); font-size: 0.8em; color: #93a3b8; display: none;">
<i class="fas fa-info-circle" style="color: #22c55e;"></i>
<span>Setting a password also reserves your username — no one else can use it.</span>
</div>
</div>
</div>
</div>
<div class="version-display-bottom">
<i class="fas fa-code-branch"></i>
<span id="launcherVersion"></span>