From 07235d3870143f5f0df9e4150863eadc279fcc73 Mon Sep 17 00:00:00 2001 From: timmy Date: Wed, 12 Aug 2026 02:54:44 +0000 Subject: [PATCH] feat: make mobile New capture-first (Closes #613) --- frontend/dashboard.css | 6 +++++- frontend/dashboard.js | 23 +++++++++++++++++++++-- frontend/index.html | 22 ++++++++++++++-------- tests/test_unfiled_captures.py | 18 +++++++++++++++++- 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/frontend/dashboard.css b/frontend/dashboard.css index 4a1cb5b..eb1e9a2 100644 --- a/frontend/dashboard.css +++ b/frontend/dashboard.css @@ -449,8 +449,12 @@ textarea { resize: vertical; min-height: 120px; } .create-issue-sheet.open { display:flex; } .create-issue-panel { width:min(560px,100%); height:100dvh; overflow:auto; overflow-x:hidden; display:grid; align-content:start; gap:12px; padding:18px; padding-bottom:calc(18px + env(safe-area-inset-bottom)); background:#0b1526; border-left:1px solid #2a496e; } .create-issue-header { display:flex; align-items:center; justify-content:space-between; gap:10px; } -.create-issue-header button, .create-issue-actions button { min-height:44px; } +.create-issue-header button, .create-issue-actions button, .create-issue-capture-actions button { min-height:44px; } .create-issue-form { display:grid; gap:12px; } +.create-issue-capture-actions { position:sticky; bottom:0; display:grid; grid-template-columns:1fr 1fr; gap:8px; padding:10px 0; padding-bottom:calc(10px + env(safe-area-inset-bottom)); background:#0b1526; } +.create-issue-capture-actions[hidden] { display:none; } +.create-issue-filing { display:grid; gap:12px; min-width:0; } +.create-issue-filing[hidden] { display:none; } .create-issue-attachment { display:grid; gap:8px; min-width:0; } .create-issue-repository-more { min-height:44px; width:100%; } .create-issue-repository-picker { min-width:0; display:grid; gap:8px; } diff --git a/frontend/dashboard.js b/frontend/dashboard.js index 3f618ca..c190255 100644 --- a/frontend/dashboard.js +++ b/frontend/dashboard.js @@ -3217,6 +3217,8 @@ qs('#create-issue-repository-results').hidden = true; qs('#create-issue-title').value = captureDraft.title; qs('#create-issue-body').value = captureDraft.body; + setIssueFilingMode(Boolean(captureDraft.repository)); + qs('#create-issue-capture-status').textContent = ''; qs('#create-issue-due-date').value = captureDraft.dueDate || ''; loadIssueLabels(qs('#create-issue-repository').value, captureDraft.labelIds); loadIssueMilestones(qs('#create-issue-repository').value, captureDraft.milestoneId); @@ -3225,7 +3227,13 @@ updateIssueCreateActions(); qs('#create-issue-sheet').classList.add('open'); creatingIssue = true; - (captureDraft.repository ? qs('#create-issue-title') : qs('#create-issue-repository-search')).focus(); + qs('#create-issue-title').focus(); + } + + function setIssueFilingMode(enabled) { + qs('#create-issue-filing').hidden = !enabled; + qs('.create-issue-capture-actions').hidden = enabled; + qs('#create-issue-heading').textContent = enabled ? 'File issue' : 'Capture work'; } let suppressCreateDraftOnHistoryClose = false; @@ -4038,6 +4046,17 @@ } }); qs('#new-issue').addEventListener('click', openCreateIssueSheet); + qs('#file-new-issue').addEventListener('click', () => { + if (!qs('#create-issue-title').value.trim()) { + qs('#create-issue-capture-status').textContent = 'Add a title before filing.'; + qs('#create-issue-title').focus(); + return; + } + saveIssueCaptureDraft(); + setIssueFilingMode(true); + qs('#create-issue-capture-status').textContent = ''; + qs('#create-issue-repository-search').focus(); + }); qs('#save-unfiled-issue').addEventListener('click', () => { const captureDraft = { title: qs('#create-issue-title').value.trim(), @@ -4052,7 +4071,7 @@ refreshMyWorkView(); qs('#my-work-action-status').textContent = 'Saved in Drafts · choose a repository after reconnecting.'; } catch (error) { - qs('#create-issue-status').textContent = error.message; + qs('#create-issue-capture-status').textContent = error.message; qs('#create-issue-title').focus(); } }); diff --git a/frontend/index.html b/frontend/index.html index de52bb2..5d0edfb 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -514,7 +514,7 @@
+ + +
+ + +
+ +
diff --git a/tests/test_unfiled_captures.py b/tests/test_unfiled_captures.py index 35ebbb4..224f64c 100644 --- a/tests/test_unfiled_captures.py +++ b/tests/test_unfiled_captures.py @@ -100,7 +100,7 @@ async def test_mobile_composer_exposes_cold_offline_save_and_account_safe_resume assert '' in html assert 'id="save-unfiled-issue"' in html - assert 'Save for filing' in html + assert 'Save to Drafts' in html assert "createUnfiledCaptures({" in html assert "getCaptureLogin: () => String(lastContextSnapshot?.user?.login || '').trim()" in html assert "unfiledCaptures.save(captureDraft)" in html @@ -109,3 +109,19 @@ async def test_mobile_composer_exposes_cold_offline_save_and_account_safe_resume assert "item.kind === 'unfiled-issue'" in html assert '.create-issue-actions button { min-height:44px;' in html assert '@media(max-width:320px)' in html + + +@pytest.mark.anyio +async def test_mobile_new_opens_capture_first_and_progressively_reveals_filing_fields(): + html = await dashboard() + + assert 'id="create-issue-heading">Capture work' in html + assert 'class="create-issue-filing" id="create-issue-filing" hidden' in html + assert 'id="save-unfiled-issue" type="button">Save to Drafts' in html + assert 'id="file-new-issue" type="button">File now' in html + assert "function setIssueFilingMode(enabled)" in html + assert "setIssueFilingMode(Boolean(captureDraft.repository))" in html + assert "qs('#create-issue-title').focus();" in html + assert "qs('#file-new-issue').addEventListener('click'" in html + assert '.create-issue-capture-actions button { min-height:44px;' in html + assert '.create-issue-capture-actions[hidden] { display:none;' in html