// Search Chat Module — Ctrl+K command palette for searching conversations import uiModule from './ui.js?v=20260908weekhoverfix1'; import sessionModule from './sessions.js'; let API_BASE = ''; let debounceTimer = null; let selectedIndex = -1; let results = []; function el(id) { return document.getElementById(id); } function hideMobileSidebarForSearch() { if (window.innerWidth >= 768) return; const sidebar = el('sidebar'); const rail = el('icon-rail'); const backdrop = el('sidebar-backdrop'); let changed = false; if (sidebar && !sidebar.classList.contains('hidden')) { sidebar.classList.add('hidden'); changed = true; } if (rail && rail.classList.contains('mobile-mini')) { rail.classList.remove('mobile-mini'); rail.style.cssText = ''; changed = true; } if (backdrop) backdrop.classList.remove('visible'); if (changed && typeof window.syncRailSide === 'function') { try { window.syncRailSide(); } catch (_) {} } } export function openSearch() { hideMobileSidebarForSearch(); const overlay = el('search-overlay'); if (!overlay) return; // Freeze the opening offset before focus summons the mobile keyboard. // A live `vh` value shrinks during the keyboard animation and visibly // pulls the search popup upward even though it is already unobscured. const openingHeight = window.innerHeight || document.documentElement.clientHeight; const openingTop = Math.max(56, Math.min(140, Math.round(openingHeight * 0.15))); overlay.style.setProperty('--search-overlay-top', `${openingTop}px`); overlay.classList.remove('hidden'); const input = el('search-input'); if (input) { input.value = ''; input.focus(); } selectedIndex = -1; results = []; el('search-results').innerHTML = ''; } export function closeSearch() { const overlay = el('search-overlay'); if (!overlay) return; overlay.classList.add('hidden'); el('search-results').innerHTML = ''; selectedIndex = -1; results = []; } export function isOpen() { const overlay = el('search-overlay'); return overlay && !overlay.classList.contains('hidden'); } var escapeHtml = uiModule.esc; function highlightMatch(text, query) { if (!query) return escapeHtml(text); const escaped = escapeHtml(text); const regex = new RegExp('(' + query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ')', 'gi'); return escaped.replace(regex, '$1'); } function formatTimestamp(iso) { if (!iso) return ''; const d = new Date(iso); const now = new Date(); const diff = now - d; if (diff < 86400000) { return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); } if (diff < 604800000) { return d.toLocaleDateString([], { weekday: 'short', hour: '2-digit', minute: '2-digit' }); } return d.toLocaleDateString([], { month: 'short', day: 'numeric', year: 'numeric' }); } function renderResults(data, query) { results = data; selectedIndex = -1; const container = el('search-results'); if (!container) return; if (!data || data.length === 0) { container.innerHTML = query ? '