personal memory agent
at main 88 lines 2.6 kB view raw
1// SPDX-License-Identifier: AGPL-3.0-only 2// Copyright (c) 2026 sol pbc 3 4/** 5 * Error Handler for App System 6 * Captures JavaScript errors and provides visual feedback 7 * 8 * Features: 9 * - Catches window errors and unhandled promise rejections 10 * - Adds error glow to status icon via .error class 11 * - Displays error log at bottom of viewport 12 * - Provides modal for manual error display via window.showError() 13 */ 14 15(function(){ 16 const statusIcon = document.querySelector('.facet-bar .status-icon'); 17 const errorLog = document.getElementById('error-log'); 18 const errorModal = document.getElementById('errorModal'); 19 const errorMessage = document.getElementById('errorMessage'); 20 const closeButton = errorModal ? errorModal.querySelector('.close') : null; 21 22 // Escape HTML to prevent XSS 23 function escapeHtml(text) { 24 return String(text).replace(/</g, '&lt;').replace(/>/g, '&gt;'); 25 } 26 27 // Log error to bottom panel 28 function logError(text) { 29 if (errorLog) { 30 if (!document.getElementById('error-log-dismiss')) { 31 var btn = document.createElement('button'); 32 btn.id = 'error-log-dismiss'; 33 btn.textContent = 'clear'; 34 btn.setAttribute('aria-label', 'dismiss error log'); 35 btn.onclick = function() { 36 errorLog.innerHTML = ''; 37 errorLog.style.display = 'none'; 38 }; 39 errorLog.insertAdjacentElement('afterbegin', btn); 40 } 41 errorLog.insertAdjacentHTML( 42 'beforeend', 43 escapeHtml(text) + '<br>' 44 ); 45 errorLog.style.display = 'block'; 46 } 47 } 48 49 // Mark status icon as error state (red with glow) 50 function markError() { 51 if (statusIcon) { 52 statusIcon.classList.add('error'); 53 } 54 } 55 56 // Global error handler 57 window.addEventListener('error', (e) => { 58 markError(); 59 logError(`${e.message} @ ${e.filename}:${e.lineno}`); 60 }); 61 62 // Unhandled promise rejection handler 63 window.addEventListener('unhandledrejection', (e) => { 64 markError(); 65 logError(`⚠️ Promise: ${e.reason}`); 66 }); 67 68 // Modal controls 69 if (errorModal && closeButton && errorMessage) { 70 // Provide global function for manual error display 71 window.showError = (text) => { 72 errorMessage.textContent = text; 73 errorModal.style.display = 'block'; 74 }; 75 76 // Close button 77 closeButton.onclick = () => { 78 errorModal.style.display = 'none'; 79 }; 80 81 // Click outside to close 82 window.addEventListener('click', (e) => { 83 if (e.target === errorModal) { 84 errorModal.style.display = 'none'; 85 } 86 }); 87 } 88})();