// ==========================================
// GLOBAL NOTIFICATION SYSTEM
// ==========================================
// Floating notification panel accessible from any view
/**
* Initialize global notification panel
*/
function initGlobalNotifications() {
// Create FAB and panel if not exists
if (!document.getElementById('globalNotificationFab')) {
const fabHtml = `
đ0
đ Notifications
No notifications
System events and task updates will appear here
`;
const container = document.createElement('div');
container.id = 'globalNotificationContainer';
container.innerHTML = fabHtml;
document.body.appendChild(container);
}
renderGlobalNotifications();
}
/**
* Toggle notification panel visibility
*/
function toggleGlobalNotifications() {
isNotificationPanelVisible = !isNotificationPanelVisible;
const panel = document.getElementById('globalNotificationPanel');
const fab = document.getElementById('globalNotificationFab');
if (panel && fab) {
if (isNotificationPanelVisible) {
panel.classList.add('show');
fab.classList.add('active');
} else {
panel.classList.remove('show');
fab.classList.remove('active');
}
}
}
/**
* Add a global notification
* @param {string} type - 'info', 'success', 'warning', 'error'
* @param {string} message - Main notification message
* @param {string} details - Optional details
* @param {string} source - Optional source identifier (e.g., 'explorer', 'mcp')
*/
function addGlobalNotification(type, message, details = null, source = null) {
const notification = {
id: Date.now(),
type,
message,
details,
source,
timestamp: new Date().toISOString(),
read: false
};
globalNotificationQueue.unshift(notification);
// Keep only last 100 notifications
if (globalNotificationQueue.length > 100) {
globalNotificationQueue = globalNotificationQueue.slice(0, 100);
}
renderGlobalNotifications();
updateGlobalNotifBadge();
// Show toast for important notifications
if (type === 'error' || type === 'success') {
showNotificationToast(notification);
}
}
/**
* Show a brief toast notification
*/
function showNotificationToast(notification) {
const typeIcon = {
'info': 'âšī¸',
'success': 'â ',
'warning': 'â ī¸',
'error': 'â'
}[notification.type] || 'âšī¸';
// Remove existing toast
const existing = document.querySelector('.notif-toast');
if (existing) existing.remove();
const toast = document.createElement('div');
toast.className = `notif-toast type-${notification.type}`;
toast.innerHTML = `
${typeIcon}${escapeHtml(notification.message)}
`;
document.body.appendChild(toast);
// Animate in
requestAnimationFrame(() => toast.classList.add('show'));
// Auto-remove
setTimeout(() => {
toast.classList.remove('show');
setTimeout(() => toast.remove(), 300);
}, 3000);
}
/**
* Render notification list
*/
function renderGlobalNotifications() {
const listEl = document.getElementById('globalNotificationList');
if (!listEl) return;
if (globalNotificationQueue.length === 0) {
listEl.innerHTML = `