From d34c082da2e9b41f4824bedb94e5f33fe19eb0ef Mon Sep 17 00:00:00 2001 From: timmy Date: Thu, 13 Aug 2026 13:53:04 +0000 Subject: [PATCH] fix: make mobile queue summary truthful (Closes #743) --- frontend/dashboard.css | 2 +- frontend/index.html | 2 +- frontend/mobile-task-dock.js | 21 ++++++++++++++------- tests/test_mobile_task_dock.py | 31 ++++++++++++++++++++++++++----- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/frontend/dashboard.css b/frontend/dashboard.css index 52140ef..a41cf2d 100644 --- a/frontend/dashboard.css +++ b/frontend/dashboard.css @@ -605,7 +605,7 @@ textarea { resize: vertical; min-height: 120px; } .mobile-task-action { min-width:0; min-height:44px; padding:6px 2px; border:0; border-radius:8px; background:transparent; display:grid; place-items:center; gap:2px; font-size:12px; } .mobile-task-action[hidden] { display:none; } .mobile-task-action[aria-current="page"] { color:#bfdbfe; background:#17365a; outline:1px solid #31577f; } -.mobile-task-count { min-width:18px; min-height:18px; padding:1px 5px; border-radius:999px; background:#31577f; font-size:11px; line-height:16px; } +.mobile-task-count { min-width:18px; min-height:18px; max-width:100%; padding:1px 5px; border-radius:999px; background:#31577f; font-size:10px; line-height:16px; white-space:nowrap; } .mobile-task-deadline { padding:1px 5px; border-radius:999px; color:#fef3c7; background:#92400e; font-size:10px; line-height:14px; } .attention-interruption:not([hidden]) { max-width:100%; display:flex; align-items:center; justify-content:space-between; gap:10px; margin:0 0 12px; padding:10px 12px; border:1px solid #31577f; border-radius:10px; background:#102641; } .attention-interruption button { min-height:44px; flex:0 0 auto; } diff --git a/frontend/index.html b/frontend/index.html index 177116b..9d66e5c 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -987,7 +987,7 @@ - + diff --git a/frontend/mobile-task-dock.js b/frontend/mobile-task-dock.js index e305b30..6c34588 100644 --- a/frontend/mobile-task-dock.js +++ b/frontend/mobile-task-dock.js @@ -97,7 +97,8 @@ function updateQueues(counts) { const names = 'today agenda attention update later draft'.split(' '); const normalized = Object.fromEntries(names.map(name => [name, Math.max(0, Number(counts?.[name]) || 0)])); - const total = ['today', 'attention', 'later', 'draft'].reduce((sum, name) => sum + normalized[name], 0); + const actionableNames = ['today', 'attention', 'update', 'later', 'draft']; + const active = actionableNames.reduce((total, name) => total + (normalized[name] > 0 ? 1 : 0), 0); Object.entries(options.queueCounts || {}).forEach(([name, element]) => { element.textContent = String(normalized[name] || 0); }); @@ -105,8 +106,8 @@ 'aria-label', 'Updates, ' + normalized.update + ' unread conversations' ); if (options.queueBadge) { - options.queueBadge.textContent = String(total); - options.queueBadge.hidden = total === 0; + options.queueBadge.textContent = active + ' active'; + options.queueBadge.hidden = active === 0; } if (options.deadlineBadge) { options.deadlineBadge.textContent = normalized.agenda + ' due'; @@ -116,10 +117,16 @@ if (normalized.agenda > 0) options.queueRows.agenda.setAttribute('data-deadlines', 'true'); else options.queueRows.agenda.removeAttribute('data-deadlines'); } - const deadlineLabel = normalized.agenda > 0 - ? ', ' + normalized.agenda + ' upcoming deadlines' - : ''; - buttons.queues?.setAttribute('aria-label', 'Queues, ' + total + ' items' + deadlineLabel); + const label = active === 0 && normalized.agenda === 0 + ? 'Queues: no active queues; no upcoming deadlines' + : 'Queues: Today ' + normalized.today + + ', Agenda ' + normalized.agenda + ' due' + + ', Attention ' + normalized.attention + + ', Updates ' + normalized.update + + ', Later ' + normalized.later + + ', Drafts ' + normalized.draft + + '; ' + active + ' active ' + (active === 1 ? 'queue' : 'queues'); + buttons.queues?.setAttribute('aria-label', label); } return {start, select, refreshVisibility, updateAttention, updateQueues, updateWork}; diff --git a/tests/test_mobile_task_dock.py b/tests/test_mobile_task_dock.py index 2eb40e6..f5d1972 100644 --- a/tests/test_mobile_task_dock.py +++ b/tests/test_mobile_task_dock.py @@ -314,14 +314,22 @@ queues.click(); rows.recaps.click(); const closedAfterUtility = !sheet.open; queues.click(); close.click(); const populated = {{ + badge:badge.textContent, badgeHidden:badge.hidden, deadline:deadline.textContent, deadlineHidden:deadline.hidden, agendaDue:rows.agenda.attributes['data-deadlines'] || null, badgeLabel:queues.attributes['aria-label'], }}; +dock.updateQueues({{today:0, agenda:0, attention:0, update:7, later:0, draft:0}}); +const updatesOnly = {{ + badge:badge.textContent, badgeHidden:badge.hidden, + deadlineHidden:deadline.hidden, + badgeLabel:queues.attributes['aria-label'], +}}; dock.updateQueues({{today:0, agenda:0, attention:0, update:0, later:0, draft:0}}); process.stdout.write(JSON.stringify({{ opened, closedAfterSelect, closedAfterUtility, selected, utilities, - badge:badge.textContent, populated, + badge:badge.textContent, populated, updatesOnly, + clearedBadgeHidden:badge.hidden, clearedDeadlineHidden:deadline.hidden, clearedAgendaDue:rows.agenda.attributes['data-deadlines'] || null, clearedBadgeLabel:queues.attributes['aria-label'], @@ -340,12 +348,25 @@ process.stdout.write(JSON.stringify({{ "closedAfterUtility": True, "selected": ["update"], "utilities": ["recaps:trigger"], - # Updates are a drill-down within Attention and must not inflate the aggregate badge. - "badge": "0", - "populated": {"badgeLabel": "Queues, 10 items, 5 upcoming deadlines", "deadline": "5 due", "deadlineHidden": False, "agendaDue": "true"}, + "badge": "0 active", + "populated": { + "badge": "5 active", + "badgeHidden": False, + "badgeLabel": "Queues: Today 2, Agenda 5 due, Attention 1, Updates 5, Later 3, Drafts 4; 5 active queues", + "deadline": "5 due", + "deadlineHidden": False, + "agendaDue": "true", + }, + "updatesOnly": { + "badge": "1 active", + "badgeHidden": False, + "deadlineHidden": True, + "badgeLabel": "Queues: Today 0, Agenda 0 due, Attention 0, Updates 7, Later 0, Drafts 0; 1 active queue", + }, + "clearedBadgeHidden": True, "clearedDeadlineHidden": True, "clearedAgendaDue": None, - "clearedBadgeLabel": "Queues, 0 items", + "clearedBadgeLabel": "Queues: no active queues; no upcoming deadlines", "counts": {"today": "0", "agenda": "0", "attention": "0", "update": "0", "later": "0", "draft": "0", "recaps": "0"}, "updateLabel": "Updates, 0 unread conversations", "queueFocuses": 3, -- 2.43.0