# feat\(mobile\): show new-task drafts alongside pending tasks in the thread list · PR \#10260 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/10260)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: t3code/mobile-drafts-in-list

Target branch: t3code/fix-offline-pending-tasks

Head commit: 0286e753379f59474ff9bf68b4459a3c15c2798a

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/10260)

[Commits](https://git.cafe/pingdotgg/t3code/pull/10260/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/10260/diffs?format=markdown)

## Description

---

Stacked on #10245.

## Problem

On mobile, text typed into a project's new-task composer is only discoverable by opening that project's new-task screen again. Nothing on Home or the iPad sidebar shows that a draft exists, so unsent work is easy to lose track of. That also made the outbox's restore path (a rejected pending task gets merged back into the project draft) feel like the task vanished: it moved from the visible Pending section into an invisible draft. Web already lists drafts at the top of its sidebar.

## Fix

`PendingNewTask` is now a union of two kinds of unsent work: `pending` (queued in the outbox, sends itself when the environment reconnects) and `draft` (the project's new-task composer content, sends only when the user submits). Only drafts with user content (text or attachments) are listed; a bare model pick is not surfaced. The pure builder lives in `pending-new-tasks-model.ts`.

Both list surfaces render drafts in the same slot as pending tasks:

- **v2 flat list** (Home and iPad sidebar): the section divider now reads **Unsent**. Drafts get an amber **Draft** label with a pen icon; queued tasks say **Sends on reconnect** in the uncolored status slot, describing what happens next rather than where the item sits.
- **v1 grouped list**: drafts get an amber **Draft** pill and pen icon. The pill has room for one word, so queued tasks keep the **Pending** pill and the subtitle leads with **Sends on reconnect**. Drafts have no timestamp since they have no creation time.

Tapping a draft opens the project's new-task composer, which already loads that draft. Long-press offers **Discard** (clears the draft, same reset a submit performs). Deleting a pending task is unchanged.

Drafts sort first (they are what the user is writing now), then queued tasks newest-first.

## Verification

`vp test run` on the touched suites in `apps/mobile`: `pending-new-tasks-model.test.ts` (new), `threadListV2.test.ts`, `homeThreadList.test.ts`, `homeListItems.test.ts`, `showcasePendingTasks.test.ts` — 73 passed. `vpr typecheck` passes. Lint on the touched files shows only pre-existing warnings (same 23 on the base branch).

### Before / after — v2 flat list (default)

![Before: only the queued task appears under Pending, labelled Queued. After: the Unsent section shows the amber Draft row above a row labelled Sends on reconnect](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/939d0274d4de30ae/drafts-v2-before-after-2.png)

### Before / after — v1 grouped list (Legacy Thread List setting)

![Before: only the Pending pill row. After: a Draft pill row with pen icon leads the group, followed by the Pending row whose subtitle reads Sends on reconnect](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/7727759335765e6c/drafts-v1-before-after-2.png)

### Tapping the draft row

![The new-task composer opens on the draft's project with the draft text loaded](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ad82da6f085177d2/drafts-open-draft.png)

Captured on an iPhone 17 Pro simulator with the dev client, same seeded state (one draft, one queued task, one real thread) on both revisions, environment filter scoped to the test backend.

## Surfaces

- Entry points: Home list (v1 and v2), iPad `ThreadNavigationSidebar` (v1 and v2), new-task composer (open target).
- Clients: mobile only. Web already has draft rows; the server is untouched.
- Reverse state: Discard from the row menu, or clear the composer.

Model: Claude Fable 5 · Harness: Claude Code in T3 Code

🤖 Generated with [Claude Code](https://claude.com/claude-code)

