[object Object]

← back to Desktop Dotbar

dotbar: surface Arrange outcome on the button instead of swallowing errors

534bea84c634e89aacfa96e7a6fce5bf25040f5e · 2026-09-16 11:54:30 -0700 · Steve Abrams

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtzMyVz6sH79QSHLZzQMEZ

Files touched

Diff

commit 534bea84c634e89aacfa96e7a6fce5bf25040f5e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 16 11:54:30 2026 -0700

    dotbar: surface Arrange outcome on the button instead of swallowing errors
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01MtzMyVz6sH79QSHLZzQMEZ
---
 public/index.html | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/public/index.html b/public/index.html
index 8951a88..68758cd 100644
--- a/public/index.html
+++ b/public/index.html
@@ -75,7 +75,7 @@
   <div id="panel"></div>
 <script>
 const BAR_H = 48, PANEL_H = 360;
-let openColor = null, data = null, _miss = 0, curBarH = BAR_H, arranging = false;
+let openColor = null, data = null, _miss = 0, curBarH = BAR_H, arranging = false, arrangeMsg = '';
 // The four needs-Steve states pulse; green/pink stay solid (Steve 2026-09-15 dot-flash directive).
 const WAIT = new Set(['lightblue','orange','purple','yellow']);
 
@@ -101,7 +101,7 @@ function renderBar(){
   }
   const sp = document.createElement('div'); sp.id='spacer'; bar.appendChild(sp);
   const meta = document.createElement('div'); meta.id='meta';
-  meta.innerHTML = `<button class="arrbtn${arranging?' busy':''}" title="re-tile every screen into the grid now" onclick="arrange()">${arranging?'⧉ Arranging…':'⧉ Arrange'}</button>`
+  meta.innerHTML = `<button class="arrbtn${arranging?' busy':''}" title="re-tile every screen into the grid now" onclick="arrange()">${arranging?'⧉ Arranging…':(arrangeMsg?('⧉ '+arrangeMsg):'⧉ Arrange')}</button>`
     + `<span><b>${data.total}</b> live</span>`
     + `<span class="icobtn" title="refresh" onclick="tick()">⟳</span>`
     + `<span class="icobtn" title="quit bar" onclick="(window.dotbar&&window.dotbar.quit)&&window.dotbar.quit()">✕</span>`;
@@ -141,9 +141,18 @@ async function reveal(tty){
 // into the grid. Shows a busy state on the button until the (multi-pass, converging) run returns.
 async function arrange(){
   if (arranging) return;
-  arranging = true; renderBar();
-  try { await fetch('/api/arrange', { method:'POST' }); } catch(e){}
-  arranging = false; renderBar();
+  arrangeMsg = ''; arranging = true; renderBar();
+  // Surface the outcome on the button instead of swallowing it — an invisible failure (the old
+  // `catch(e){}`) is exactly why "the button does nothing" was undiagnosable. Show moved-count on
+  // success, or the server err / HTTP status / "no server" on failure.
+  let msg;
+  try {
+    const r = await fetch('/api/arrange', { method:'POST' });
+    const j = await r.json().catch(() => null);
+    msg = (j && j.ok) ? `moved ${j.moved || 0}` : ('✗ ' + ((j && j.err) || ('HTTP ' + r.status)));
+  } catch (e) { msg = '✗ ' + ((e && e.message) || 'no server'); }
+  arranging = false; arrangeMsg = msg; renderBar();
+  clearTimeout(window._arrTimer); window._arrTimer = setTimeout(() => { arrangeMsg = ''; renderBar(); }, 2200);
   tick();   // refresh counts/labels once windows have settled
 }
 

← 2f67aa2 dotbar: render a strip on EVERY display (Arrange button reac  ·  back to Desktop Dotbar  ·  wire arrange bar to master router 8db4601 →