From 74e5181b7e1a56361f65080c6801b4e79280206e Mon Sep 17 00:00:00 2001 From: mARTin-B78 Date: Fri, 29 May 2026 14:20:52 +0200 Subject: [PATCH] Fix conversation input bar hidden when mic is blocked - Move mic-blocked warning into conv-chat-window (prepend) so it scrolls with the chat instead of pushing the input bar off-screen - Remove min-height:400px from conv-chat-window; give conv-chat-panel a viewport-relative height so the input bar is always visible at the bottom - loader.js: append ?v= to section fetches to bust browser cache (was serving stale s-conversation.html after updates) Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 13 +++++++++++++ static/js/conversation.js | 6 ++++-- static/loader.js | 6 ++++-- static/style.css | 12 ++++++++---- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 274bd5c..03f98e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi ## [Unreleased] +### Fixed + +- **Conversation input bar hidden when mic unavailable** — the mic-blocked + warning box was inserted before `conv-chat-window` inside the flex column, + pushing the input bar off-screen. Fixed by prepending the warning inside + `conv-chat-window` so it scrolls with the chat and never affects the bar. +- **Chat panel overflow / missing input bar on smaller viewports** — removed + `min-height: 400px` from `conv-chat-window` (prevented shrinking) and gave + `conv-chat-panel` a viewport-relative height (`calc(100vh - 340px)`, + min 440px) so the input bar is always anchored at the bottom. +- **Browser caches old section HTML after updates** — `loader.js` now appends + `?v=` to every section fetch, busting the cache on each page load. + ### Added - **`scripts/release.py`** — automates version bump + CHANGELOG promotion. diff --git a/static/js/conversation.js b/static/js/conversation.js index 5c51d6b..1e36cd1 100644 --- a/static/js/conversation.js +++ b/static/js/conversation.js @@ -143,7 +143,7 @@ $('s-import-voices-file')?.addEventListener('change', async function () { } const flagsUrl = 'chrome://flags/#unsafely-treat-insecure-origin-as-secure'; const warn = document.createElement('div'); - warn.style.cssText = 'background:var(--red,#c00);color:#fff;padding:12px 16px;border-radius:8px;margin:12px 0;font-size:13px;line-height:1.7'; + warn.style.cssText = 'background:var(--red,#c00);color:#fff;padding:12px 16px;border-radius:8px;margin:0 0 12px;font-size:13px;line-height:1.7;flex-shrink:0'; warn.innerHTML = '⚠ Microphone blocked by browser
' + 'Browsers only allow microphone access on secure contexts (HTTPS or localhost).
' + @@ -154,7 +154,9 @@ $('s-import-voices-file')?.addEventListener('change', async function () { `' + ''; - chatWindow && chatWindow.parentElement && chatWindow.parentElement.insertBefore(warn, chatWindow); + // Insert inside the chat window so it scrolls with the conversation and + // never pushes the input bar off-screen. + if (chatWindow) chatWindow.prepend(warn); } // Restore conv LLM URL from server settings diff --git a/static/loader.js b/static/loader.js index 1c82c3a..2499f7d 100644 --- a/static/loader.js +++ b/static/loader.js @@ -13,10 +13,12 @@ }); } - // 1. Fetch all section partials in parallel and inject into their shells + // 1. Fetch all section partials in parallel and inject into their shells. + // ?v= busts the browser cache so updated HTML is always used. + var _v = Date.now(); await Promise.all(SECTIONS.map(async function (id) { try { - var res = await fetch('/static/sections/' + id + '.html'); + var res = await fetch('/static/sections/' + id + '.html?v=' + _v); if (!res.ok) throw new Error(res.status + ' ' + res.statusText); var html = await res.text(); var el = document.getElementById(id); diff --git a/static/style.css b/static/style.css index afb9b1d..56afb7d 100644 --- a/static/style.css +++ b/static/style.css @@ -2028,12 +2028,16 @@ code { background: var(--panel); border-radius: 4px; padding: 1px 5px; font-fami .conv-system-textarea { flex: 1; resize: vertical; min-height: 34px; max-height: 120px; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 13px; font-family: var(--font); background: var(--surface); color: var(--text); } /* Layout */ -.conv-main { display: flex; gap: 14px; margin-top: 14px; min-height: 520px; } -.conv-chat-panel { flex: 1; display: flex; flex-direction: column; gap: 0; min-width: 0; } +.conv-main { display: flex; gap: 14px; margin-top: 14px; } +/* Chat panel: fixed height so the input bar never gets pushed off-screen */ +.conv-chat-panel { + flex: 1; display: flex; flex-direction: column; gap: 0; min-width: 0; + height: calc(100vh - 340px); min-height: 440px; +} .conv-stats-panel { width: 280px; flex-shrink: 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; display: flex; flex-direction: column; gap: 8px; } -/* Chat window */ -.conv-chat-window { flex: 1; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius) var(--radius) 0 0; padding: 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; min-height: 400px; } +/* Chat window fills the space above the input bar; warning box scrolls inside it */ +.conv-chat-window { flex: 1; min-height: 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius) var(--radius) 0 0; padding: 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; } .conv-chat-welcome { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; flex: 1; color: var(--subtext); text-align: center; } /* Bubbles */