Skip to content

feat(desktop): separate tasks and pull requests in sidebar - #5975

Merged
saddlepaddle merged 4 commits into
ParadevAI:mainfrom
Roshvan:tasks_and_prs
Aug 4, 2026
Merged

saddlepaddle merged 4 commits into
ParadevAI:mainfrom
Roshvan:tasks_and_prs

Conversation

@Roshvan

@Roshvan Roshvan commented Jul 26, 2026 •

Copy link
Copy Markdown
Contributor

What & why

Closes #5974.

Tasks and pull requests are distinct workflows with different filters, empty states, and detail journeys, but the desktop dashboard placed them behind one “Tasks & PRs” destination and repeated the same choice as page-level tabs. This made the surface dense and gave navigation two competing sources of truth.

This change:

  • adds separate Tasks and Pull requests destinations to both dashboard sidebar variants
  • introduces a focused /pull-requests route with independent repository, state, and search context
  • keeps Linear and GitHub Issues as contextual sources inside Tasks
  • restores each workflow’s persisted filters when moving between destinations and detail panes
  • redirects legacy /tasks?type=prs and /tasks/pr/:prNumber links while preserving relevant filters
  • uses the serving host for remote projects and prevents stale rows from leaking between project/host pairs
  • follows cache-first TanStack DB rendering and distinguishes loading, empty, unavailable, invalid-link, and retry states
  • removes the redundant Tasks/Pull Requests page tabs and adds accessible active states, keyboard focus, reduced-motion behavior, and responsive toolbars/detail headers

How I tested it

  • bun run lint:fix
  • bun run lint — 0 warnings/errors
  • focused Bun tests across 8 changed-area files — 27 tests and 54 expectations pass
  • bun run typecheck — 35/35 tasks pass
  • bun run --cwd apps/desktop compile:app — production main, preload, and renderer builds pass
  • exact Electron/CDP journeys against this worktree at renderer 3085, API 3081, Electric proxy 3092, and CDP 9307:
    • seeded an isolated local-only project with 14 Linear tasks, 8 GitHub issues, and 8 pull requests through the real Electric and host-service data paths
    • clicked Tasks → Linear table → board → task detail → back → GitHub issues → issue detail → Pull requests → PR detail using visible UI controls
    • repeated the full journey at a 960×720 compact viewport
    • verified destination-specific context restoration, one active left-rail item, no combined navigation, no redundant primary tabs, valid detail routes, and wrapped compact task titles
    • captured and visually inspected all 14 populated list/board/detail screenshots

The full local bun test monorepo run was also attempted: 4,284 passed, while 129 failed with 20 harness errors in unrelated environment-dependent PTY, Electron preload, localStorage, relay, and git-process suites. The changed-area tests, lint, root typecheck, production compile, and exact-app flows are green; CI remains the repository-wide acceptance gate.

Before: combined destination and page tabs

Before: combined Tasks and PRs experience

Populated Tasks workflow

Table Board
Populated Tasks table with status groups, priorities, labels, and assignees Populated Tasks board with Backlog, Todo, In Progress, and Done columns

Task detail pane

Populated task detail with acceptance criteria and properties

Populated GitHub issues inside Tasks

Issue list Issue detail pane
Populated GitHub Issues source inside Tasks Populated GitHub issue detail pane

Populated Pull requests workflow

Pull request list Pull request detail pane
Populated Pull requests destination Populated pull request detail pane
Compact 960×720 verification with populated data

Tasks

Table Board Detail pane
Populated Tasks table at 960 by 720 Populated Tasks board at 960 by 720 Populated task detail with wrapped title at 960 by 720

GitHub issues

Issue list Issue detail pane
Populated GitHub Issues at 960 by 720 Populated GitHub issue detail at 960 by 720

Pull requests

Pull request list Pull request detail pane
Populated Pull requests at 960 by 720 Populated pull request detail at 960 by 720

Checklist

  • PR title follows conventional commits (type(scope): subject)
  • bun run lint and bun run typecheck pass
  • “Allow edits from maintainers” is checked on this fork PR

Open in Stage

Summary by cubic

Split Tasks and Pull requests into separate sidebar destinations with a new /pull-requests route and PR detail page. Each workflow has its own filters and search, picks the right serving host, task titles auto-resize while editing, and pull-requests views hide the empty TopBar while keeping window drag regions.

  • New Features

    • Added Tasks and Pull requests entries to both sidebars with clear active states.
    • New /pull-requests route with project filter, Open/All toggle, and search; filters persist independently from Tasks and are stored under pull-requests-filter-state.
    • New /pull-requests/$prNumber detail page with shared header/state UI, back navigation, external link, and “Add to workspace”.
    • GitHub Issues stay in Tasks with an Include closed toggle; PRs UI removed from Tasks.
    • Shared ProjectFilter, OpenClosedFilter, and WorkItemsSearch; each destination restores its own filters and drops stale rows when project/host changes.
    • Pull-requests views hide the global TopBar; the toolbar and shared detail header preserve window drag. Project filter shows a loading label while projects resolve.
  • Migration

    • Legacy routes /tasks?type=prs and /tasks/pr/:prNumber redirect to /pull-requests and /pull-requests/$prNumber (preserves search/state).
    • Existing Tasks filter state migrates safely (drops the PRs tab, adds “Include closed issues”); no user action needed.

Written for commit 62e9192. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added dedicated Pull requests navigation separate from Tasks.
    • Added pull-request search, project, and Open/All filters with persisted selections.
    • Added pull-request list and detail views with descriptions, authors, external links, and workspace actions.
    • Added support for viewing closed GitHub issues while preserving filters during navigation.
    • Added reusable search, filtering, loading, and error states across work-item views.
    • Task titles now support multiline editing.
  • Bug Fixes

    • Improved project loading, empty states, error handling, retries, accessibility, and detail navigation.
  • Tests

    • Added coverage for filtering, navigation, host selection, parameter validation, and migrations.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change separates Tasks and Pull requests into distinct dashboard destinations. It adds independent filters and routes, shared work-item controls, host-aware loading, detail pages, and compatibility redirects.

Changes

Tasks and Pull Requests separation

Layer / File(s) Summary
Shared controls, state, and routing utilities
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/*, .../hooks/useProjectHost/*, .../pull-requests/stores/*, .../tasks/stores/*, .../utils/*
Adds reusable search, state, detail, project, host-selection, filter-persistence, URL-serialization, and placeholder-query utilities.
Tasks and GitHub issues workflow
.../tasks/components/TasksView/*, .../tasks/issue/$issueNumber/page.tsx, .../tasks/layout.tsx, .../tasks/page.tsx, .../tasks/pr/$prNumber/page.tsx
Keeps Linear and GitHub Issues inside Tasks, adds open/all issue filtering, passes host readiness into issue content, updates detail navigation, and redirects legacy PR routes.
Pull-request routes, filters, and detail flow
.../pull-requests/layout.tsx, .../pull-requests/page.tsx, .../pull-requests/$prNumber/page.tsx, .../pull-requests/components/PullRequestsView/*
Adds the dedicated pull-request route, persisted project/state filters, debounced URL synchronization, host-aware fetching, list states, preview navigation, and detail rendering.
Dedicated sidebar navigation
.../DashboardSidebarHeader/DashboardSidebarHeader.tsx, .../WorkspaceSidebarHeader/WorkspaceSidebarHeader.tsx
Replaces the combined Tasks & PRs entry with separate Tasks and Pull requests buttons in collapsed and expanded layouts, including route state, filter restoration, gating, tooltips, and ARIA attributes.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

Tasks and issues

sequenceDiagram
  participant User
  participant TasksTopBar
  participant TasksView
  participant GitHubIssuesContent
  participant HostService
  User->>TasksTopBar: Select Issues or Open/All
  TasksTopBar->>TasksView: Update source and closed-state filters
  TasksView->>GitHubIssuesContent: Pass filters and host context
  GitHubIssuesContent->>HostService: Search GitHub issues
  HostService-->>GitHubIssuesContent: Return issue results
Loading

Pull requests

sequenceDiagram
  participant User
  participant PullRequestsView
  participant PullRequestsContent
  participant HostService
  participant PullRequestDetailPage
  User->>PullRequestsView: Change search, project, or state
  PullRequestsView->>PullRequestsContent: Pass synchronized filters
  PullRequestsContent->>HostService: Search pull requests
  HostService-->>PullRequestsContent: Return pull-request results
  User->>PullRequestsContent: Open a pull request
  PullRequestsContent->>PullRequestDetailPage: Navigate with PR number and filters
  PullRequestDetailPage->>HostService: Fetch pull-request details
  HostService-->>PullRequestDetailPage: Return detail data
Loading

Possibly related PRs

Suggested reviewers: kitenite

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR fully addresses issue #5974 requirements: separate left-rail Tasks and Pull Requests destinations, independent pull-request route with persisted filters, Linear/GitHub Issues inside Tasks, legacy URL redirects, and verified wide/compact Electron testing.
Out of Scope Changes check ✅ Passed All changes directly support the objective of separating Tasks and Pull Requests workflows. Sidebar updates, new routes, filter persistence, shared UI components, and legacy redirects are all within scope.
Title check ✅ Passed The title clearly summarizes the primary change: separating Tasks and Pull requests in the desktop sidebar.
Description check ✅ Passed The description is complete, explains the change and motivation, documents extensive testing, includes screenshots, and addresses the checklist.
✨ 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.

@ghost

ghost commented Jul 26, 2026 •

Copy link
Copy Markdown

@Roshvan
Roshvan marked this pull request as ready for review July 27, 2026 19:00

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🧹 Nitpick comments (1)
apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/issue/$issueNumber/page.tsx (1)

118-185: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider extracting the repeated header+state wrapper.

The <div className="flex min-h-0 flex-1 flex-col">{header}<WorkItemDetailState .../></div> wrapper is duplicated across five early-return branches. A small local helper would reduce repetition and keep future markup changes in one place.

♻️ Example extraction
const renderState = (props: React.ComponentProps<typeof WorkItemDetailState>) => (
	<div className="flex min-h-0 flex-1 flex-col">
		{header}
		<WorkItemDetailState {...props} />
	</div>
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/issue/`$issueNumber/page.tsx
around lines 118 - 185, Extract a local renderState helper near the early-return
logic, using WorkItemDetailState props to render the shared flex wrapper and
header. Replace the five duplicated header-plus-WorkItemDetailState branches for
invalid issue, missing project, unavailable project, unavailable host, loading,
and error states with calls to this helper, preserving each branch’s existing
props and messages.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/`$prNumber/page.tsx:
- Around line 168-181: Update the conditional in the pull request detail
rendering flow to prioritize existing data: render the data-first path whenever
data is present, even when error is an Error, and only show the
WorkItemDetailState fallback when data is absent. Preserve the existing error
message and refetch retry behavior for the no-data case.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/PullRequestsView.tsx`:
- Around line 31-49: Update the initialSearch synchronization effect in
PullRequestsView so it calls setSearchQuery only when initialSearch is supplied,
preserving the storedSearch value on mount when initialSearch is undefined. Keep
subsequent updates to an explicitly provided initialSearch unchanged.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/stores/pullRequestsFilterStore/pullRequestsFilterStore.ts`:
- Around line 40-48: Update pullRequestsSearchFromFilters to return
Partial<PullRequestsSearch> (or the equivalent route search schema type) instead
of Record<string, string>, preserving the existing filter mappings while keeping
state constrained to the route’s "open" | "all" values and enabling compile-time
validation at navigate callers.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/`$taskId/components/EditableTitle/EditableTitle.tsx:
- Around line 17-22: Update the useLayoutEffect in EditableTitle to recalculate
the textarea height whenever the title value changes, rather than only on mount.
Preserve the existing reset-to-auto and scrollHeight measurement sequence so
wrapped text expands correctly.

---

Nitpick comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/issue/`$issueNumber/page.tsx:
- Around line 118-185: Extract a local renderState helper near the early-return
logic, using WorkItemDetailState props to render the shared flex wrapper and
header. Replace the five duplicated header-plus-WorkItemDetailState branches for
invalid issue, missing project, unavailable project, unavailable host, loading,
and error states with calls to this helper, preserving each branch’s existing
props and messages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e357af2-ef72-4853-acf1-f9e463d74845

📥 Commits

Reviewing files that changed from the base of the PR and between 97e0446 and a953e13.

📒 Files selected for processing (46)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/OpenClosedFilter/OpenClosedFilter.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/OpenClosedFilter/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/ProjectFilter/ProjectFilter.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/ProjectFilter/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemDetailHeader/WorkItemDetailHeader.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemDetailHeader/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemDetailState/WorkItemDetailState.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemDetailState/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemsSearch/WorkItemsSearch.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemsSearch/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/hooks/useProjectHost/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/hooks/useProjectHost/useProjectHost.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/hooks/useProjectHost/useProjectHost.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/PullRequestsView.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/components/PullRequestsContent/PullRequestsContent.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/components/PullRequestsContent/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/components/PullRequestsTopBar/PullRequestsTopBar.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/components/PullRequestsTopBar/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/layout.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/stores/pullRequestsFilterStore/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/stores/pullRequestsFilterStore/pullRequestsFilterStore.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/stores/pullRequestsFilterStore/pullRequestsFilterStore.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/$taskId/components/EditableTitle/EditableTitle.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/$taskId/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/TasksView.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/TasksView.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/GitHubIssuesContent/GitHubIssuesContent.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/TasksTopBar/TasksTopBar.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/TasksTopBar/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/issue/$issueNumber/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/layout.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/pr/$prNumber/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/stores/tasks-filter-state.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/stores/tasks-filter-state.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/utils/parsePositiveIntegerParam/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/utils/parsePositiveIntegerParam/parsePositiveIntegerParam.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/utils/parsePositiveIntegerParam/parsePositiveIntegerParam.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/utils/shouldKeepWorkItemsPlaceholder/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/utils/shouldKeepWorkItemsPlaceholder/shouldKeepWorkItemsPlaceholder.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/utils/shouldKeepWorkItemsPlaceholder/shouldKeepWorkItemsPlaceholder.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/WorkspaceSidebarHeader.tsx

Comment on lines +168 to +181
if (error instanceof Error || !data) {
return (
<div className="flex min-h-0 flex-1 flex-col">
{header}
<WorkItemDetailState
message={
error instanceof Error ? error.message : "Pull request not found."
}
isError
onRetry={() => void refetch()}
/>
</div>
);
}

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In TanStack Query v5, does datafrom a previously successfuluseQueryfetch remain populated after a subsequent background refetch fails withretry: false?

💡 Result:

Yes, in TanStack Query v5, data from a previously successful fetch remains populated in the cache after a subsequent background refetch fails, even if retry: false is set [1][2]. When a background refetch fails, the query transitions into an error state [1][3]. However, the previously successfully fetched data is not discarded from the cache [1][2]. This behavior allows you to continue displaying the existing data to the user while the query is in an error state [2]. Key points regarding this behavior: 1. Data Persistence: The data property on the useQuery result object will still contain the last successful data [1][2]. 2. State Changes: The query status will update to error (isError becomes true), and the error property will be populated with the error object [1][3]. 3. Rendering: Because the data remains available, components that rely on the data can continue to render the stale information [2]. This is also why the default throwOnError behavior in TanStack Query typically does not propagate errors to an Error Boundary if existing data is available to show the user [2]. If you need to strictly clear the data upon a refetch error, you would need to implement custom logic, such as using the queryCache or specific state management patterns, as the default behavior preserves the existing cache entry [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/page.tsx"
echo "Exists: $(test -f "$file" && echo yes || echo no)"
wc -l "$file"
echo "--- relevant slice ---"
sed -n '130,195p' "$file" | nl -ba -v130
echo "--- query options search ---"
rg -n "useQuery|refetch|retry|placeholderData|keepPreviousData|onRetry|data =|error is|isLoading|isSuccess|status" "$file"

Repository: superset-sh/superset

Length of output: 199


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/page.tsx'
echo "Exists: $(test -f "$file" && echo yes || echo no)"
wc -l "$file"
echo "--- relevant slice ---"
sed -n '130,195p' "$file" | nl -ba -v130
echo "--- query options/consumer search ---"
rg -n "useQuery|refetch|retry|placeholderData|keepPreviousData|onRetry|data =|error is|isLoading|isSuccess|status" "$file"

Repository: superset-sh/superset

Length of output: 329


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/page.tsx'

echo "--- relevant slice (lines 130-195) ---"
awk 'NR>=130 && NR<=195 { printf "%5d\t%s\n", NR, $0 }' "$file"

echo "--- query options/consumer search ---"
grep -En "useQuery|refetch|retry|placeholderData|keepPreviousData|onRetry|data =|error is|isLoading|isSuccess|status" "$file" || true

Repository: superset-sh/superset

Length of output: 2654


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/page.tsx'

echo "--- query declaration slice ---"
awk 'NR>=45 && NR<=75 { printf "%5d\t%s\n", NR, $0 }' "$file"

echo "--- full relevant hook/render flow ---"
awk 'NR>=1 && NR<=200 { printf "%5d\t%s\n", NR, $0 }' "$file"

Repository: superset-sh/superset

Length of output: 8455


Prefer stale PR data over a transient refetch error.

TanStack Query keeps the last successful data even when a later refetch enters the error state, so error instanceof Error || !data can replace a fully rendered PR detail view with “Pull request not found” while valid content still exists. Render the data-first path whenever data is present, and only fall back to the error/not-found state when data is absent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/`$prNumber/page.tsx
around lines 168 - 181, Update the conditional in the pull request detail
rendering flow to prioritize existing data: render the data-first path whenever
data is present, even when error is an Error, and only show the
WorkItemDetailState fallback when data is absent. Preserve the existing error
message and refetch retry behavior for the no-data case.

Comment on lines +31 to +49
const [searchQuery, setSearchQuery] = useState(initialSearch ?? storedSearch);
const projectFilter = initialProject ?? storedProjectFilter;
const includeClosed =
initialState === undefined ? storedIncludeClosed : initialState === "all";
const debounceRef = useRef<ReturnType<typeof setTimeout>>(null);
const {
hostId: projectHostId,
isReady: areProjectsReady,
project: selectedProject,
projects: hostProjects,
} = useProjectHost(projectFilter);

useEffect(() => {
setSearchQuery(initialSearch ?? "");
}, [initialSearch]);

useEffect(() => {
storeSetSearch(searchQuery);
}, [searchQuery, storeSetSearch]);

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd -a 'layout.tsx|page.tsx' apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests
cat -n apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/layout.tsx apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/page.tsx 2>/dev/null

Repository: superset-sh/superset

Length of output: 2022


🏁 Script executed:

#!/bin/bash
set -e
fd -a 'PullRequestsView.tsx' apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components | while read -r f; do
  echo "===== $f ====="
  wc -l "$f"
  sed -n '1,180p' "$f"
done

sed -n '1,240p' apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/page.tsx
sed -n '1,220p' apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/layout.tsx

Repository: superset-sh/superset

Length of output: 6349


Persisted search filter is wiped on mount.

PullRequestsView seeds searchQuery from storedSearch, but the first effect runs setSearchQuery(initialSearch ?? "") on mount. Since /pull-requests/?search is validated to undefined when absent, opening the existing persisted search is immediately reset to "", and the following storeSetSearch(searchQuery) persists the empty value back to the filter store. Only override searchQuery when initialSearch is actually supplied.

🐛 Proposed fix
 	useEffect(() => {
-		setSearchQuery(initialSearch ?? "");
+		if (initialSearch !== undefined) {
+			setSearchQuery(initialSearch);
+		}
 	}, [initialSearch]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [searchQuery, setSearchQuery] = useState(initialSearch ?? storedSearch);
const projectFilter = initialProject ?? storedProjectFilter;
const includeClosed =
initialState === undefined ? storedIncludeClosed : initialState === "all";
const debounceRef = useRef<ReturnType<typeof setTimeout>>(null);
const {
hostId: projectHostId,
isReady: areProjectsReady,
project: selectedProject,
projects: hostProjects,
} = useProjectHost(projectFilter);
useEffect(() => {
setSearchQuery(initialSearch ?? "");
}, [initialSearch]);
useEffect(() => {
storeSetSearch(searchQuery);
}, [searchQuery, storeSetSearch]);
const [searchQuery, setSearchQuery] = useState(initialSearch ?? storedSearch);
const projectFilter = initialProject ?? storedProjectFilter;
const includeClosed =
initialState === undefined ? storedIncludeClosed : initialState === "all";
const debounceRef = useRef<ReturnType<typeof setTimeout>>(null);
const {
hostId: projectHostId,
isReady: areProjectsReady,
project: selectedProject,
projects: hostProjects,
} = useProjectHost(projectFilter);
useEffect(() => {
if (initialSearch !== undefined) {
setSearchQuery(initialSearch);
}
}, [initialSearch]);
useEffect(() => {
storeSetSearch(searchQuery);
}, [searchQuery, storeSetSearch]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/PullRequestsView.tsx`
around lines 31 - 49, Update the initialSearch synchronization effect in
PullRequestsView so it calls setSearchQuery only when initialSearch is supplied,
preserving the storedSearch value on mount when initialSearch is undefined. Keep
subsequent updates to an explicitly provided initialSearch unchanged.

Roshvan commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

@kiet @satyan Tasks and pull requests are different workflows, but today they’re grouped behind the same navigation and tabs. This gives each one its own sidebar section and remembers your filters when you switch between them—would love your thoughts.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx (1)

211-214: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Include pull requests in the explanatory comment.

onDashboardViewRoute now includes /pull-requests, but the comment lists only automations/tasks/workspaces. Update the comment so it documents all routes covered by hideTopBar.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx` around
lines 211 - 214, Update the explanatory comment near the hideTopBar logic to
include pull requests alongside automations, tasks, and workspaces, documenting
every route covered by onDashboardViewRoute.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx`:
- Around line 211-214: Update the explanatory comment near the hideTopBar logic
to include pull requests alongside automations, tasks, and workspaces,
documenting every route covered by onDashboardViewRoute.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6756a257-e857-4802-888b-5b36a4b6cc74

📥 Commits

Reviewing files that changed from the base of the PR and between e5d0454 and 555b2d6.

📒 Files selected for processing (7)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/ProjectFilter/ProjectFilter.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemDetailHeader/WorkItemDetailHeader.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/components/PullRequestsTopBar/PullRequestsTopBar.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/TasksView.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/TasksTopBar/TasksTopBar.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemDetailHeader/WorkItemDetailHeader.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/ProjectFilter/ProjectFilter.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/TasksTopBar/TasksTopBar.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/components/PullRequestsTopBar/PullRequestsTopBar.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/TasksView.tsx

@cubic-dev-ai cubic-dev-ai Bot 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.

13 issues found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/page.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/page.tsx:30">
P3: PR and GitHub issue detail flows now require parallel fixes whenever their shared loading, navigation, or workspace-linking behavior changes. A shared work-item detail shell or hook would keep these flows consistent and reduce maintenance drift.

(Based on your team's feedback about avoiding duplicated business logic.)</violation>
</file>

<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/WorkspaceSidebarHeader.tsx">

<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/WorkspaceSidebarHeader.tsx:56">
P2: Opening a pull-request detail URL directly (or after a reload) and clicking the Pull requests rail item drops the detail's search/project/state context because this navigation uses the store instead of the current detail route search. Preserving the route search or synchronizing it from the detail page would keep the workflow context intact.</violation>
</file>

<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/$taskId/components/EditableTitle/EditableTitle.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/$taskId/components/EditableTitle/EditableTitle.tsx:18">
P2: Resizing the task detail pane can clip wrapped title lines or leave excess vertical space because the autosize effect does not rerun when the textarea width changes. Observing the element with `ResizeObserver` (or another width-change signal) would keep the height synchronized.</violation>

<violation number="2" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/$taskId/components/EditableTitle/EditableTitle.tsx:47">
P2: Pasting a multiline title can now persist embedded newlines even though this editor still treats Enter as a save/blur action. Normalizing line breaks before updating would preserve the previous single-line title behavior.</violation>
</file>

<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemDetailState/WorkItemDetailState.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemDetailState/WorkItemDetailState.tsx:19">
P3: When `isError` is true, the `role="alert"` (implicit `aria-live="assertive"`) conflicts with the static `aria-live="polite"`. Explicit `aria-live` takes precedence over implicit values from the role, so error announcements may be treated as polite instead of assertive, reducing responsiveness for time-sensitive errors. Other `role="alert"` usages in the codebase omit `aria-live` entirely. Consider removing `aria-live` from the container or making it conditional so it's omitted when `role="alert"` is active.</violation>
</file>

<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemsSearch/WorkItemsSearch.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemsSearch/WorkItemsSearch.tsx:22">
P3: The Pull Requests search inherits a shortcut whose user-facing label and description explicitly say it only focuses the task search, so keyboard-shortcut settings and discoverability are incorrect on `/pull-requests`. A destination-neutral work-items shortcut (or a dedicated PR shortcut with matching metadata) would keep the new destination’s context accurate.</violation>
</file>

<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/GitHubIssuesContent/GitHubIssuesContent.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/GitHubIssuesContent/GitHubIssuesContent.tsx:102">
P3: The GitHub issues and pull-request destinations now maintain nearly identical query, placeholder, pagination, and rendering-state workflows separately, so fixes to scoping or retry behavior can diverge between destinations. A shared work-item query/render helper would keep these flows consistent.

(Based on your team's feedback about avoiding duplicated business logic.)</violation>

<violation number="2" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/GitHubIssuesContent/GitHubIssuesContent.tsx:106">
P2: Changing the serving host can leave selected GitHub issues from the previous host in the toolbar while the list has reloaded from the new host, allowing actions to use stale issue URLs and metadata. The selection reset should follow the same host-scoped lifecycle as the query, not only project changes.</violation>

<violation number="3" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/GitHubIssuesContent/GitHubIssuesContent.tsx:224">
P2: Offline remote projects do not reach this unavailable state: cached project host IDs can remain selected while `useHostUrl` still returns a relay URL, so the request runs and exposes a generic fetch error instead of the dedicated unavailable-device message. Propagating host reachability into this component, or selecting only reachable serving hosts, would make the state accurate.</violation>
</file>

<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx:155">
P2: Both `DashboardSidebarHeader` and `WorkspaceSidebarHeader` now contain near-identical `handlePullRequestsClick` functions, identical `usePullRequestsFilterStore` subscriptions, and identical `includeClosedIssues` additions to `handleTasksClick`. This duplicated business logic means any future change to PR navigation behavior (adding a filter param, changing the gate feature, or altering the navigate call) must be applied in two separate files. The pattern matches prior team feedback about extracting shared navigation logic into a hook or helper to keep behavior consistent and reduce cognitive load when changes are made.</violation>
</file>

<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/PullRequestsView.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/PullRequestsView.tsx:65">
P3: Filter synchronization and project fallback behavior are duplicated between `PullRequestsView` and `TasksView`, which makes navigation fixes easy to apply to one destination but miss the other. A shared workflow hook/helper for the common debounce, URL serialization, store synchronization, and first-project selection would keep the two destinations consistent while retaining separate filter stores.</violation>

<violation number="2" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/PullRequestsView.tsx:128">
P2: Changing the repository or state filter can be reverted by a pending search URL update: the 300 ms callback retains the previous `buildSearch` closure, while these immediate filter handlers do not cancel it. Cancel the pending debounce before non-search navigation (or have the callback read the latest route/filter state) so the final URL reflects the user's last action.</violation>
</file>

<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/TasksView.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/TasksView.tsx:267">
P2: A pending search debounce can overwrite the URL state selected by the GitHub issue Open/All filter: typing and then toggling the filter within 300 ms can remove `state=all` from the URL. Clearing the existing search debounce before this immediate navigation would keep the URL and issue-state selection consistent.</violation>
</file>

Tip: cubic used a learning from your PR history. Let your coding agent read cubic learnings directly with the cubic MCP.

Re-trigger cubic

includeClosedIssues: lastIncludeClosedIssues,
} = useTasksFilterStore();
const {
search: lastPullRequestsSearch,

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.

P2: Opening a pull-request detail URL directly (or after a reload) and clicking the Pull requests rail item drops the detail's search/project/state context because this navigation uses the store instead of the current detail route search. Preserving the route search or synchronizing it from the detail page would keep the workflow context intact.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarHeader/WorkspaceSidebarHeader.tsx, line 56:

<comment>Opening a pull-request detail URL directly (or after a reload) and clicking the Pull requests rail item drops the detail's search/project/state context because this navigation uses the store instead of the current detail route search. Preserving the route search or synchronizing it from the detail page would keep the workflow context intact.</comment>

<file context>
@@ -41,7 +50,13 @@ export function WorkspaceSidebarHeader({
+		includeClosedIssues: lastIncludeClosedIssues,
 	} = useTasksFilterStore();
+	const {
+		search: lastPullRequestsSearch,
+		projectFilter: lastPullRequestsProjectFilter,
+		includeClosed: lastPullRequestsIncludeClosed,
</file context>


return (
<input
<textarea

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.

P2: Pasting a multiline title can now persist embedded newlines even though this editor still treats Enter as a save/blur action. Normalizing line breaks before updating would preserve the previous single-line title behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/$taskId/components/EditableTitle/EditableTitle.tsx, line 47:

<comment>Pasting a multiline title can now persist embedded newlines even though this editor still treats Enter as a save/blur action. Normalizing line breaks before updating would preserve the previous single-line title behavior.</comment>

<file context>
@@ -35,15 +44,16 @@ export function EditableTitle({ value, onSave }: EditableTitleProps) {
 
 	return (
-		<input
+		<textarea
 			ref={inputRef}
-			type="text"
</file context>

Comment on lines +18 to +23
useLayoutEffect(() => {
const input = inputRef.current;
if (!input) return;
input.style.height = "auto";
input.style.height = `${input.scrollHeight}px`;
}, [localValue]);

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.

P2: Resizing the task detail pane can clip wrapped title lines or leave excess vertical space because the autosize effect does not rerun when the textarea width changes. Observing the element with ResizeObserver (or another width-change signal) would keep the height synchronized.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/$taskId/components/EditableTitle/EditableTitle.tsx, line 18:

<comment>Resizing the task detail pane can clip wrapped title lines or leave excess vertical space because the autosize effect does not rerun when the textarea width changes. Observing the element with `ResizeObserver` (or another width-change signal) would keep the height synchronized.</comment>

<file context>
@@ -7,13 +7,21 @@ interface EditableTitleProps {
 	}, [value]);
 
+	// biome-ignore lint/correctness/useExhaustiveDependencies: re-measure height whenever the rendered text changes
+	useLayoutEffect(() => {
+		const input = inputRef.current;
+		if (!input) return;
</file context>
Suggested change
useLayoutEffect(() => {
const input = inputRef.current;
if (!input) return;
input.style.height = "auto";
input.style.height = `${input.scrollHeight}px`;
}, [localValue]);
useLayoutEffect(() => {
const input = inputRef.current;
if (!input) return;
const resize = () => {
input.style.height = "auto";
input.style.height = `${input.scrollHeight}px`;
};
resize();
const observer = new ResizeObserver(resize);
observer.observe(input);
return () => observer.disconnect();
}, [localValue]);

);
}

if (!hostId || !hostUrl) {

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.

P2: Offline remote projects do not reach this unavailable state: cached project host IDs can remain selected while useHostUrl still returns a relay URL, so the request runs and exposes a generic fetch error instead of the dedicated unavailable-device message. Propagating host reachability into this component, or selecting only reachable serving hosts, would make the state accurate.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/GitHubIssuesContent/GitHubIssuesContent.tsx, line 224:

<comment>Offline remote projects do not reach this unavailable state: cached project host IDs can remain selected while `useHostUrl` still returns a relay URL, so the request runs and exposes a generic fetch error instead of the dedicated unavailable-device message. Propagating host reachability into this component, or selecting only reachable serving hosts, would make the state accurate.</comment>

<file context>
@@ -195,7 +209,26 @@ export function GitHubIssuesContent({
+		);
+	}
+
+	if (!hostId || !hostUrl) {
+		return (
+			<div className="flex h-full items-center justify-center p-8">
</file context>

});
};

const handlePullRequestsClick = () => {

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.

P2: Both DashboardSidebarHeader and WorkspaceSidebarHeader now contain near-identical handlePullRequestsClick functions, identical usePullRequestsFilterStore subscriptions, and identical includeClosedIssues additions to handleTasksClick. This duplicated business logic means any future change to PR navigation behavior (adding a filter param, changing the gate feature, or altering the navigate call) must be applied in two separate files. The pattern matches prior team feedback about extracting shared navigation logic into a hook or helper to keep behavior consistent and reduce cognitive load when changes are made.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsx, line 156:

<comment>Both `DashboardSidebarHeader` and `WorkspaceSidebarHeader` now contain near-identical `handlePullRequestsClick` functions, identical `usePullRequestsFilterStore` subscriptions, and identical `includeClosedIssues` additions to `handleTasksClick`. This duplicated business logic means any future change to PR navigation behavior (adding a filter param, changing the gate feature, or altering the navigate call) must be applied in two separate files. The pattern matches prior team feedback about extracting shared navigation logic into a hook or helper to keep behavior consistent and reduce cognitive load when changes are made.</comment>

<file context>
@@ -132,6 +147,20 @@ export function DashboardSidebarHeader({
+		});
+	};
+
+	const handlePullRequestsClick = () => {
+		gateFeature(GATED_FEATURES.TASKS, () => {
+			navigate({
</file context>

component: PullRequestDetailPage,
});

function PullRequestDetailPage() {

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.

P3: PR and GitHub issue detail flows now require parallel fixes whenever their shared loading, navigation, or workspace-linking behavior changes. A shared work-item detail shell or hook would keep these flows consistent and reduce maintenance drift.

(Based on your team's feedback about avoiding duplicated business logic.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/page.tsx, line 30:

<comment>PR and GitHub issue detail flows now require parallel fixes whenever their shared loading, navigation, or workspace-linking behavior changes. A shared work-item detail shell or hook would keep these flows consistent and reduce maintenance drift.

(Based on your team's feedback about avoiding duplicated business logic.) </comment>

<file context>
@@ -0,0 +1,229 @@
+	component: PullRequestDetailPage,
+});
+
+function PullRequestDetailPage() {
+	const { prNumber: prNumberRaw } = Route.useParams();
+	const prNumber = parsePositiveIntegerParam(prNumberRaw);
</file context>

onRetry,
}: WorkItemDetailStateProps) {
return (
<div

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.

P3: When isError is true, the role="alert" (implicit aria-live="assertive") conflicts with the static aria-live="polite". Explicit aria-live takes precedence over implicit values from the role, so error announcements may be treated as polite instead of assertive, reducing responsiveness for time-sensitive errors. Other role="alert" usages in the codebase omit aria-live entirely. Consider removing aria-live from the container or making it conditional so it's omitted when role="alert" is active.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemDetailState/WorkItemDetailState.tsx, line 19:

<comment>When `isError` is true, the `role="alert"` (implicit `aria-live="assertive"`) conflicts with the static `aria-live="polite"`. Explicit `aria-live` takes precedence over implicit values from the role, so error announcements may be treated as polite instead of assertive, reducing responsiveness for time-sensitive errors. Other `role="alert"` usages in the codebase omit `aria-live` entirely. Consider removing `aria-live` from the container or making it conditional so it's omitted when `role="alert"` is active.</comment>

<file context>
@@ -0,0 +1,39 @@
+	onRetry,
+}: WorkItemDetailStateProps) {
+	return (
+		<div
+			className={cn(
+				"flex flex-1 flex-col items-center justify-center gap-3 px-6 py-10 text-center text-sm",
</file context>

const inputRef = useRef<HTMLInputElement>(null);

useHotkey(
"FOCUS_TASK_SEARCH",

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.

P3: The Pull Requests search inherits a shortcut whose user-facing label and description explicitly say it only focuses the task search, so keyboard-shortcut settings and discoverability are incorrect on /pull-requests. A destination-neutral work-items shortcut (or a dedicated PR shortcut with matching metadata) would keep the new destination’s context accurate.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/WorkItemsSearch/WorkItemsSearch.tsx, line 22:

<comment>The Pull Requests search inherits a shortcut whose user-facing label and description explicitly say it only focuses the task search, so keyboard-shortcut settings and discoverability are incorrect on `/pull-requests`. A destination-neutral work-items shortcut (or a dedicated PR shortcut with matching metadata) would keep the new destination’s context accurate.</comment>

<file context>
@@ -0,0 +1,52 @@
+	const inputRef = useRef<HTMLInputElement>(null);
+
+	useHotkey(
+		"FOCUS_TASK_SEARCH",
+		() => {
+			inputRef.current?.focus();
</file context>

staleTime: 30_000,
gcTime: 10 * 60_000,
placeholderData: keepPreviousData,
placeholderData: (previousData, previousQuery) => {

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.

P3: The GitHub issues and pull-request destinations now maintain nearly identical query, placeholder, pagination, and rendering-state workflows separately, so fixes to scoping or retry behavior can diverge between destinations. A shared work-item query/render helper would keep these flows consistent.

(Based on your team's feedback about avoiding duplicated business logic.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/tasks/components/TasksView/components/GitHubIssuesContent/GitHubIssuesContent.tsx, line 102:

<comment>The GitHub issues and pull-request destinations now maintain nearly identical query, placeholder, pagination, and rendering-state workflows separately, so fixes to scoping or retry behavior can diverge between destinations. A shared work-item query/render helper would keep these flows consistent.

(Based on your team's feedback about avoiding duplicated business logic.) </comment>

<file context>
@@ -99,7 +99,15 @@ export function GitHubIssuesContent({
 		staleTime: 30_000,
 		gcTime: 10 * 60_000,
-		placeholderData: keepPreviousData,
+		placeholderData: (previousData, previousQuery) => {
+			return shouldKeepWorkItemsPlaceholder(
+				previousQuery?.queryKey,
</file context>

[includeClosed, projectFilter, searchQuery],
);

const syncSearchToUrl = useCallback(

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.

P3: Filter synchronization and project fallback behavior are duplicated between PullRequestsView and TasksView, which makes navigation fixes easy to apply to one destination but miss the other. A shared workflow hook/helper for the common debounce, URL serialization, store synchronization, and first-project selection would keep the two destinations consistent while retaining separate filter stores.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/components/PullRequestsView/PullRequestsView.tsx, line 65:

<comment>Filter synchronization and project fallback behavior are duplicated between `PullRequestsView` and `TasksView`, which makes navigation fixes easy to apply to one destination but miss the other. A shared workflow hook/helper for the common debounce, URL serialization, store synchronization, and first-project selection would keep the two destinations consistent while retaining separate filter stores.</comment>

<file context>
@@ -0,0 +1,171 @@
+		[includeClosed, projectFilter, searchQuery],
+	);
+
+	const syncSearchToUrl = useCallback(
+		(query: string) => {
+			if (debounceRef.current) clearTimeout(debounceRef.current);
</file context>

Roshvan and others added 3 commits August 3, 2026 16:36
…ests views

Extends the hidden-TopBar treatment from ParadevAI#6023 to the new /pull-requests
route: the layout hides the strip there, and the pull-requests toolbar and
shared work-item detail header carry the window-drag filler leaves.

Claude-Session: https://claude.ai/code/session_01WPvjzEZjYWFoedQUiCKBPb
@saddlepaddle
saddlepaddle merged commit 61f9410 into ParadevAI:main Aug 4, 2026
12 checks passed
Kitenite added a commit that referenced this pull request Aug 5, 2026
* docs: weekly update for PRs merged 2026-07-29 to 2026-08-05

- tasks.mdx: Tasks and Pull requests are now separate sidebar destinations
  with independent persisted filters; GitHub Issues as a Tasks source (#5975)
- workspaces.mdx: prompt history popover (#6083), typed-name-seeds-branch
  behavior (#6129), right-click import of untracked worktrees (#6097),
  bulk workspace actions section (#6021)
- automations.mdx: inline Retry and Retry all for failed runs (#6139)
- keyboard-shortcuts.mdx: Open Command Palette ⌘⇧K and Check Resources ⌘⇧U (#6037)
- setup-teardown-scripts.mdx: experimental wait-for-setup-before-agents
  setting (#5925)

* docs(recipes): add agent-driven Superset recipe for the shipped superset:* skills

Covers the workflow from #6181: standup, automate, doctor, setup,
feedback, and orchestrate driven from the agent you're already in.

* docs(recipes): focus agent-driven recipe on orchestrate and automate, defer to skills page

* docs(recipes): defer orchestrate teaching to its page, center recipe on the automate arc

* docs: address review — branch name is slugified, retry scoping, Linear source wording
@Roshvan
Roshvan deleted the tasks_and_prs branch October 11, 2026 14:50
AviPeltz added a commit that referenced this pull request Oct 29, 2026
…hes (#8440)

* feat(desktop): add a refresh button to the workspace PR pane

The button refetches the PR detail and marks the linked PR, review
threads, and Code tab diff and threads stale, so the pane reloads what
is on screen. It spins while the detail fetch runs.

* perf(desktop): stop the PR view re-rendering and refetching unchanged data

- Code tab: each file's version is a hash of its patch, its thread
  annotations, and its collapsed state, so a 30 s thread poll with no
  change redraws no files (155 of 155 before on a 155-file PR). This
  replaces the composer and collapse version counters.
- Code tab: give each file a content-addressed cacheKey. Without one,
  @pierre/diffs falls back to the file name and keeps rendering a file's
  old content after its patch changes.
- Code tab: no diff refetch on window focus. The pane's refresh button
  covers a manual reload.
- Memoize MarkdownRenderer and PullRequestMarkdown and stop spreading
  the detail query result, so a refetch with identical data re-renders
  no comment bodies (40 before on a 10-body summary).
- Persist page 1 of the default PR list again. #5975 moved the list off
  the persisted "tasks" key, so every cold start waited 4-5 s on the
  spinner.
- Move hashString to _dashboard/utils now that two areas use it.

* fix(desktop): scope PR pane refresh to its PR and harden Code tab keys

- The refresh spinner watches only this PR's detail query, and refresh
  invalidates only this PR's diff and threads, so two PR panes no longer
  spin or reload each other.
- Code tab file keys use the Changes pane's content key (two independent
  FNV-1a hashes plus length) instead of one 32-bit hash. buildContentKey
  moves to _dashboard/utils for both.
- Keep window-focus refetch for the diff: the standalone PR page has no
  refresh button, and an identical refetch now redraws no files. The
  workspace client already turns focus refetch off for the pane.

* fix(desktop): refresh only the pane's own diff and thread queries

The refresh button matched diff and thread queries by PR number, so a PR
with the same number in another project was refetched too. The Code tab
query keys now come from shared builders, and refresh invalidates the
exact keys for this pane's project, host, repository and PR.

* feat(desktop): put the PR refresh button next to copy link

The refresh button moves from the workspace pane's header into the PR
detail's action bar, before copy link, so it shows on the Pull requests
page and in the workspace pane. useRefreshPullRequest holds the refresh
logic for both: it refetches the detail and invalidates this PR's exact
diff and thread queries, and the workspace's linked-PR queries.

* fix(desktop): match refresh's diff key to the Code tab and narrow list persistence

- Refresh derives the diff key's repository from the PR's own URL, the
  same way the Code tab does, so a PR whose URL names another repository
  is still refreshed.
- The PR list is persisted only without an author or review filter, as
  with search: those are typed in and unbounded. Page 1 of each of the
  three state tabs is still saved.

* fix(desktop): key the persisted PR list by host id, not host URL

The host-service port can change between launches, so a list key that
included the host URL never matched the persisted page after a restart
and the list fell back to the spinner. The key now relies on target.key,
which already names the host by id and its projects, and the previous
rows placeholder compares that key alone. Measured on a restart where
the port changed: rows 0.66 s after the shell is ready, no spinner.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Separate Tasks and Pull Requests into dedicated sidebar destinations

2 participants