From 95f24a4e9047739e8b19fa16ff13a7534568367d Mon Sep 17 00:00:00 2001 From: timmy Date: Wed, 12 Aug 2026 09:52:41 +0000 Subject: [PATCH] feat: expose Updates in mobile queues (Closes #639) --- frontend/index.html | 1 + frontend/mobile-task-dock.js | 9 +++++++-- tests/test_mobile_task_dock.py | 15 ++++++++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index 1401d4f..5da019f 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -861,6 +861,7 @@
+
diff --git a/frontend/mobile-task-dock.js b/frontend/mobile-task-dock.js index 12f4a50..022d50d 100644 --- a/frontend/mobile-task-dock.js +++ b/frontend/mobile-task-dock.js @@ -95,12 +95,17 @@ } function updateQueues(counts) { - const names = ['today', 'attention', 'later', 'draft']; + const names = ['today', 'attention', 'update', 'later', 'draft']; const normalized = Object.fromEntries(names.map(name => [name, Math.max(0, Number(counts?.[name]) || 0)])); - const total = names.reduce((sum, name) => sum + normalized[name], 0); + // Updates are already represented by the Attention destination, so keep + // the dock aggregate non-overlapping while exposing the useful drill-down. + const total = ['today', 'attention', 'later', 'draft'].reduce((sum, name) => sum + normalized[name], 0); Object.entries(options.queueCounts || {}).forEach(([name, element]) => { element.textContent = String(normalized[name] || 0); }); + options.queueRows?.update?.setAttribute( + 'aria-label', 'Updates, ' + normalized.update + ' unread conversations' + ); if (options.queueBadge) { options.queueBadge.textContent = String(total); options.queueBadge.hidden = total === 0; diff --git a/tests/test_mobile_task_dock.py b/tests/test_mobile_task_dock.py index 38283d7..0e88dfd 100644 --- a/tests/test_mobile_task_dock.py +++ b/tests/test_mobile_task_dock.py @@ -292,7 +292,7 @@ sheet.showModal = function () {{ this.open = true; }}; sheet.close = function () {{ this.open = false; this.listeners.close?.(); }}; const close = new FakeElement(); const badge = new FakeElement(); -const rows = Object.fromEntries(['today','attention','later','draft'].map(name => [name, new FakeElement()])); +const rows = Object.fromEntries(['today','attention','update','later','draft'].map(name => [name, new FakeElement()])); const counts = Object.fromEntries(Object.keys(rows).map(name => [name, new FakeElement()])); const selected = []; const dock = createDock({{ @@ -302,16 +302,17 @@ const dock = createDock({{ observe() {{}}, }}); dock.start(); -dock.updateQueues({{today:2, attention:1, later:3, draft:4}}); +dock.updateQueues({{today:2, attention:1, update:5, later:3, draft:4}}); queues.click(); const opened = sheet.open; -rows.later.click(); +rows.update.click(); const closedAfterSelect = !sheet.open; queues.click(); close.click(); process.stdout.write(JSON.stringify({{ opened, closedAfterSelect, selected, badge:badge.textContent, badgeLabel:queues.attributes['aria-label'], counts:Object.fromEntries(Object.entries(counts).map(([name, node]) => [name, node.textContent])), + updateLabel:rows.update.attributes['aria-label'], queueFocuses:queues.focuses, columnState:nav.attributes['data-attention'] || null, }})); @@ -322,10 +323,12 @@ process.stdout.write(JSON.stringify({{ assert json.loads(result.stdout) == { "opened": True, "closedAfterSelect": True, - "selected": ["later"], + "selected": ["update"], + # Updates are a drill-down within Attention and must not inflate the aggregate badge. "badge": "10", "badgeLabel": "Queues, 10 items", - "counts": {"today": "2", "attention": "1", "later": "3", "draft": "4"}, + "counts": {"today": "2", "attention": "1", "update": "5", "later": "3", "draft": "4"}, + "updateLabel": "Updates, 5 unread conversations", "queueFocuses": 2, "columnState": None, } @@ -340,6 +343,8 @@ async def test_dashboard_renders_and_wires_mobile_queue_switcher(): assert 'aria-labelledby="mobile-queue-heading"' in html assert 'data-mobile-queue="today"' in html assert 'data-mobile-queue="attention"' in html + assert 'data-mobile-queue="update"' in html + assert 'UpdatesUnread conversations' in html assert 'data-mobile-queue="later"' in html assert 'data-mobile-queue="draft"' in html assert 'id="mobile-queue-count"' in html -- 2.43.0