feat(sidebar): drag-and-drop reordering of threads within a project - #3069

Closed
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder
Closed

feat(sidebar): drag-and-drop reordering of threads within a project#3069
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder

Conversation

@TheIcarusWings

@TheIcarusWingsTheIcarusWings commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

Adds drag-and-drop reordering of threads within their project in the sidebar — grab a thread row and move it among the other threads in the same project. This is reordering within one project, not moving threads between projects. It mirrors the existing project-reorder pattern (same @dnd-kit setup, same client-side persistence model).

Demo

Enable Sort threads → Manual, then drag a thread row to reorder it within its project. The list auto-expands so the whole project is reorderable, and the order persists across reloads.

Thread drag-and-drop reorder demo

New "Manual" thread sortBeforeAfter (persists on reload)

Changes

  • contracts: add "manual" to SidebarThreadSortOrder (alongside updated_at/created_at), matching SidebarProjectSortOrder. New "Manual" option in the "Sort threads" menu.
  • threadSort: sortThreads returns input order for "manual", so the user-defined order is layered on top via orderItemsByPreferredIds (same shape as sortProjectsForSidebar).
  • uiStateStore: new threadOrderByProject: Record<projectKey, threadKey[]>. Because scopedThreadKey is stable, it persists directly to localStorage (no id→cwd remapping like projects need). New reorderThreads action; syncThreads prunes stale thread keys and drops emptied projects.
  • Sidebar: per-project DndContext + SortableContext + SortableThreadItem rendered only when manual sort is active (non-DnD fallback otherwise). dragInProgress / suppressClickAfterDrag refs guard click, cmd/shift multi-select and rename so they don't fire on a drag. Manual mode auto-expands the full list (skips preview slicing / "Show more") so the whole list is reorderable; auto-animate stays attached.

The order map is keyed per project now but keyed so it extends naturally to user-defined groups once folders land.

Verification

  • tsgo --noEmit passes (web + contracts).
  • Full web unit suite green (1057 tests); contracts 148. Added store tests (reorder up/down, first-drag seeding, no-ops, sync pruning, persistence round-trip) plus manual-order coverage for the delete-fallback and command-palette navigation helpers.
  • Manually tested on localhost: enabled Manual thread sort, dragged a thread within a project, confirmed the new order persists across reload, and that click / rename / multi-select still work.

🤖 Generated with Claude Code


Note

Low Risk
Client-only sidebar ordering and localStorage persistence; navigation/delete fallbacks are aligned with manual order but do not touch server auth or data.

Overview
Adds manual thread sort so users can drag thread rows within a project to define sidebar order, with the same persistence model as manual project reorder.

Contracts & sorting:SidebarThreadSortOrder gains "manual". orderItemsByPreferredIds moves to threadSort.ts; manual mode keeps store order and callers apply persisted scoped thread keys. getLatestThreadForProject and post-delete fallback navigation use that order so “open project” and delete routing match the first visible thread.

Persistence:uiStateStore adds threadOrderByProject and reorderThreads, saved to localStorage; syncThreads prunes removed threads.

Sidebar UX: When sort is manual, per-project DndContext/SortableContext enables vertical drag on rows (grab cursor, drop highlight), suppresses clicks during/after drag, and shows the full thread list (no “Show more” truncation). Thread-jump indices and prewarm lists follow the same manual ordering.

Call sites: Command palette project open paths pass flattened manual order into getLatestThreadForProject.

Reviewed by Cursor Bugbot for commit 1ed1189. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add drag-and-drop manual reordering of threads within sidebar projects

  • Adds a new 'manual' sort mode to SidebarThreadSortOrder and a reorderThreads reducer in uiStateStore.ts that persists per-project thread order to localStorage.
  • Wraps sidebar thread rows in a SortableThreadItem component using @dnd-kit, enabling vertical drag-and-drop reordering within each project in Sidebar.tsx.
  • Extends sortThreads and getLatestThreadForProject in threadSort.ts so manual mode preserves input order and resolves "latest" thread by manual position rather than timestamp.
  • Fallback navigation after thread deletion and command palette project opening both respect manual order when active.
  • syncThreads prunes stale thread keys from the saved order automatically when threads are removed.

Macroscope summarized 1ed1189.

Add a "Manual" thread sort mode that lets you drag a thread row to reorder
it among the other threads in the same project, mirroring the existing
project-reorder pattern.
- contracts: add "manual" to SidebarThreadSortOrder
- threadSort: sortThreads returns input order for "manual" so a user-defined
order can be layered on top (matches sortProjectsForSidebar)
- uiStateStore: persist threadOrderByProject directly (thread keys are stable,
no id->cwd remapping); add reorderThreads action and prune stale keys /
empty projects in syncThreads
- Sidebar: per-project DndContext + SortableContext + SortableThreadItem when
manual sort is active; suppress click/multi-select/rename during drag; apply
the order via orderItemsByPreferredIds and auto-expand the full list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jun 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21981e0e-a37c-489b-b623-0244d0809ec2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jun 13, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 83326f5. Configure here.

Comment threadapps/web/src/lib/threadSort.ts
@macroscopeapp

macroscopeappBot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (drag-and-drop thread reordering) with new state management and UI interactions across multiple components. New capabilities of this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Cursor Bugbot flagged that helpers picking a thread via sortThreads still
used raw store order under manual sort, so the delete-fallback navigation
and "open project from search" could jump to a thread that isn't first in
the sidebar's manual list.
- getLatestThreadForProject / getFallbackThreadIdAfterDelete now accept the
manual order (scoped thread keys) and apply orderItemsByPreferredIds when
sort is "manual", matching the sidebar's on-screen order
- move orderItemsByPreferredIds into lib/threadSort (re-exported from
Sidebar.logic) so the lib helper can use it without an import cycle
- callers (useThreadActions, CommandPalette) pass the flattened
threadOrderByProject; the per-project filter means only the relevant
project's keys match
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Jun 14, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Closing as part of backlog cleanup: this PR is stale, currently conflicting with main, has no approval, and has not had active remediation for 30+ days. If the change is still relevant, please rebase onto current main and request reopening or submit a focused current diff. Thank you for the contribution.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TheIcarusWings@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(sidebar): drag-and-drop reordering of threads within a project - #3069

Closed
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder
Closed

feat(sidebar): drag-and-drop reordering of threads within a project#3069
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder

Conversation

@TheIcarusWings

@TheIcarusWingsTheIcarusWings commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

Adds drag-and-drop reordering of threads within their project in the sidebar — grab a thread row and move it among the other threads in the same project. This is reordering within one project, not moving threads between projects. It mirrors the existing project-reorder pattern (same @dnd-kit setup, same client-side persistence model).

Demo

Enable Sort threads → Manual, then drag a thread row to reorder it within its project. The list auto-expands so the whole project is reorderable, and the order persists across reloads.

Thread drag-and-drop reorder demo

New "Manual" thread sortBeforeAfter (persists on reload)

Changes

  • contracts: add "manual" to SidebarThreadSortOrder (alongside updated_at/created_at), matching SidebarProjectSortOrder. New "Manual" option in the "Sort threads" menu.
  • threadSort: sortThreads returns input order for "manual", so the user-defined order is layered on top via orderItemsByPreferredIds (same shape as sortProjectsForSidebar).
  • uiStateStore: new threadOrderByProject: Record<projectKey, threadKey[]>. Because scopedThreadKey is stable, it persists directly to localStorage (no id→cwd remapping like projects need). New reorderThreads action; syncThreads prunes stale thread keys and drops emptied projects.
  • Sidebar: per-project DndContext + SortableContext + SortableThreadItem rendered only when manual sort is active (non-DnD fallback otherwise). dragInProgress / suppressClickAfterDrag refs guard click, cmd/shift multi-select and rename so they don't fire on a drag. Manual mode auto-expands the full list (skips preview slicing / "Show more") so the whole list is reorderable; auto-animate stays attached.

The order map is keyed per project now but keyed so it extends naturally to user-defined groups once folders land.

Verification

  • tsgo --noEmit passes (web + contracts).
  • Full web unit suite green (1057 tests); contracts 148. Added store tests (reorder up/down, first-drag seeding, no-ops, sync pruning, persistence round-trip) plus manual-order coverage for the delete-fallback and command-palette navigation helpers.
  • Manually tested on localhost: enabled Manual thread sort, dragged a thread within a project, confirmed the new order persists across reload, and that click / rename / multi-select still work.

🤖 Generated with Claude Code


Note

Low Risk
Client-only sidebar ordering and localStorage persistence; navigation/delete fallbacks are aligned with manual order but do not touch server auth or data.

Overview
Adds manual thread sort so users can drag thread rows within a project to define sidebar order, with the same persistence model as manual project reorder.

Contracts & sorting:SidebarThreadSortOrder gains "manual". orderItemsByPreferredIds moves to threadSort.ts; manual mode keeps store order and callers apply persisted scoped thread keys. getLatestThreadForProject and post-delete fallback navigation use that order so “open project” and delete routing match the first visible thread.

Persistence:uiStateStore adds threadOrderByProject and reorderThreads, saved to localStorage; syncThreads prunes removed threads.

Sidebar UX: When sort is manual, per-project DndContext/SortableContext enables vertical drag on rows (grab cursor, drop highlight), suppresses clicks during/after drag, and shows the full thread list (no “Show more” truncation). Thread-jump indices and prewarm lists follow the same manual ordering.

Call sites: Command palette project open paths pass flattened manual order into getLatestThreadForProject.

Reviewed by Cursor Bugbot for commit 1ed1189. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add drag-and-drop manual reordering of threads within sidebar projects

  • Adds a new 'manual' sort mode to SidebarThreadSortOrder and a reorderThreads reducer in uiStateStore.ts that persists per-project thread order to localStorage.
  • Wraps sidebar thread rows in a SortableThreadItem component using @dnd-kit, enabling vertical drag-and-drop reordering within each project in Sidebar.tsx.
  • Extends sortThreads and getLatestThreadForProject in threadSort.ts so manual mode preserves input order and resolves "latest" thread by manual position rather than timestamp.
  • Fallback navigation after thread deletion and command palette project opening both respect manual order when active.
  • syncThreads prunes stale thread keys from the saved order automatically when threads are removed.

Macroscope summarized 1ed1189.

Add a "Manual" thread sort mode that lets you drag a thread row to reorder
it among the other threads in the same project, mirroring the existing
project-reorder pattern.
- contracts: add "manual" to SidebarThreadSortOrder
- threadSort: sortThreads returns input order for "manual" so a user-defined
order can be layered on top (matches sortProjectsForSidebar)
- uiStateStore: persist threadOrderByProject directly (thread keys are stable,
no id->cwd remapping); add reorderThreads action and prune stale keys /
empty projects in syncThreads
- Sidebar: per-project DndContext + SortableContext + SortableThreadItem when
manual sort is active; suppress click/multi-select/rename during drag; apply
the order via orderItemsByPreferredIds and auto-expand the full list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jun 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21981e0e-a37c-489b-b623-0244d0809ec2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jun 13, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 83326f5. Configure here.

Comment threadapps/web/src/lib/threadSort.ts
@macroscopeapp

macroscopeappBot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (drag-and-drop thread reordering) with new state management and UI interactions across multiple components. New capabilities of this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Cursor Bugbot flagged that helpers picking a thread via sortThreads still
used raw store order under manual sort, so the delete-fallback navigation
and "open project from search" could jump to a thread that isn't first in
the sidebar's manual list.
- getLatestThreadForProject / getFallbackThreadIdAfterDelete now accept the
manual order (scoped thread keys) and apply orderItemsByPreferredIds when
sort is "manual", matching the sidebar's on-screen order
- move orderItemsByPreferredIds into lib/threadSort (re-exported from
Sidebar.logic) so the lib helper can use it without an import cycle
- callers (useThreadActions, CommandPalette) pass the flattened
threadOrderByProject; the per-project filter means only the relevant
project's keys match
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Jun 14, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Closing as part of backlog cleanup: this PR is stale, currently conflicting with main, has no approval, and has not had active remediation for 30+ days. If the change is still relevant, please rebase onto current main and request reopening or submit a focused current diff. Thank you for the contribution.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TheIcarusWings@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(sidebar): drag-and-drop reordering of threads within a project - #3069

Closed
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder
Closed

feat(sidebar): drag-and-drop reordering of threads within a project#3069
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder

Conversation

@TheIcarusWings

@TheIcarusWingsTheIcarusWings commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

Adds drag-and-drop reordering of threads within their project in the sidebar — grab a thread row and move it among the other threads in the same project. This is reordering within one project, not moving threads between projects. It mirrors the existing project-reorder pattern (same @dnd-kit setup, same client-side persistence model).

Demo

Enable Sort threads → Manual, then drag a thread row to reorder it within its project. The list auto-expands so the whole project is reorderable, and the order persists across reloads.

Thread drag-and-drop reorder demo

New "Manual" thread sortBeforeAfter (persists on reload)

Changes

  • contracts: add "manual" to SidebarThreadSortOrder (alongside updated_at/created_at), matching SidebarProjectSortOrder. New "Manual" option in the "Sort threads" menu.
  • threadSort: sortThreads returns input order for "manual", so the user-defined order is layered on top via orderItemsByPreferredIds (same shape as sortProjectsForSidebar).
  • uiStateStore: new threadOrderByProject: Record<projectKey, threadKey[]>. Because scopedThreadKey is stable, it persists directly to localStorage (no id→cwd remapping like projects need). New reorderThreads action; syncThreads prunes stale thread keys and drops emptied projects.
  • Sidebar: per-project DndContext + SortableContext + SortableThreadItem rendered only when manual sort is active (non-DnD fallback otherwise). dragInProgress / suppressClickAfterDrag refs guard click, cmd/shift multi-select and rename so they don't fire on a drag. Manual mode auto-expands the full list (skips preview slicing / "Show more") so the whole list is reorderable; auto-animate stays attached.

The order map is keyed per project now but keyed so it extends naturally to user-defined groups once folders land.

Verification

  • tsgo --noEmit passes (web + contracts).
  • Full web unit suite green (1057 tests); contracts 148. Added store tests (reorder up/down, first-drag seeding, no-ops, sync pruning, persistence round-trip) plus manual-order coverage for the delete-fallback and command-palette navigation helpers.
  • Manually tested on localhost: enabled Manual thread sort, dragged a thread within a project, confirmed the new order persists across reload, and that click / rename / multi-select still work.

🤖 Generated with Claude Code


Note

Low Risk
Client-only sidebar ordering and localStorage persistence; navigation/delete fallbacks are aligned with manual order but do not touch server auth or data.

Overview
Adds manual thread sort so users can drag thread rows within a project to define sidebar order, with the same persistence model as manual project reorder.

Contracts & sorting:SidebarThreadSortOrder gains "manual". orderItemsByPreferredIds moves to threadSort.ts; manual mode keeps store order and callers apply persisted scoped thread keys. getLatestThreadForProject and post-delete fallback navigation use that order so “open project” and delete routing match the first visible thread.

Persistence:uiStateStore adds threadOrderByProject and reorderThreads, saved to localStorage; syncThreads prunes removed threads.

Sidebar UX: When sort is manual, per-project DndContext/SortableContext enables vertical drag on rows (grab cursor, drop highlight), suppresses clicks during/after drag, and shows the full thread list (no “Show more” truncation). Thread-jump indices and prewarm lists follow the same manual ordering.

Call sites: Command palette project open paths pass flattened manual order into getLatestThreadForProject.

Reviewed by Cursor Bugbot for commit 1ed1189. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add drag-and-drop manual reordering of threads within sidebar projects

  • Adds a new 'manual' sort mode to SidebarThreadSortOrder and a reorderThreads reducer in uiStateStore.ts that persists per-project thread order to localStorage.
  • Wraps sidebar thread rows in a SortableThreadItem component using @dnd-kit, enabling vertical drag-and-drop reordering within each project in Sidebar.tsx.
  • Extends sortThreads and getLatestThreadForProject in threadSort.ts so manual mode preserves input order and resolves "latest" thread by manual position rather than timestamp.
  • Fallback navigation after thread deletion and command palette project opening both respect manual order when active.
  • syncThreads prunes stale thread keys from the saved order automatically when threads are removed.

Macroscope summarized 1ed1189.

Add a "Manual" thread sort mode that lets you drag a thread row to reorder
it among the other threads in the same project, mirroring the existing
project-reorder pattern.
- contracts: add "manual" to SidebarThreadSortOrder
- threadSort: sortThreads returns input order for "manual" so a user-defined
order can be layered on top (matches sortProjectsForSidebar)
- uiStateStore: persist threadOrderByProject directly (thread keys are stable,
no id->cwd remapping); add reorderThreads action and prune stale keys /
empty projects in syncThreads
- Sidebar: per-project DndContext + SortableContext + SortableThreadItem when
manual sort is active; suppress click/multi-select/rename during drag; apply
the order via orderItemsByPreferredIds and auto-expand the full list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jun 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21981e0e-a37c-489b-b623-0244d0809ec2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jun 13, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 83326f5. Configure here.

Comment threadapps/web/src/lib/threadSort.ts
@macroscopeapp

macroscopeappBot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (drag-and-drop thread reordering) with new state management and UI interactions across multiple components. New capabilities of this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Cursor Bugbot flagged that helpers picking a thread via sortThreads still
used raw store order under manual sort, so the delete-fallback navigation
and "open project from search" could jump to a thread that isn't first in
the sidebar's manual list.
- getLatestThreadForProject / getFallbackThreadIdAfterDelete now accept the
manual order (scoped thread keys) and apply orderItemsByPreferredIds when
sort is "manual", matching the sidebar's on-screen order
- move orderItemsByPreferredIds into lib/threadSort (re-exported from
Sidebar.logic) so the lib helper can use it without an import cycle
- callers (useThreadActions, CommandPalette) pass the flattened
threadOrderByProject; the per-project filter means only the relevant
project's keys match
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Jun 14, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Closing as part of backlog cleanup: this PR is stale, currently conflicting with main, has no approval, and has not had active remediation for 30+ days. If the change is still relevant, please rebase onto current main and request reopening or submit a focused current diff. Thank you for the contribution.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TheIcarusWings@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(sidebar): drag-and-drop reordering of threads within a project - #3069

Closed
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder
Closed

feat(sidebar): drag-and-drop reordering of threads within a project#3069
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder

Conversation

@TheIcarusWings

@TheIcarusWingsTheIcarusWings commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

Adds drag-and-drop reordering of threads within their project in the sidebar — grab a thread row and move it among the other threads in the same project. This is reordering within one project, not moving threads between projects. It mirrors the existing project-reorder pattern (same @dnd-kit setup, same client-side persistence model).

Demo

Enable Sort threads → Manual, then drag a thread row to reorder it within its project. The list auto-expands so the whole project is reorderable, and the order persists across reloads.

Thread drag-and-drop reorder demo

New "Manual" thread sortBeforeAfter (persists on reload)

Changes

  • contracts: add "manual" to SidebarThreadSortOrder (alongside updated_at/created_at), matching SidebarProjectSortOrder. New "Manual" option in the "Sort threads" menu.
  • threadSort: sortThreads returns input order for "manual", so the user-defined order is layered on top via orderItemsByPreferredIds (same shape as sortProjectsForSidebar).
  • uiStateStore: new threadOrderByProject: Record<projectKey, threadKey[]>. Because scopedThreadKey is stable, it persists directly to localStorage (no id→cwd remapping like projects need). New reorderThreads action; syncThreads prunes stale thread keys and drops emptied projects.
  • Sidebar: per-project DndContext + SortableContext + SortableThreadItem rendered only when manual sort is active (non-DnD fallback otherwise). dragInProgress / suppressClickAfterDrag refs guard click, cmd/shift multi-select and rename so they don't fire on a drag. Manual mode auto-expands the full list (skips preview slicing / "Show more") so the whole list is reorderable; auto-animate stays attached.

The order map is keyed per project now but keyed so it extends naturally to user-defined groups once folders land.

Verification

  • tsgo --noEmit passes (web + contracts).
  • Full web unit suite green (1057 tests); contracts 148. Added store tests (reorder up/down, first-drag seeding, no-ops, sync pruning, persistence round-trip) plus manual-order coverage for the delete-fallback and command-palette navigation helpers.
  • Manually tested on localhost: enabled Manual thread sort, dragged a thread within a project, confirmed the new order persists across reload, and that click / rename / multi-select still work.

🤖 Generated with Claude Code


Note

Low Risk
Client-only sidebar ordering and localStorage persistence; navigation/delete fallbacks are aligned with manual order but do not touch server auth or data.

Overview
Adds manual thread sort so users can drag thread rows within a project to define sidebar order, with the same persistence model as manual project reorder.

Contracts & sorting:SidebarThreadSortOrder gains "manual". orderItemsByPreferredIds moves to threadSort.ts; manual mode keeps store order and callers apply persisted scoped thread keys. getLatestThreadForProject and post-delete fallback navigation use that order so “open project” and delete routing match the first visible thread.

Persistence:uiStateStore adds threadOrderByProject and reorderThreads, saved to localStorage; syncThreads prunes removed threads.

Sidebar UX: When sort is manual, per-project DndContext/SortableContext enables vertical drag on rows (grab cursor, drop highlight), suppresses clicks during/after drag, and shows the full thread list (no “Show more” truncation). Thread-jump indices and prewarm lists follow the same manual ordering.

Call sites: Command palette project open paths pass flattened manual order into getLatestThreadForProject.

Reviewed by Cursor Bugbot for commit 1ed1189. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add drag-and-drop manual reordering of threads within sidebar projects

  • Adds a new 'manual' sort mode to SidebarThreadSortOrder and a reorderThreads reducer in uiStateStore.ts that persists per-project thread order to localStorage.
  • Wraps sidebar thread rows in a SortableThreadItem component using @dnd-kit, enabling vertical drag-and-drop reordering within each project in Sidebar.tsx.
  • Extends sortThreads and getLatestThreadForProject in threadSort.ts so manual mode preserves input order and resolves "latest" thread by manual position rather than timestamp.
  • Fallback navigation after thread deletion and command palette project opening both respect manual order when active.
  • syncThreads prunes stale thread keys from the saved order automatically when threads are removed.

Macroscope summarized 1ed1189.

Add a "Manual" thread sort mode that lets you drag a thread row to reorder
it among the other threads in the same project, mirroring the existing
project-reorder pattern.
- contracts: add "manual" to SidebarThreadSortOrder
- threadSort: sortThreads returns input order for "manual" so a user-defined
order can be layered on top (matches sortProjectsForSidebar)
- uiStateStore: persist threadOrderByProject directly (thread keys are stable,
no id->cwd remapping); add reorderThreads action and prune stale keys /
empty projects in syncThreads
- Sidebar: per-project DndContext + SortableContext + SortableThreadItem when
manual sort is active; suppress click/multi-select/rename during drag; apply
the order via orderItemsByPreferredIds and auto-expand the full list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jun 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21981e0e-a37c-489b-b623-0244d0809ec2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jun 13, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 83326f5. Configure here.

Comment threadapps/web/src/lib/threadSort.ts
@macroscopeapp

macroscopeappBot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (drag-and-drop thread reordering) with new state management and UI interactions across multiple components. New capabilities of this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Cursor Bugbot flagged that helpers picking a thread via sortThreads still
used raw store order under manual sort, so the delete-fallback navigation
and "open project from search" could jump to a thread that isn't first in
the sidebar's manual list.
- getLatestThreadForProject / getFallbackThreadIdAfterDelete now accept the
manual order (scoped thread keys) and apply orderItemsByPreferredIds when
sort is "manual", matching the sidebar's on-screen order
- move orderItemsByPreferredIds into lib/threadSort (re-exported from
Sidebar.logic) so the lib helper can use it without an import cycle
- callers (useThreadActions, CommandPalette) pass the flattened
threadOrderByProject; the per-project filter means only the relevant
project's keys match
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Jun 14, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Closing as part of backlog cleanup: this PR is stale, currently conflicting with main, has no approval, and has not had active remediation for 30+ days. If the change is still relevant, please rebase onto current main and request reopening or submit a focused current diff. Thank you for the contribution.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TheIcarusWings@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(sidebar): drag-and-drop reordering of threads within a project - #3069

Closed
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder
Closed

feat(sidebar): drag-and-drop reordering of threads within a project#3069
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder

Conversation

@TheIcarusWings

@TheIcarusWingsTheIcarusWings commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

Adds drag-and-drop reordering of threads within their project in the sidebar — grab a thread row and move it among the other threads in the same project. This is reordering within one project, not moving threads between projects. It mirrors the existing project-reorder pattern (same @dnd-kit setup, same client-side persistence model).

Demo

Enable Sort threads → Manual, then drag a thread row to reorder it within its project. The list auto-expands so the whole project is reorderable, and the order persists across reloads.

Thread drag-and-drop reorder demo

New "Manual" thread sortBeforeAfter (persists on reload)

Changes

  • contracts: add "manual" to SidebarThreadSortOrder (alongside updated_at/created_at), matching SidebarProjectSortOrder. New "Manual" option in the "Sort threads" menu.
  • threadSort: sortThreads returns input order for "manual", so the user-defined order is layered on top via orderItemsByPreferredIds (same shape as sortProjectsForSidebar).
  • uiStateStore: new threadOrderByProject: Record<projectKey, threadKey[]>. Because scopedThreadKey is stable, it persists directly to localStorage (no id→cwd remapping like projects need). New reorderThreads action; syncThreads prunes stale thread keys and drops emptied projects.
  • Sidebar: per-project DndContext + SortableContext + SortableThreadItem rendered only when manual sort is active (non-DnD fallback otherwise). dragInProgress / suppressClickAfterDrag refs guard click, cmd/shift multi-select and rename so they don't fire on a drag. Manual mode auto-expands the full list (skips preview slicing / "Show more") so the whole list is reorderable; auto-animate stays attached.

The order map is keyed per project now but keyed so it extends naturally to user-defined groups once folders land.

Verification

  • tsgo --noEmit passes (web + contracts).
  • Full web unit suite green (1057 tests); contracts 148. Added store tests (reorder up/down, first-drag seeding, no-ops, sync pruning, persistence round-trip) plus manual-order coverage for the delete-fallback and command-palette navigation helpers.
  • Manually tested on localhost: enabled Manual thread sort, dragged a thread within a project, confirmed the new order persists across reload, and that click / rename / multi-select still work.

🤖 Generated with Claude Code


Note

Low Risk
Client-only sidebar ordering and localStorage persistence; navigation/delete fallbacks are aligned with manual order but do not touch server auth or data.

Overview
Adds manual thread sort so users can drag thread rows within a project to define sidebar order, with the same persistence model as manual project reorder.

Contracts & sorting:SidebarThreadSortOrder gains "manual". orderItemsByPreferredIds moves to threadSort.ts; manual mode keeps store order and callers apply persisted scoped thread keys. getLatestThreadForProject and post-delete fallback navigation use that order so “open project” and delete routing match the first visible thread.

Persistence:uiStateStore adds threadOrderByProject and reorderThreads, saved to localStorage; syncThreads prunes removed threads.

Sidebar UX: When sort is manual, per-project DndContext/SortableContext enables vertical drag on rows (grab cursor, drop highlight), suppresses clicks during/after drag, and shows the full thread list (no “Show more” truncation). Thread-jump indices and prewarm lists follow the same manual ordering.

Call sites: Command palette project open paths pass flattened manual order into getLatestThreadForProject.

Reviewed by Cursor Bugbot for commit 1ed1189. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add drag-and-drop manual reordering of threads within sidebar projects

  • Adds a new 'manual' sort mode to SidebarThreadSortOrder and a reorderThreads reducer in uiStateStore.ts that persists per-project thread order to localStorage.
  • Wraps sidebar thread rows in a SortableThreadItem component using @dnd-kit, enabling vertical drag-and-drop reordering within each project in Sidebar.tsx.
  • Extends sortThreads and getLatestThreadForProject in threadSort.ts so manual mode preserves input order and resolves "latest" thread by manual position rather than timestamp.
  • Fallback navigation after thread deletion and command palette project opening both respect manual order when active.
  • syncThreads prunes stale thread keys from the saved order automatically when threads are removed.

Macroscope summarized 1ed1189.

Add a "Manual" thread sort mode that lets you drag a thread row to reorder
it among the other threads in the same project, mirroring the existing
project-reorder pattern.
- contracts: add "manual" to SidebarThreadSortOrder
- threadSort: sortThreads returns input order for "manual" so a user-defined
order can be layered on top (matches sortProjectsForSidebar)
- uiStateStore: persist threadOrderByProject directly (thread keys are stable,
no id->cwd remapping); add reorderThreads action and prune stale keys /
empty projects in syncThreads
- Sidebar: per-project DndContext + SortableContext + SortableThreadItem when
manual sort is active; suppress click/multi-select/rename during drag; apply
the order via orderItemsByPreferredIds and auto-expand the full list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jun 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21981e0e-a37c-489b-b623-0244d0809ec2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jun 13, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 83326f5. Configure here.

Comment threadapps/web/src/lib/threadSort.ts
@macroscopeapp

macroscopeappBot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (drag-and-drop thread reordering) with new state management and UI interactions across multiple components. New capabilities of this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Cursor Bugbot flagged that helpers picking a thread via sortThreads still
used raw store order under manual sort, so the delete-fallback navigation
and "open project from search" could jump to a thread that isn't first in
the sidebar's manual list.
- getLatestThreadForProject / getFallbackThreadIdAfterDelete now accept the
manual order (scoped thread keys) and apply orderItemsByPreferredIds when
sort is "manual", matching the sidebar's on-screen order
- move orderItemsByPreferredIds into lib/threadSort (re-exported from
Sidebar.logic) so the lib helper can use it without an import cycle
- callers (useThreadActions, CommandPalette) pass the flattened
threadOrderByProject; the per-project filter means only the relevant
project's keys match
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Jun 14, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Closing as part of backlog cleanup: this PR is stale, currently conflicting with main, has no approval, and has not had active remediation for 30+ days. If the change is still relevant, please rebase onto current main and request reopening or submit a focused current diff. Thank you for the contribution.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TheIcarusWings@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(sidebar): drag-and-drop reordering of threads within a project - #3069

Closed
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder
Closed

feat(sidebar): drag-and-drop reordering of threads within a project#3069
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder

Conversation

@TheIcarusWings

@TheIcarusWingsTheIcarusWings commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

Adds drag-and-drop reordering of threads within their project in the sidebar — grab a thread row and move it among the other threads in the same project. This is reordering within one project, not moving threads between projects. It mirrors the existing project-reorder pattern (same @dnd-kit setup, same client-side persistence model).

Demo

Enable Sort threads → Manual, then drag a thread row to reorder it within its project. The list auto-expands so the whole project is reorderable, and the order persists across reloads.

Thread drag-and-drop reorder demo

New "Manual" thread sortBeforeAfter (persists on reload)

Changes

  • contracts: add "manual" to SidebarThreadSortOrder (alongside updated_at/created_at), matching SidebarProjectSortOrder. New "Manual" option in the "Sort threads" menu.
  • threadSort: sortThreads returns input order for "manual", so the user-defined order is layered on top via orderItemsByPreferredIds (same shape as sortProjectsForSidebar).
  • uiStateStore: new threadOrderByProject: Record<projectKey, threadKey[]>. Because scopedThreadKey is stable, it persists directly to localStorage (no id→cwd remapping like projects need). New reorderThreads action; syncThreads prunes stale thread keys and drops emptied projects.
  • Sidebar: per-project DndContext + SortableContext + SortableThreadItem rendered only when manual sort is active (non-DnD fallback otherwise). dragInProgress / suppressClickAfterDrag refs guard click, cmd/shift multi-select and rename so they don't fire on a drag. Manual mode auto-expands the full list (skips preview slicing / "Show more") so the whole list is reorderable; auto-animate stays attached.

The order map is keyed per project now but keyed so it extends naturally to user-defined groups once folders land.

Verification

  • tsgo --noEmit passes (web + contracts).
  • Full web unit suite green (1057 tests); contracts 148. Added store tests (reorder up/down, first-drag seeding, no-ops, sync pruning, persistence round-trip) plus manual-order coverage for the delete-fallback and command-palette navigation helpers.
  • Manually tested on localhost: enabled Manual thread sort, dragged a thread within a project, confirmed the new order persists across reload, and that click / rename / multi-select still work.

🤖 Generated with Claude Code


Note

Low Risk
Client-only sidebar ordering and localStorage persistence; navigation/delete fallbacks are aligned with manual order but do not touch server auth or data.

Overview
Adds manual thread sort so users can drag thread rows within a project to define sidebar order, with the same persistence model as manual project reorder.

Contracts & sorting:SidebarThreadSortOrder gains "manual". orderItemsByPreferredIds moves to threadSort.ts; manual mode keeps store order and callers apply persisted scoped thread keys. getLatestThreadForProject and post-delete fallback navigation use that order so “open project” and delete routing match the first visible thread.

Persistence:uiStateStore adds threadOrderByProject and reorderThreads, saved to localStorage; syncThreads prunes removed threads.

Sidebar UX: When sort is manual, per-project DndContext/SortableContext enables vertical drag on rows (grab cursor, drop highlight), suppresses clicks during/after drag, and shows the full thread list (no “Show more” truncation). Thread-jump indices and prewarm lists follow the same manual ordering.

Call sites: Command palette project open paths pass flattened manual order into getLatestThreadForProject.

Reviewed by Cursor Bugbot for commit 1ed1189. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add drag-and-drop manual reordering of threads within sidebar projects

  • Adds a new 'manual' sort mode to SidebarThreadSortOrder and a reorderThreads reducer in uiStateStore.ts that persists per-project thread order to localStorage.
  • Wraps sidebar thread rows in a SortableThreadItem component using @dnd-kit, enabling vertical drag-and-drop reordering within each project in Sidebar.tsx.
  • Extends sortThreads and getLatestThreadForProject in threadSort.ts so manual mode preserves input order and resolves "latest" thread by manual position rather than timestamp.
  • Fallback navigation after thread deletion and command palette project opening both respect manual order when active.
  • syncThreads prunes stale thread keys from the saved order automatically when threads are removed.

Macroscope summarized 1ed1189.

Add a "Manual" thread sort mode that lets you drag a thread row to reorder
it among the other threads in the same project, mirroring the existing
project-reorder pattern.
- contracts: add "manual" to SidebarThreadSortOrder
- threadSort: sortThreads returns input order for "manual" so a user-defined
order can be layered on top (matches sortProjectsForSidebar)
- uiStateStore: persist threadOrderByProject directly (thread keys are stable,
no id->cwd remapping); add reorderThreads action and prune stale keys /
empty projects in syncThreads
- Sidebar: per-project DndContext + SortableContext + SortableThreadItem when
manual sort is active; suppress click/multi-select/rename during drag; apply
the order via orderItemsByPreferredIds and auto-expand the full list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jun 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21981e0e-a37c-489b-b623-0244d0809ec2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jun 13, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 83326f5. Configure here.

Comment threadapps/web/src/lib/threadSort.ts
@macroscopeapp

macroscopeappBot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (drag-and-drop thread reordering) with new state management and UI interactions across multiple components. New capabilities of this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Cursor Bugbot flagged that helpers picking a thread via sortThreads still
used raw store order under manual sort, so the delete-fallback navigation
and "open project from search" could jump to a thread that isn't first in
the sidebar's manual list.
- getLatestThreadForProject / getFallbackThreadIdAfterDelete now accept the
manual order (scoped thread keys) and apply orderItemsByPreferredIds when
sort is "manual", matching the sidebar's on-screen order
- move orderItemsByPreferredIds into lib/threadSort (re-exported from
Sidebar.logic) so the lib helper can use it without an import cycle
- callers (useThreadActions, CommandPalette) pass the flattened
threadOrderByProject; the per-project filter means only the relevant
project's keys match
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Jun 14, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Closing as part of backlog cleanup: this PR is stale, currently conflicting with main, has no approval, and has not had active remediation for 30+ days. If the change is still relevant, please rebase onto current main and request reopening or submit a focused current diff. Thank you for the contribution.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TheIcarusWings@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(sidebar): drag-and-drop reordering of threads within a project - #3069

Closed
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder
Closed

feat(sidebar): drag-and-drop reordering of threads within a project#3069
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder

Conversation

@TheIcarusWings

@TheIcarusWingsTheIcarusWings commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

Adds drag-and-drop reordering of threads within their project in the sidebar — grab a thread row and move it among the other threads in the same project. This is reordering within one project, not moving threads between projects. It mirrors the existing project-reorder pattern (same @dnd-kit setup, same client-side persistence model).

Demo

Enable Sort threads → Manual, then drag a thread row to reorder it within its project. The list auto-expands so the whole project is reorderable, and the order persists across reloads.

Thread drag-and-drop reorder demo

New "Manual" thread sortBeforeAfter (persists on reload)

Changes

  • contracts: add "manual" to SidebarThreadSortOrder (alongside updated_at/created_at), matching SidebarProjectSortOrder. New "Manual" option in the "Sort threads" menu.
  • threadSort: sortThreads returns input order for "manual", so the user-defined order is layered on top via orderItemsByPreferredIds (same shape as sortProjectsForSidebar).
  • uiStateStore: new threadOrderByProject: Record<projectKey, threadKey[]>. Because scopedThreadKey is stable, it persists directly to localStorage (no id→cwd remapping like projects need). New reorderThreads action; syncThreads prunes stale thread keys and drops emptied projects.
  • Sidebar: per-project DndContext + SortableContext + SortableThreadItem rendered only when manual sort is active (non-DnD fallback otherwise). dragInProgress / suppressClickAfterDrag refs guard click, cmd/shift multi-select and rename so they don't fire on a drag. Manual mode auto-expands the full list (skips preview slicing / "Show more") so the whole list is reorderable; auto-animate stays attached.

The order map is keyed per project now but keyed so it extends naturally to user-defined groups once folders land.

Verification

  • tsgo --noEmit passes (web + contracts).
  • Full web unit suite green (1057 tests); contracts 148. Added store tests (reorder up/down, first-drag seeding, no-ops, sync pruning, persistence round-trip) plus manual-order coverage for the delete-fallback and command-palette navigation helpers.
  • Manually tested on localhost: enabled Manual thread sort, dragged a thread within a project, confirmed the new order persists across reload, and that click / rename / multi-select still work.

🤖 Generated with Claude Code


Note

Low Risk
Client-only sidebar ordering and localStorage persistence; navigation/delete fallbacks are aligned with manual order but do not touch server auth or data.

Overview
Adds manual thread sort so users can drag thread rows within a project to define sidebar order, with the same persistence model as manual project reorder.

Contracts & sorting:SidebarThreadSortOrder gains "manual". orderItemsByPreferredIds moves to threadSort.ts; manual mode keeps store order and callers apply persisted scoped thread keys. getLatestThreadForProject and post-delete fallback navigation use that order so “open project” and delete routing match the first visible thread.

Persistence:uiStateStore adds threadOrderByProject and reorderThreads, saved to localStorage; syncThreads prunes removed threads.

Sidebar UX: When sort is manual, per-project DndContext/SortableContext enables vertical drag on rows (grab cursor, drop highlight), suppresses clicks during/after drag, and shows the full thread list (no “Show more” truncation). Thread-jump indices and prewarm lists follow the same manual ordering.

Call sites: Command palette project open paths pass flattened manual order into getLatestThreadForProject.

Reviewed by Cursor Bugbot for commit 1ed1189. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add drag-and-drop manual reordering of threads within sidebar projects

  • Adds a new 'manual' sort mode to SidebarThreadSortOrder and a reorderThreads reducer in uiStateStore.ts that persists per-project thread order to localStorage.
  • Wraps sidebar thread rows in a SortableThreadItem component using @dnd-kit, enabling vertical drag-and-drop reordering within each project in Sidebar.tsx.
  • Extends sortThreads and getLatestThreadForProject in threadSort.ts so manual mode preserves input order and resolves "latest" thread by manual position rather than timestamp.
  • Fallback navigation after thread deletion and command palette project opening both respect manual order when active.
  • syncThreads prunes stale thread keys from the saved order automatically when threads are removed.

Macroscope summarized 1ed1189.

Add a "Manual" thread sort mode that lets you drag a thread row to reorder
it among the other threads in the same project, mirroring the existing
project-reorder pattern.
- contracts: add "manual" to SidebarThreadSortOrder
- threadSort: sortThreads returns input order for "manual" so a user-defined
order can be layered on top (matches sortProjectsForSidebar)
- uiStateStore: persist threadOrderByProject directly (thread keys are stable,
no id->cwd remapping); add reorderThreads action and prune stale keys /
empty projects in syncThreads
- Sidebar: per-project DndContext + SortableContext + SortableThreadItem when
manual sort is active; suppress click/multi-select/rename during drag; apply
the order via orderItemsByPreferredIds and auto-expand the full list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jun 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21981e0e-a37c-489b-b623-0244d0809ec2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jun 13, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 83326f5. Configure here.

Comment threadapps/web/src/lib/threadSort.ts
@macroscopeapp

macroscopeappBot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (drag-and-drop thread reordering) with new state management and UI interactions across multiple components. New capabilities of this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Cursor Bugbot flagged that helpers picking a thread via sortThreads still
used raw store order under manual sort, so the delete-fallback navigation
and "open project from search" could jump to a thread that isn't first in
the sidebar's manual list.
- getLatestThreadForProject / getFallbackThreadIdAfterDelete now accept the
manual order (scoped thread keys) and apply orderItemsByPreferredIds when
sort is "manual", matching the sidebar's on-screen order
- move orderItemsByPreferredIds into lib/threadSort (re-exported from
Sidebar.logic) so the lib helper can use it without an import cycle
- callers (useThreadActions, CommandPalette) pass the flattened
threadOrderByProject; the per-project filter means only the relevant
project's keys match
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Jun 14, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Closing as part of backlog cleanup: this PR is stale, currently conflicting with main, has no approval, and has not had active remediation for 30+ days. If the change is still relevant, please rebase onto current main and request reopening or submit a focused current diff. Thank you for the contribution.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TheIcarusWings@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(sidebar): drag-and-drop reordering of threads within a project - #3069

Closed
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder
Closed

feat(sidebar): drag-and-drop reordering of threads within a project#3069
TheIcarusWings wants to merge 2 commits into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder

Conversation

@TheIcarusWings

@TheIcarusWingsTheIcarusWings commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

Adds drag-and-drop reordering of threads within their project in the sidebar — grab a thread row and move it among the other threads in the same project. This is reordering within one project, not moving threads between projects. It mirrors the existing project-reorder pattern (same @dnd-kit setup, same client-side persistence model).

Demo

Enable Sort threads → Manual, then drag a thread row to reorder it within its project. The list auto-expands so the whole project is reorderable, and the order persists across reloads.

Thread drag-and-drop reorder demo

New "Manual" thread sortBeforeAfter (persists on reload)

Changes

  • contracts: add "manual" to SidebarThreadSortOrder (alongside updated_at/created_at), matching SidebarProjectSortOrder. New "Manual" option in the "Sort threads" menu.
  • threadSort: sortThreads returns input order for "manual", so the user-defined order is layered on top via orderItemsByPreferredIds (same shape as sortProjectsForSidebar).
  • uiStateStore: new threadOrderByProject: Record<projectKey, threadKey[]>. Because scopedThreadKey is stable, it persists directly to localStorage (no id→cwd remapping like projects need). New reorderThreads action; syncThreads prunes stale thread keys and drops emptied projects.
  • Sidebar: per-project DndContext + SortableContext + SortableThreadItem rendered only when manual sort is active (non-DnD fallback otherwise). dragInProgress / suppressClickAfterDrag refs guard click, cmd/shift multi-select and rename so they don't fire on a drag. Manual mode auto-expands the full list (skips preview slicing / "Show more") so the whole list is reorderable; auto-animate stays attached.

The order map is keyed per project now but keyed so it extends naturally to user-defined groups once folders land.

Verification

  • tsgo --noEmit passes (web + contracts).
  • Full web unit suite green (1057 tests); contracts 148. Added store tests (reorder up/down, first-drag seeding, no-ops, sync pruning, persistence round-trip) plus manual-order coverage for the delete-fallback and command-palette navigation helpers.
  • Manually tested on localhost: enabled Manual thread sort, dragged a thread within a project, confirmed the new order persists across reload, and that click / rename / multi-select still work.

🤖 Generated with Claude Code


Note

Low Risk
Client-only sidebar ordering and localStorage persistence; navigation/delete fallbacks are aligned with manual order but do not touch server auth or data.

Overview
Adds manual thread sort so users can drag thread rows within a project to define sidebar order, with the same persistence model as manual project reorder.

Contracts & sorting:SidebarThreadSortOrder gains "manual". orderItemsByPreferredIds moves to threadSort.ts; manual mode keeps store order and callers apply persisted scoped thread keys. getLatestThreadForProject and post-delete fallback navigation use that order so “open project” and delete routing match the first visible thread.

Persistence:uiStateStore adds threadOrderByProject and reorderThreads, saved to localStorage; syncThreads prunes removed threads.

Sidebar UX: When sort is manual, per-project DndContext/SortableContext enables vertical drag on rows (grab cursor, drop highlight), suppresses clicks during/after drag, and shows the full thread list (no “Show more” truncation). Thread-jump indices and prewarm lists follow the same manual ordering.

Call sites: Command palette project open paths pass flattened manual order into getLatestThreadForProject.

Reviewed by Cursor Bugbot for commit 1ed1189. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add drag-and-drop manual reordering of threads within sidebar projects

  • Adds a new 'manual' sort mode to SidebarThreadSortOrder and a reorderThreads reducer in uiStateStore.ts that persists per-project thread order to localStorage.
  • Wraps sidebar thread rows in a SortableThreadItem component using @dnd-kit, enabling vertical drag-and-drop reordering within each project in Sidebar.tsx.
  • Extends sortThreads and getLatestThreadForProject in threadSort.ts so manual mode preserves input order and resolves "latest" thread by manual position rather than timestamp.
  • Fallback navigation after thread deletion and command palette project opening both respect manual order when active.
  • syncThreads prunes stale thread keys from the saved order automatically when threads are removed.

Macroscope summarized 1ed1189.

Add a "Manual" thread sort mode that lets you drag a thread row to reorder
it among the other threads in the same project, mirroring the existing
project-reorder pattern.
- contracts: add "manual" to SidebarThreadSortOrder
- threadSort: sortThreads returns input order for "manual" so a user-defined
order can be layered on top (matches sortProjectsForSidebar)
- uiStateStore: persist threadOrderByProject directly (thread keys are stable,
no id->cwd remapping); add reorderThreads action and prune stale keys /
empty projects in syncThreads
- Sidebar: per-project DndContext + SortableContext + SortableThreadItem when
manual sort is active; suppress click/multi-select/rename during drag; apply
the order via orderItemsByPreferredIds and auto-expand the full list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jun 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21981e0e-a37c-489b-b623-0244d0809ec2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actionsgithub-actionsBot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jun 13, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 83326f5. Configure here.

Comment threadapps/web/src/lib/threadSort.ts
@macroscopeapp

macroscopeappBot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (drag-and-drop thread reordering) with new state management and UI interactions across multiple components. New capabilities of this scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Cursor Bugbot flagged that helpers picking a thread via sortThreads still
used raw store order under manual sort, so the delete-fallback navigation
and "open project from search" could jump to a thread that isn't first in
the sidebar's manual list.
- getLatestThreadForProject / getFallbackThreadIdAfterDelete now accept the
manual order (scoped thread keys) and apply orderItemsByPreferredIds when
sort is "manual", matching the sidebar's on-screen order
- move orderItemsByPreferredIds into lib/threadSort (re-exported from
Sidebar.logic) so the lib helper can use it without an import cycle
- callers (useThreadActions, CommandPalette) pass the flattened
threadOrderByProject; the per-project filter means only the relevant
project's keys match
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actionsgithub-actionsBot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Jun 14, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Closing as part of backlog cleanup: this PR is stale, currently conflicting with main, has no approval, and has not had active remediation for 30+ days. If the change is still relevant, please rebase onto current main and request reopening or submit a focused current diff. Thank you for the contribution.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL500-999 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TheIcarusWings@juliusmarminge