import { isAcceptableNewAccessPin, isForbiddenAccessPin, isValidAccessPin, normalizePinDigits } from '../lib/ellyAccessPin.js'; document.addEventListener('DOMContentLoaded', () => { let enteredPIN = ''; let confirmPIN = ''; let setupStep = 'enter'; // enter | confirm (setup mode only) const pinDisplay = document.getElementById('pinDisplay'); const errorMessage = document.getElementById('errorMessage'); const titleEl = document.querySelector('h1'); const subtitleEl = document.querySelector('.subtitle'); const params = new URLSearchParams(window.location.search); const isSetupMode = params.get('mode') === 'setup'; if (isSetupMode) { if (titleEl) { titleEl.textContent = 'Set Access PIN'; } if (subtitleEl) { subtitleEl.textContent = 'Choose an 8-digit Access PIN (not 12345678)'; } } // Initialize PIN display updatePinDisplay(); // Number buttons document.querySelectorAll('.pin-btn[data-digit]').forEach(btn => { btn.addEventListener('click', (e) => { const target = /** @type {HTMLElement} */ (e.currentTarget); const digit = target?.dataset?.digit; if (!digit) { return; } if (enteredPIN.length < 8) { enteredPIN += digit; updatePinDisplay(); if (errorMessage) { errorMessage.textContent = ''; } } }); }); // Backspace button document.getElementById('btnBackspace')?.addEventListener('click', () => { if (enteredPIN.length > 0) { enteredPIN = enteredPIN.slice(0, -1); updatePinDisplay(); if (errorMessage) { errorMessage.textContent = ''; } } }); // Clear button document.getElementById('btnClear')?.addEventListener('click', () => { enteredPIN = ''; updatePinDisplay(); if (errorMessage) { errorMessage.textContent = ''; } }); // Submit button document.getElementById('btnSubmit')?.addEventListener('click', () => { submitPin().catch((err) => console.error(err)); }); // Enter key support document.addEventListener('keydown', (e) => { if (e.key >= '0' && e.key <= '9' && enteredPIN.length < 8) { enteredPIN += e.key; updatePinDisplay(); if (errorMessage) { errorMessage.textContent = ''; } } else if (e.key === 'Backspace') { enteredPIN = enteredPIN.slice(0, -1); updatePinDisplay(); if (errorMessage) { errorMessage.textContent = ''; } } else if (e.key === 'Enter') { submitPin().catch((err) => console.error(err)); } }); /** * Renders the 8 PIN digit slots. * @returns {void} */ function updatePinDisplay() { if (!pinDisplay) { return; } pinDisplay.innerHTML = ''; for (let i = 0; i < 8; i++) { const digitDiv = document.createElement('div'); digitDiv.className = 'pin-digit'; digitDiv.textContent = enteredPIN[i] || '•'; pinDisplay.appendChild(digitDiv); } } /** * Opens the main popup window after successful Access PIN auth. * @returns {Promise} */ async function openMainPopupThenClose() { try { await chrome.windows.create({ url: chrome.runtime.getURL('popup/popup.html'), type: 'popup', width: 560, height: 640, focused: true }); } catch (err) { console.error('Elly pin: open popup failed', err); } window.close(); } /** * Handles submit for unlock or setup (two-step confirm). * @returns {Promise} */ async function submitPin() { if (!errorMessage) { return; } if (enteredPIN.length !== 8) { errorMessage.textContent = 'Please enter 8 digits'; return; } const pin = normalizePinDigits(enteredPIN); if (isSetupMode) { if (setupStep === 'enter') { if (!isAcceptableNewAccessPin(pin)) { errorMessage.textContent = isForbiddenAccessPin(pin) ? 'That PIN is not allowed. Choose a different 8-digit PIN.' : 'PIN must be 8 digits'; enteredPIN = ''; updatePinDisplay(); return; } confirmPIN = pin; enteredPIN = ''; setupStep = 'confirm'; if (subtitleEl) { subtitleEl.textContent = 'Confirm your 8-digit Access PIN'; } updatePinDisplay(); return; } if (pin !== confirmPIN) { errorMessage.textContent = 'PINs do not match. Try again.'; enteredPIN = ''; confirmPIN = ''; setupStep = 'enter'; if (subtitleEl) { subtitleEl.textContent = 'Choose an 8-digit Access PIN (not 12345678)'; } updatePinDisplay(); return; } try { const response = await chrome.runtime.sendMessage({ action: 'setNewPIN', newPin: pin }); if (!response?.success) { errorMessage.textContent = response?.error || 'Could not save Access PIN'; enteredPIN = ''; updatePinDisplay(); return; } await openMainPopupThenClose(); } catch (error) { errorMessage.textContent = 'Error saving PIN. Please try again.'; console.error('PIN setup error:', error); } return; } // Unlock mode — always verify via background (never client-only compare) if (!isValidAccessPin(pin) || isForbiddenAccessPin(pin)) { errorMessage.textContent = 'Invalid Access PIN'; enteredPIN = ''; updatePinDisplay(); return; } try { const response = await chrome.runtime.sendMessage({ action: 'verifyAccessPin', pin }); if (response?.success) { await openMainPopupThenClose(); } else { errorMessage.textContent = response?.error || 'Incorrect PIN. Please try again.'; enteredPIN = ''; updatePinDisplay(); errorMessage.style.animation = 'none'; setTimeout(() => { errorMessage.style.animation = 'shake 0.5s'; }, 10); } } catch (error) { errorMessage.textContent = 'Error verifying PIN. Please try again.'; console.error('PIN verification error:', error); } } });