Skip to content

Commit 0bcfc6a

Browse files
authored
🤖 refactor: remove generic links, keep only PR badge (#1658)
## Summary Removes the generic link detection/dropdown feature, keeping only the PR status badge in the workspace header. ## Changes **Removed:** - `LinksDropdown` component (showed chat-extracted URLs) - Generic link detection from `StreamingMessageAggregator` - `useWorkspaceLinks` hook from `WorkspaceStore` - `GenericLink` type, `extractUrls`, `categorizeUrl`, `deduplicateLinks` utilities - Link detection test files **Simplified:** - `WorkspaceLinks` now only renders `PRLinkBadge` - `links.ts` now only contains PR-related types (`GitHubPRLink`, `GitHubPRStatus`) ## PR badge behavior (unchanged) The PR badge is detected from the workspace's current branch via `gh pr view` - not from chat content. --- _Generated with `mux` • Model: `anthropic:claude-opus-4-5` • Thinking: `high` • Cost: `$49.60`_
1 parent 5b59d56 commit 0bcfc6a

File tree

8 files changed

+20
-784
lines changed

8 files changed

+20
-784
lines changed

src/browser/components/LinksDropdown.tsx

Lines changed: 0 additions & 123 deletions
This file was deleted.
Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,21 @@
11
/**
2-
* Component to display detected links in the workspace header.
3-
* Shows:
4-
* - PR badge: from branch-based detection (via `gh pr view`)
5-
* - Links dropdown: from chat-extracted links
2+
* Component to display the PR badge in the workspace header.
3+
* PR is detected from the workspace's current branch via `gh pr view`.
64
*/
75

8-
import { useWorkspaceLinks } from "@/browser/stores/WorkspaceStore";
96
import { useWorkspacePR } from "@/browser/stores/PRStatusStore";
10-
import type { GenericLink } from "@/common/types/links";
117
import { PRLinkBadge } from "./PRLinkBadge";
12-
import { LinksDropdown } from "./LinksDropdown";
138

149
interface WorkspaceLinksProps {
1510
workspaceId: string;
1611
}
1712

1813
export function WorkspaceLinks({ workspaceId }: WorkspaceLinksProps) {
19-
// Get links extracted from chat (for dropdown)
20-
const { detectedLinks } = useWorkspaceLinks(workspaceId);
21-
22-
// Get PR for this workspace's branch (not from chat)
2314
const workspacePR = useWorkspacePR(workspaceId);
2415

25-
// Filter out generic links (non-PR) for dropdown
26-
const genericLinks = detectedLinks.filter((link): link is GenericLink => link.type === "generic");
27-
28-
// Don't render anything if no PR and no links
29-
if (!workspacePR && genericLinks.length === 0) {
16+
if (!workspacePR) {
3017
return null;
3118
}
3219

33-
return (
34-
<div className="flex items-center gap-1">
35-
{/* Show the workspace's PR badge (from branch detection) */}
36-
{workspacePR && <PRLinkBadge prLink={workspacePR} />}
37-
38-
{/* Generic links dropdown (from chat) */}
39-
{genericLinks.length > 0 && <LinksDropdown links={genericLinks} />}
40-
</div>
41-
);
20+
return <PRLinkBadge prLink={workspacePR} />;
4221
}

src/browser/stores/WorkspaceStore.ts

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import type { WorkspaceChatMessage, WorkspaceStatsSnapshot } from "@/common/orpc
55
import type { RouterClient } from "@orpc/server";
66
import type { AppRouter } from "@/node/orpc/router";
77
import type { TodoItem } from "@/common/types/tools";
8-
import type { DetectedLink } from "@/common/types/links";
98
import { applyWorkspaceChatEventToAggregator } from "@/browser/utils/messages/applyWorkspaceChatEventToAggregator";
109
import { StreamingMessageAggregator } from "@/browser/utils/messages/StreamingMessageAggregator";
1110
import { updatePersistedState } from "@/browser/hooks/usePersistedState";
@@ -60,8 +59,6 @@ export interface WorkspaceState {
6059
// Live streaming stats (updated on each stream-delta)
6160
streamingTokenCount: number | undefined;
6261
streamingTPS: number | undefined;
63-
// Detected links from chat content (generic URLs for links dropdown)
64-
detectedLinks: DetectedLink[];
6562
}
6663

6764
/**
@@ -871,7 +868,6 @@ export class WorkspaceStore {
871868
pendingCompactionModel: aggregator.getPendingCompactionModel(),
872869
streamingTokenCount,
873870
streamingTPS,
874-
detectedLinks: aggregator.getDetectedLinks(),
875871
};
876872
});
877873
}
@@ -1873,46 +1869,6 @@ export function useWorkspaceSidebarState(workspaceId: string): WorkspaceSidebarS
18731869
);
18741870
}
18751871

1876-
/**
1877-
* State for detected links in a workspace (for the links dropdown).
1878-
* PR badge uses branch-based detection via useWorkspacePR instead.
1879-
*/
1880-
export interface WorkspaceLinksState {
1881-
detectedLinks: DetectedLink[];
1882-
}
1883-
1884-
// Cache for useWorkspaceLinks to return stable references
1885-
const workspaceLinksCache = new Map<string, WorkspaceLinksState>();
1886-
1887-
/**
1888-
* Hook to get detected links from a workspace.
1889-
* Separate from sidebar state to avoid re-renders on message changes.
1890-
* Returns cached references to avoid triggering infinite render loops.
1891-
*/
1892-
export function useWorkspaceLinks(workspaceId: string): WorkspaceLinksState {
1893-
const store = getStoreInstance();
1894-
1895-
return useSyncExternalStore(
1896-
(listener) => store.subscribeKey(workspaceId, listener),
1897-
() => {
1898-
const state = store.getWorkspaceState(workspaceId);
1899-
const existing = workspaceLinksCache.get(workspaceId);
1900-
1901-
// Return same reference if nothing meaningful changed
1902-
if (existing && existing.detectedLinks === state.detectedLinks) {
1903-
return existing;
1904-
}
1905-
1906-
// Create new state and cache it
1907-
const newState: WorkspaceLinksState = {
1908-
detectedLinks: state.detectedLinks,
1909-
};
1910-
workspaceLinksCache.set(workspaceId, newState);
1911-
return newState;
1912-
}
1913-
);
1914-
}
1915-
19161872
/**
19171873
* Hook to get UI-only live stdout/stderr for a running bash tool call.
19181874
*/

src/browser/stories/App.links.stories.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/**
2-
* PR link badge and links dropdown stories
2+
* PR status badge stories
33
*
44
* Shows various PR status states in the workspace header.
5+
* PR is detected from the workspace's current branch via `gh pr view`.
56
*/
67

78
import { appMeta, AppWithMocks, type AppStory } from "./meta.js";

0 commit comments

Comments
 (0)