diff --git a/api/endpoints/history.php b/api/endpoints/history.php
new file mode 100644
index 0000000..a710072
--- /dev/null
+++ b/api/endpoints/history.php
@@ -0,0 +1,21 @@
+ [], 'error' => 'Query too short']);
+ exit;
+}
+
+$rows = JarvisDB::query(
+ "SELECT role, content, created_at FROM conversations
+ WHERE content LIKE ? ORDER BY created_at DESC LIMIT 25",
+ ['%' . $q . '%']
+) ?? [];
+
+echo json_encode(['results' => $rows, 'total' => count($rows)]);
diff --git a/public_html/api.php b/public_html/api.php
index 577c36b..49afe8b 100644
--- a/public_html/api.php
+++ b/public_html/api.php
@@ -72,6 +72,7 @@ $endpoints = [
'agent' => 'agent.php',
'planner' => 'planner.php',
'jellyfin' => 'jellyfin.php',
+ 'history' => 'history.php',
'arc' => 'arc.php',
'directives' => 'directives.php',
'memory' => 'memory.php',
diff --git a/public_html/index.html b/public_html/index.html
index 57d59ec..9e627b8 100644
--- a/public_html/index.html
+++ b/public_html/index.html
@@ -301,11 +301,39 @@ body::after{
#mainLayout.swapped.focus-mode #rightPanel{transform:translateX(-20px)}
#btn-swap-panels{background:none;border:1px solid var(--panel-border);color:var(--text-dim);padding:3px 8px;cursor:pointer;font-family:var(--font-mono);font-size:0.6rem;letter-spacing:1px;transition:all 0.2s}
#btn-swap-panels:hover,#btn-swap-panels.active{color:var(--cyan);border-color:var(--cyan)}
-/* Mobile fallback */
+/* ── MOBILE RESPONSIVE ──────────────────────────────────────────────── */
@media(max-width:900px){
- #mainLayout{grid-template-columns:1fr;grid-template-rows:auto}
+ #mainLayout{grid-template-columns:1fr!important;grid-template-rows:1fr!important;padding:6px;gap:6px}
#leftPanel,#rightPanel{display:none}
+ #leftPanel.mob-active,#rightPanel.mob-active{display:flex!important;flex-direction:column}
+ #centerPanel{display:none}
+ #centerPanel.mob-active{display:flex!important;flex-direction:column}
+ #topBar{padding:0 10px;height:42px}
+ .tb-center{display:none}
+ .tb-logo{font-size:0.85rem;letter-spacing:2px}
+ #clock{font-size:0.85rem}
+ #date-display{display:none}
+ #btn-swap-panels,.btn-panels{display:none}
+ #inputArea{padding:8px 6px}
+ #textInput{font-size:0.85rem;padding:8px 10px;min-height:40px}
+ #sendBtn{min-height:40px;padding:0 14px;font-size:0.65rem}
+ #micBtn{min-height:40px;min-width:40px;font-size:1.1rem}
+ #app{padding-bottom:48px}
+ #mobileNav{display:flex!important}
}
+@media(min-width:901px){#mobileNav{display:none!important}}
+#mobileNav{
+ display:none;position:fixed;bottom:0;left:0;right:0;z-index:100;
+ background:rgba(0,8,22,0.96);border-top:1px solid var(--panel-border);height:48px;
+}
+.mob-nav-btn{
+ flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
+ font-family:var(--font-display);font-size:0.5rem;letter-spacing:1.5px;
+ color:var(--text-dim);cursor:pointer;gap:2px;border:none;background:none;transition:color 0.2s;
+}
+.mob-nav-btn .mob-icon{font-size:1rem;line-height:1}
+.mob-nav-btn.active{color:var(--cyan)}
+.mob-nav-btn.active .mob-icon{filter:drop-shadow(0 0 4px var(--cyan))}
/* Panel toggle button */
.btn-panels{
background:rgba(0,212,255,0.06);
@@ -1210,6 +1238,7 @@ body::after{
+
@@ -1283,6 +1312,13 @@ body::after{
@@ -2547,6 +2583,7 @@ function showApp(name, greeting, silent = false) {
loadAlerts();
loadWeather();
loadNews();
+ initMobile();
// Guardian Mode — badge refresh + proactive chat
setTimeout(() => {
_refreshGuardianBadge();
@@ -3231,6 +3268,17 @@ async function loadWeather() {
}
// ── NEWS ──────────────────────────────────────────────────────────────
+function getNewsHidden() {
+ try { return JSON.parse(localStorage.getItem('news_hidden_cats') || '[]'); } catch(e) { return []; }
+}
+function setNewsHidden(arr) { localStorage.setItem('news_hidden_cats', JSON.stringify(arr)); }
+
+function toggleNewsFilter() {
+ const panel = document.getElementById('news-filter-panel');
+ panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
+}
+
+let _newsCats = [];
async function loadNews() {
const d = await api('news');
const el = document.getElementById('news-list');
@@ -3238,10 +3286,24 @@ async function loadNews() {
el.innerHTML = '
News loading...
';
return;
}
- const catLabels = { headlines: '📰 TOP HEADLINES', technology: '💻 TECHNOLOGY' };
+ const catLabels = { headlines: '📰 TOP HEADLINES', technology: '💻 TECHNOLOGY', pinned: '📌 JARVIS PINNED' };
+ const hidden = getNewsHidden();
+ _newsCats = Object.keys(d.categories);
+
+ // Build filter checkboxes
+ const cbContainer = document.getElementById('news-filter-checkboxes');
+ if (cbContainer) {
+ cbContainer.innerHTML = _newsCats.map(cat => `
+
`).join('');
+ }
+
let html = '';
for (const [cat, articles] of Object.entries(d.categories)) {
- if (!articles.length) continue;
+ if (!articles.length || hidden.includes(cat)) continue;
html += ``;
for (const a of articles.slice(0, 5)) {
const ctxKey = 'news_' + (cat + '_' + a.title).replace(/[^a-z0-9]/gi,'').slice(0,30);
@@ -3254,11 +3316,24 @@ async function loadNews() {
`;
}
}
+ if (!html) html = 'All categories hidden — use ⚙ to show sources
';
const ageMin = d.cache_age_s > 0 ? Math.round(d.cache_age_s/60) : 0;
html += `Updated ${ageMin}m ago
`;
el.innerHTML = html;
}
+function toggleNewsCat(cat, show) {
+ const hidden = getNewsHidden();
+ if (show) {
+ const idx = hidden.indexOf(cat);
+ if (idx > -1) hidden.splice(idx, 1);
+ } else {
+ if (!hidden.includes(cat)) hidden.push(cat);
+ }
+ setNewsHidden(hidden);
+ loadNews();
+}
+
// ── TABS ──────────────────────────────────────────────────────────────
function switchTab(name) {
if (name === 'sites') { openSitesModal(); return; }
@@ -4996,6 +5071,68 @@ document.addEventListener('keydown', e => {
if (e.key === 'Escape') closeVisionLightbox();
});
+// ── CHAT HISTORY SEARCH ───────────────────────────────────────────────────────
+function openSearchModal() {
+ document.getElementById('searchModal').style.display = 'flex';
+ document.getElementById('searchInput').focus();
+}
+function closeSearchModal() {
+ document.getElementById('searchModal').style.display = 'none';
+ document.getElementById('searchResults').innerHTML = 'Type to search your JARVIS conversations
';
+ document.getElementById('searchInput').value = '';
+}
+async function runSearch() {
+ const q = document.getElementById('searchInput').value.trim();
+ if (!q) return;
+ const el = document.getElementById('searchResults');
+ el.innerHTML = 'Searching...
';
+ try {
+ const d = await api('history?q=' + encodeURIComponent(q));
+ if (!d.results || !d.results.length) {
+ el.innerHTML = 'No results for "' + q + '"
';
+ return;
+ }
+ el.innerHTML = d.results.map(r => {
+ const role = r.role === 'user' ? '👤' : '🤖';
+ const ts = new Date(r.created_at).toLocaleString('en-US', {month:'short',day:'numeric',hour:'2-digit',minute:'2-digit'});
+ const snippet = r.content.length > 200 ? r.content.slice(0,197) + '…' : r.content;
+ return `
+
+ ${role} ${r.role.toUpperCase()}
+ ${ts}
+
+
${snippet.replace(/
+
`;
+ }).join('');
+ } catch(e) {
+ el.innerHTML = '
Search failed
';
+ }
+}
+document.getElementById('searchModal')?.addEventListener('click', e => {
+ if (e.target === document.getElementById('searchModal')) closeSearchModal();
+});
+
+// ── MOBILE PANEL SWITCHER ─────────────────────────────────────────────────────
+function mobSwitch(which) {
+ if (window.innerWidth > 900) return;
+ const panels = {left:'leftPanel', center:'centerPanel', right:'rightPanel'};
+ Object.entries(panels).forEach(([k, id]) => {
+ document.getElementById(id)?.classList.toggle('mob-active', k === which);
+ });
+ document.querySelectorAll('.mob-nav-btn').forEach(b => b.classList.remove('active'));
+ document.getElementById('mob-btn-' + which)?.classList.add('active');
+ if (which === 'right') loadNews();
+}
+function initMobile() {
+ if (window.innerWidth > 900) return;
+ ['leftPanel','centerPanel','rightPanel'].forEach(id =>
+ document.getElementById(id)?.classList.remove('mob-active'));
+ document.getElementById('leftPanel')?.classList.add('mob-active');
+ document.querySelectorAll('.mob-nav-btn').forEach(b => b.classList.remove('active'));
+ document.getElementById('mob-btn-left')?.classList.add('active');
+}
+window.addEventListener('resize', initMobile);
+
@@ -5009,5 +5146,35 @@ document.addEventListener('keydown', e => {
+
+
+
+
+
◈ CHAT HISTORY SEARCH
+
+
+
+
+
+
+
+
Type to search your JARVIS conversations
+
+
+
+
+