From 7cee1d504f9530a5362685eb80bebbf9142ad3c8 Mon Sep 17 00:00:00 2001 From: Rolando Santamaria Maso Date: Sun, 26 Jul 2026 14:46:32 +0200 Subject: [PATCH] =?UTF-8?q?feat(ui):=20WebUI=20modernization=20PR4=20?= =?UTF-8?q?=E2=80=94=20completion=20keyboard=20nav,=20attachments,=20sideb?= =?UTF-8?q?ar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fourth PR of the WebUI modernization roadmap (Phase 2c + 2d). Stacked on #111 (feat/webui-modernization-3). Input & @-completion (2c): - ArrowUp/ArrowDown move the selection (with wrap-around), Enter/Tab accept, Esc dismisses. Previously mouse-only with Tab-to-accept, and Enter would send the prompt even with the popup open. - role="listbox"/role="option" + aria-selected kept in sync for keyboard, mouse, and hover selection. - Attachments: per-file error chips (oversized/unreadable/over the 10 MB total cap) that dismiss on click or after 6s, replacing toast-only errors; total-size meter ("1.2 MB / 10 MB", amber when above 8 MB) rendered next to the chips. Sessions sidebar (2d): - Session items restructured: the whole body is a real + + + + + ` + ).join(''); + } catch { + sessionListEl.querySelectorAll('.session-skel').forEach(el => el.remove()); + } +} // ── Session history rendering ── // Renders the full persisted transcript on session load: user/assistant @@ -2092,30 +2245,6 @@ sidebarSearch.addEventListener('input', () => { }); }); -async function loadSessions() { - try { - const resp = await fetch('/api/sessions', { headers: apiHeaders() }); - const sessions = await resp.json(); - if (!sessions || !Array.isArray(sessions)) return; - allSessions = sessions; - - sessionListEl.innerHTML = sessions.map(s => - `
-
-
${escapeHtml(s.id.slice(0, 8))}
- - -
-
${escapeHtml(s.task || 'untitled')}
-
- ${s.turns || 0} turn${s.turns !== 1 ? 's' : ''}${relativeTime(s.updated_at)} - ${s.model ? `${escapeHtml(s.model)}` : ''} -
-
` - ).join(''); - } catch { /* ignore */ } -} - // ── Init ── // Save references so newSession() can restore the empty state after clearing. savedEmptyStateNode = document.getElementById('empty-state'); diff --git a/cmd/odek/ui/index.html b/cmd/odek/ui/index.html index d3a14ef..dfc25ed 100644 --- a/cmd/odek/ui/index.html +++ b/cmd/odek/ui/index.html @@ -76,7 +76,7 @@

Sessions

-
+