Files
Password-Manager/index.html
T
Zaki eac02ed17c Replace batch mode toggle with click/Shift/Ctrl selection
- Remove separate 'select mode' toggle and checkbox UI
- Click any entry to select it (blue highlight border)
- Shift+click for range selection between two entries
- Ctrl/Cmd+click to toggle individual entries
- Click entry background or press Escape to clear selection
- Batch action bar appears automatically when items are selected
- Selected entries get accent-color border and highlight
- Single delEntry() cleans up selectedIds
- Shortcut help updated with selection tips
2026-05-09 13:48:22 +01:00

212 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🔐 Vault</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="toast-container" id="toastContainer"></div>
<div class="idle-warning" id="idleWarning">
<h3>⏰ Auto-lock</h3>
<p>Vault locks in <span id="idleCountdown">30</span>s</p>
<button class="btn btn-sm" onclick="resetIdle()">Stay Unlocked</button>
</div>
<div class="edit-modal" id="editModal">
<div class="edit-box">
<h3>✏️ Edit Entry</h3>
<label>Website / App</label><input type="text" id="editSite" placeholder="example.com">
<label style="margin-top:.6rem">Username / Email</label><input type="text" id="editUsername" placeholder="user@example.com">
<label style="margin-top:.6rem">Password</label>
<div style="position:relative">
<input type="password" id="editPassword" placeholder="Password" style="width:100%;padding-right:40px">
<button type="button" onclick="toggleEditPassword()" style="position:absolute;right:8px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--text2);cursor:pointer;font-size:.9rem">👁️</button>
</div>
<label style="margin-top:.6rem">Folder</label>
<select id="editFolder" style="width:100%;margin-bottom:.4rem"></select>
<input type="hidden" id="editId">
<div style="display:flex;gap:.5rem;margin-top:1rem">
<button class="btn" onclick="saveEdit()">💾 Save</button>
<button class="btn btn-outline" onclick="closeEdit()">Cancel</button>
</div>
</div>
</div>
<!-- Add Password Modal -->
<div class="modal-overlay" id="addModal">
<div class="modal-box">
<h3> New Password</h3>
<label>Website / App</label><input type="text" id="addSite" placeholder="example.com">
<label style="margin-top:.6rem">Username / Email (optional)</label><input type="text" id="addUsername" placeholder="user@example.com">
<label style="margin-top:.6rem">Password</label>
<div style="position:relative">
<input type="password" id="addPassword" placeholder="Password" style="width:100%;padding-right:40px" oninput="checkAddStrength()">
<button type="button" onclick="openGen()" style="position:absolute;right:8px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--text2);cursor:pointer;font-size:1.1rem;line-height:1" title="Generate">🎲</button>
</div>
<div class="strength-bar s0" id="addStrengthBar" style="margin-top:0.2rem;"></div>
<label style="margin-top:.6rem">Folder</label>
<select id="addFolder" style="width:100%;margin-bottom:.4rem"></select>
<div style="display:flex;gap:.5rem;margin-top:1rem">
<button class="btn" id="addEntryBtn" onclick="addEntry()">💾 Save</button>
<button class="btn btn-outline" onclick="closeAdd()">Cancel</button>
</div>
</div>
</div>
<!-- Floating action button -->
<button class="fab" onclick="openAdd()" title="Add password">+</button>
<div class="vault">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:0.6rem">
<h1 style="margin-bottom:0">🔐 Vault <span>XAMPP</span></h1>
<button class="btn btn-outline btn-xs" onclick="toggleTheme()" title="Toggle theme">🌓</button>
</div>
<!-- Auth Section -->
<div id="authSection" class="auth-section">
<div class="auth-tabs">
<button class="auth-tab active" onclick="switchTab('login')">Login</button>
<button class="auth-tab" onclick="switchTab('register')">Register</button>
</div>
<div id="loginForm">
<div class="input-group">
<input type="text" id="loginUsername" placeholder="Username" autocomplete="off">
<input type="password" id="loginPassword" placeholder="Master Password" autocomplete="off">
<button class="btn" id="loginBtn" onclick="login()">🔓 Unlock</button>
<button class="btn btn-outline btn-sm" onclick="loginWithPasskey()" title="Use passkey" style="white-space:nowrap">🔐 Passkey</button>
</div>
</div>
<div id="registerForm" class="hidden">
<div class="input-group">
<input type="text" id="regUsername" placeholder="Username (min 3)" autocomplete="off">
<input type="password" id="regPassword" placeholder="Password (min 8)" autocomplete="off" oninput="checkRegStrength()">
<button class="btn" id="registerBtn" onclick="register()">✨ Create</button>
</div>
<div class="strength-bar s0" id="regStrengthBar" style="margin-top:0.4rem;margin-bottom:0.2rem;flex-basis:100%"></div>
</div>
</div>
<!-- Vault Section -->
<div id="vaultSection" class="hidden">
<!-- Top bar -->
<div style="display:flex;justify-content:space-between;margin-bottom:.5rem;align-items:center;flex-wrap:wrap;gap:.4rem">
<span class="status-badge" id="connectionStatus">🟢 Connected</span>
<span id="entryCount" style="color:var(--text2);font-size:.8rem"></span>
<div style="display:flex;gap:.4rem;align-items:center">
<span id="currentUser" style="color:var(--text2);font-size:.8rem"></span>
<div class="settings-dropdown">
<button class="btn btn-outline btn-sm" id="settingsBtn" onclick="toggleSettings()">⚙️</button>
<div class="settings-menu hidden" id="settingsMenu">
<div class="settings-item">
<span>Auto-lock</span>
<select id="autoLockTimer" onchange="setAutoLock()">
<option value="0">No lock</option>
<option value="1">1 min</option>
<option value="5" selected>5 min</option>
<option value="15">15 min</option>
<option value="30">30 min</option>
<option value="60">1 hour</option>
</select>
</div>
<div class="settings-item" onclick="toggleSound();event.stopPropagation();">
<span>Sound</span>
<div class="toggle-switch" id="soundToggleSwitch"></div>
</div>
<div class="settings-item" onclick="toggleTheme();event.stopPropagation();">
<span>Theme</span>
<div class="toggle-switch" id="themeToggleSwitch"></div>
</div>
<div class="settings-item" onclick="toggleViewBtn();event.stopPropagation();">
<span>👁️ View password</span>
<div class="toggle-switch active" id="showViewBtnToggle"></div>
</div>
<div class="settings-item" onclick="toggleShowEmail();event.stopPropagation();">
<span>📧 Show email</span>
<div class="toggle-switch active" id="showEmailToggle"></div>
</div>
<div class="settings-item" onclick="if(window.PublicKeyCredential){registerPasskey()}else{toast('Passkeys not supported','error')};event.stopPropagation();">
<span>🔐 Set up passkey</span>
<span style="color:var(--accent);font-size:0.7rem"></span>
</div>
</div>
</div>
<button class="btn btn-outline btn-sm" onclick="doLogout()">🔒 Lock</button>
</div>
</div>
<!-- Add Entry Form -->
<!-- <form onsubmit="return false" class="input-group" autocomplete="off"> -->
<!-- <input type="text" id="siteInput" placeholder="Website *" autocomplete="off"> -->
<!-- <input type="text" id="usernameInput" placeholder="Username (optional)" autocomplete="off"> -->
<!-- <div style="flex:1;min-width:130px;position:relative"> -->
<!-- <input type="password" id="passwordInput" placeholder="Password *" autocomplete="new-password" style="width:100%;padding-right:40px" oninput="checkStrength()"> -->
<!-- <button type="button" onclick="openGen()" style="position:absolute;right:8px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--text2);cursor:pointer;font-size:1.1rem;line-height:1" title="Generate password">🎲</button> -->
<!-- </div> -->
<!-- <div class="strength-bar s0" id="strengthBar" style="flex-basis:100%;margin-top:-0.3rem;margin-bottom:0.3rem"></div> -->
<!-- <select id="addFolderSelect"></select> -->
<!-- <button type="button" class="btn" id="addBtn" onclick="addEntry()"> Add</button> -->
<!-- </form> -->
<!-- Toolbar with search + trash + views -->
<div class="toolbar">
<div class="search-box">
<input type="text" id="searchInput" placeholder="🔍 Search..." oninput="searchEntries()" autocomplete="off">
<button type="button" class="clear-search-btn" id="clearSearchBtn" onclick="clearSearch()" title="Clear search"></button>
</div>
<div style="display:flex;gap:.4rem;align-items:center;flex-wrap:wrap">
<button class="btn btn-outline btn-sm" id="trashBtn" onclick="toggleTrash()" title="Trash">🗑️</button>
<button class="btn btn-outline btn-sm" onclick="showShortcutsHelp()" title="Shortcuts">⌨️</button>
<div class="view-toggle" id="viewToggle">
<button class="view-btn active" data-view="grid">🟫 Grid</button>
<button class="view-btn" data-view="compact">📝 Compact</button>
<button class="view-btn" data-view="table">📊 Table</button>
<button class="view-btn" data-view="list">📋 List</button>
</div>
</div>
</div>
<div class="folders-bar" id="foldersBar"></div>
<div id="trashActions" class="hidden" style="margin-bottom:.5rem;text-align:right;">
<button class="empty-trash-btn" onclick="emptyTrash()">🗑️ Empty Trash</button>
</div>
<div id="entriesContainer" class="grid-view">
<div style="text-align:center;color:var(--text2);padding:2rem;grid-column:1/-1">📭 No entries</div>
</div>
<div style="margin-top:.6rem;text-align:right">
<button class="btn btn-outline btn-sm" onclick="showExportModal()">📤 Export</button>
</div>
</div>
</div>
<!-- Generator Modal -->
<div id="genModal" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.7);display:none;justify-content:center;align-items:center;z-index:2000">
<div style="background:var(--bg2);border-radius:1.5rem;padding:1.5rem;min-width:320px;max-width:90%">
<h3 style="margin-bottom:.8rem;color:var(--text)">🎲 Generator</h3>
<div style="background:var(--input);padding:.8rem;border-radius:1rem;font-family:monospace;text-align:center;color:#4ade80;margin:.6rem 0;word-break:break-all" id="genPreview">Click Generate</div>
<div style="display:flex;align-items:center;gap:.6rem;margin:.8rem 0">
<span>Length:</span>
<input type="range" id="pwdLen" min="8" max="64" value="16" oninput="onLenChange()" style="flex:1">
<span id="lenVal" style="background:var(--input);padding:.2rem .6rem;border-radius:1rem;min-width:30px;text-align:center">16</span>
</div>
<div style="display:flex;flex-wrap:wrap;gap:.5rem;margin:.5rem 0">
<label style="font-size:.8rem;color:var(--text2)"><input type="checkbox" id="useUpper" checked onchange="genPwd()"> A-Z</label>
<label style="font-size:.8rem;color:var(--text2)"><input type="checkbox" id="useLower" checked onchange="genPwd()"> a-z</label>
<label style="font-size:.8rem;color:var(--text2)"><input type="checkbox" id="useNum" checked onchange="genPwd()"> 0-9</label>
<label style="font-size:.8rem;color:var(--text2)"><input type="checkbox" id="useSym" checked onchange="genPwd()"> !@#$</label>
</div>
<div style="display:flex;gap:0.3rem;margin-top:0.8rem;flex-wrap:wrap">
<button class="btn btn-sm" onclick="genPreset(16,'upper+lower+num+sym')" style="flex:1;min-width:70px">🔒 Strong 16</button>
<button class="btn btn-sm" onclick="genPreset(20,'upper+lower+num+sym')" style="flex:1;min-width:70px">🔒 Strong 20</button>
<button class="btn btn-sm btn-danger" onclick="genPreset(32,'upper+lower+num+sym')" style="flex:1;min-width:70px">🛡️ Paranoid 32</button>
</div>
<div style="display:flex;gap:.4rem;margin-top:.6rem">
<button class="btn" onclick="genPwd()" style="flex:1">🔄</button>
<button class="btn" onclick="useGen()" style="flex:1">✅ Use</button>
<button class="btn btn-outline" onclick="closeGen()">Cancel</button>
</div>
</div>
</div>
<script src="js/app.js"></script>
</body>
</html>