# feat\(mobile\): arrange active threads from both thread lists · PR \#9730 · pingdotgg/t3code

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

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

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: sidebar/mobile-active-order

Target branch: sidebar/active-order

Head commit: a41887d423c1d7ce46ca90b6f78a22251917b4b7

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

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

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

## Description

---

Active threads could not be arranged from mobile. Home and the navigation sidebar now offer **Move up** and **Move down** when the server supports saved Active order. Moves use the complete section even when the visible list is filtered, and hold the chosen order until command receipts and canonical updates arrive so partially saved keys do not make rows jump.

Menu availability and execution share the same planner. A move stays available around unsupported servers' existing keys, but is disabled when it would require writing keys to an unsupported server.

The planner reserves snoozed and filtered rows' saved keys without changing those rows.

Verified with 62 focused list and pending-order tests, mobile typecheck, and targeted lint. An Android emulator pass covered Home and the wide navigation sidebar, saved order after relaunch, pinned moves in both directions, first-row disabled controls, and a filtered middle row retaining both directions.

| Before: Active thread menu | After: Active thread menu |
| --- | --- |
| ![Before: no Active move controls](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/c425275d84a198b6/mobile-before-menu.png) | ![After: Move up and Move down for Active threads](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/99436a87a9aa7ea4/mobile-after-menu.png) |

Home: move an Active thread up, then verify its first-position control is disabled.

https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a61e68e9ccbf1707/mobile-home-move.mp4

Navigation sidebar: move the same thread back down.

https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fa7ae5b4e9202b12/mobile-sidebar-move.mp4

![Navigation sidebar with Move up disabled at the first Active position](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/792fcffabed4fc74/mobile-sidebar-menu.png)

Depends on [#9729](https://github.com/pingdotgg/t3code/pull/9729).

Prepared with Codex.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes thread list ordering and multi-step server reorder mutations with optimistic UI holds; incorrect reconciliation could show wrong order until sync, but scope is mobile list UX rather than auth or data integrity.
> 
> **Overview**
> Mobile thread list v2 now supports **Move up** / **Move down** for **active** threads (not only pinned), gated on the server `threadActiveReorder` capability. The action is renamed from `movePinnedThread` to **`moveThread`** and routes pinned moves through `reorderPin` and active moves through **`reorderActive`**.
> 
> **Ordering** aligns with web: active rows sort via **`activeOrderKey`** (`sortActiveThreadsByOrderKey`), with new/unsettled threads still above saved arrangement. **`getThreadListV2OrderedSection`** defines the full pinned/active section for planning so search and project filters do not change valid moves.
> 
> A shared **pending-order** layer (`threadOrder.ts`, `state/thread-order.ts`) holds the target order until reorder commands finish and canonical shells catch up, blocks overlapping moves, and keeps filtered lists in the pending section order. **`createThreadMovePlanner`** drives both menu enablement and execution, including mixed-environment lists where only reorder-capable servers get writes.
> 
> Home, navigation sidebar, and **`ThreadListV2Row`** expose generic reorder props (`reorderSupported`, `canMoveUp`/`canMoveDown`, `onMoveThread`) on **card** rows. Tests cover sorting, pending reconciliation, and move availability.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit eeb5a1e3d61b87778fdee355bcfaaae0a9035320. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- Macroscope's pull request summary starts here -->
<!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. -->
<!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. -->
> [!NOTE]
> ### Add active thread reordering to mobile home and sidebar lists
> - Adds "Move up" and "Move down" menu actions for active threads to [HomeScreen](https://github.com/pingdotgg/t3code/pull/9730/files#diff-b6e075b3065ae370669290cbaa8476a852399968002468571cd914d06a32fd40) and [ThreadNavigationSidebar](https://github.com/pingdotgg/t3code/pull/9730/files#diff-4431208d7dda139d19919302f332d6a63788b9d114b4b7a410d89a727b9ed455) when the environment supports reordering
> - Replaces the pinned-only move action with a generalized `moveThread` in [useThreadListActions](https://github.com/pingdotgg/t3code/pull/9730/files#diff-306460b1de597bc9d164b691fb0e4075061f7eb9246d316db687209ac8dec787) that builds and executes plans for either active or pinned sections
> - Introduces a shared pending order coordinator in [thread-order.ts](https://github.com/pingdotgg/t3code/pull/9730/files#diff-968de6c5de2def04bec0e8824ac89b00df932bc83b3a5b18454475d61236e092) that maintains the requested UI order across views while server assignments are pending
> - Risk: The `beginPendingThreadOrder` coordinator blocks overlapping moves until all assignments are confirmed or the move is cancelled, and releases the hold if the section membership or foreign keys change unexpectedly
>
> <!-- Macroscope's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized a41887d.</sup>
> <!-- Macroscope's review summary ends here -->
>
<!-- Macroscope's pull request summary ends here -->
