Skip to content

Commit d85c8ce

Browse files
celestial-vaultElephant Lumps
andauthored
migrate historyButtonClicked to protobus (RooCodeInc#3977)
* migrate historyButtonClicked * add webview provider type filtering --------- Co-authored-by: Elephant Lumps <[email protected]>
1 parent b38994f commit d85c8ce

File tree

6 files changed

+114
-21
lines changed

6 files changed

+114
-21
lines changed

.changeset/giant-items-tan.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"claude-dev": minor
3+
---
4+
5+
Migrate historyButtonClicked to protobus

proto/ui.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,7 @@ service UiService {
3131

3232
// Subscribe to MCP button clicked events
3333
rpc subscribeToMcpButtonClicked(WebviewProviderTypeRequest) returns (stream Empty);
34+
35+
// Subscribe to history button click events
36+
rpc subscribeToHistoryButtonClicked(WebviewProviderTypeRequest) returns (stream Empty);
3437
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { Controller } from "../index"
2+
import { Empty } from "@shared/proto/common"
3+
import { WebviewProviderType, WebviewProviderTypeRequest } from "@shared/proto/ui"
4+
import { StreamingResponseHandler, getRequestRegistry } from "../grpc-handler"
5+
6+
// Keep track of active subscriptions with their provider type
7+
const activeHistoryButtonClickedSubscriptions = new Map<StreamingResponseHandler, WebviewProviderType>()
8+
9+
/**
10+
* Subscribe to history button clicked events
11+
* @param controller The controller instance
12+
* @param request The webview provider type request
13+
* @param responseStream The streaming response handler
14+
* @param requestId The ID of the request (passed by the gRPC handler)
15+
*/
16+
export async function subscribeToHistoryButtonClicked(
17+
controller: Controller,
18+
request: WebviewProviderTypeRequest,
19+
responseStream: StreamingResponseHandler,
20+
requestId?: string,
21+
): Promise<void> {
22+
// Extract the provider type from the request
23+
const providerType = request.providerType
24+
console.log(`[DEBUG] set up history button subscription for ${WebviewProviderType[providerType]} webview`)
25+
26+
// Add this subscription to the active subscriptions with its provider type
27+
activeHistoryButtonClickedSubscriptions.set(responseStream, providerType)
28+
29+
// Register cleanup when the connection is closed
30+
const cleanup = () => {
31+
activeHistoryButtonClickedSubscriptions.delete(responseStream)
32+
}
33+
34+
// Register the cleanup function with the request registry if we have a requestId
35+
if (requestId) {
36+
getRequestRegistry().registerRequest(requestId, cleanup, { type: "history_button_clicked_subscription" }, responseStream)
37+
}
38+
}
39+
40+
/**
41+
* Send a history button clicked event to all active subscribers
42+
* @param webviewType Optional filter to send only to a specific webview type
43+
*/
44+
export async function sendHistoryButtonClickedEvent(webviewType?: WebviewProviderType): Promise<void> {
45+
// Send the event to all active subscribers matching the webview type (if specified)
46+
const promises = Array.from(activeHistoryButtonClickedSubscriptions.entries()).map(async ([responseStream, providerType]) => {
47+
// Skip subscribers of different types if webview type is specified
48+
if (webviewType !== undefined && webviewType !== providerType) {
49+
return
50+
}
51+
52+
try {
53+
const event: Empty = {}
54+
await responseStream(
55+
event,
56+
false, // Not the last message
57+
)
58+
} catch (error) {
59+
console.error(`Error sending history button clicked event to ${WebviewProviderType[providerType]}:`, error)
60+
// Remove the subscription if there was an error
61+
activeHistoryButtonClickedSubscriptions.delete(responseStream)
62+
}
63+
})
64+
65+
await Promise.all(promises)
66+
}

src/extension.ts

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import { telemetryService } from "./services/posthog/telemetry/TelemetryService"
1818
import { v4 as uuidv4 } from "uuid"
1919
import { WebviewProviderType as WebviewProviderTypeEnum } from "@shared/proto/ui"
2020
import { WebviewProviderType } from "./shared/webview/types"
21+
import { sendHistoryButtonClickedEvent } from "./core/controller/ui/subscribeToHistoryButtonClicked"
22+
2123
/*
2224
Built using https://github.com/microsoft/vscode-webview-ui-toolkit
2325
@@ -175,21 +177,14 @@ export async function activate(context: vscode.ExtensionContext) {
175177
)
176178

177179
context.subscriptions.push(
178-
vscode.commands.registerCommand("cline.historyButtonClicked", (webview: any) => {
179-
WebviewProvider.getAllInstances().forEach((instance) => {
180-
const openHistory = async (instance?: WebviewProvider) => {
181-
instance?.controller.postMessageToWebview({
182-
type: "action",
183-
action: "historyButtonClicked",
184-
})
185-
}
186-
const isSidebar = !webview
187-
if (isSidebar) {
188-
openHistory(WebviewProvider.getSidebarInstance())
189-
} else {
190-
WebviewProvider.getTabInstances().forEach(openHistory)
191-
}
192-
})
180+
vscode.commands.registerCommand("cline.historyButtonClicked", async (webview: any) => {
181+
console.log("[DEBUG] historyButtonClicked", webview)
182+
// Pass the webview type to the event sender
183+
const isSidebar = !webview
184+
const webviewType = isSidebar ? WebviewProviderTypeEnum.SIDEBAR : WebviewProviderTypeEnum.TAB
185+
186+
// Send event to all subscribers using the gRPC streaming method
187+
await sendHistoryButtonClickedEvent(webviewType)
193188
}),
194189
)
195190

src/shared/ExtensionMessage.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ export interface ExtensionMessage {
4141
action?:
4242
| "chatButtonClicked"
4343
| "settingsButtonClicked"
44-
| "historyButtonClicked"
4544
| "didBecomeVisible"
4645
| "accountLogoutClicked"
4746
| "accountButtonClicked"

webview-ui/src/context/ExtensionStateContext.tsx

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,6 @@ export const ExtensionStateContextProvider: React.FC<{
196196
case "settingsButtonClicked":
197197
navigateToSettings()
198198
break
199-
case "historyButtonClicked":
200-
navigateToHistory()
201-
break
202199
case "accountButtonClicked":
203200
navigateToAccount()
204201
break
@@ -272,9 +269,14 @@ export const ExtensionStateContextProvider: React.FC<{
272269
// References to store subscription cancellation functions
273270
const stateSubscriptionRef = useRef<(() => void) | null>(null)
274271
const mcpButtonUnsubscribeRef = useRef<(() => void) | null>(null)
272+
const historyButtonClickedSubscriptionRef = useRef<(() => void) | null>(null)
275273

276274
// Subscribe to state updates and UI events using the gRPC streaming API
277275
useEffect(() => {
276+
// Determine the webview provider type
277+
const webviewType =
278+
window.WEBVIEW_PROVIDER_TYPE === "sidebar" ? WebviewProviderTypeEnum.SIDEBAR : WebviewProviderTypeEnum.TAB
279+
278280
// Set up state subscription
279281
stateSubscriptionRef.current = StateServiceClient.subscribeToState(EmptyRequest.create({}), {
280282
onResponse: (response) => {
@@ -348,8 +350,7 @@ export const ExtensionStateContextProvider: React.FC<{
348350
// Subscribe to MCP button clicked events with webview type
349351
mcpButtonUnsubscribeRef.current = UiServiceClient.subscribeToMcpButtonClicked(
350352
WebviewProviderTypeRequest.create({
351-
providerType:
352-
window.WEBVIEW_PROVIDER_TYPE === "sidebar" ? WebviewProviderTypeEnum.SIDEBAR : WebviewProviderTypeEnum.TAB,
353+
providerType: webviewType,
353354
}),
354355
{
355356
onResponse: () => {
@@ -365,6 +366,26 @@ export const ExtensionStateContextProvider: React.FC<{
365366
},
366367
)
367368

369+
// Set up history button clicked subscription with webview type
370+
historyButtonClickedSubscriptionRef.current = UiServiceClient.subscribeToHistoryButtonClicked(
371+
WebviewProviderTypeRequest.create({
372+
providerType: webviewType,
373+
}),
374+
{
375+
onResponse: () => {
376+
// When history button is clicked, navigate to history view
377+
console.log("[DEBUG] Received history button clicked event from gRPC stream")
378+
navigateToHistory()
379+
},
380+
onError: (error) => {
381+
console.error("Error in history button clicked subscription:", error)
382+
},
383+
onComplete: () => {
384+
console.log("History button clicked subscription completed")
385+
},
386+
},
387+
)
388+
368389
// Still send the webviewDidLaunch message for other initialization
369390
vscode.postMessage({ type: "webviewDidLaunch" })
370391

@@ -378,6 +399,10 @@ export const ExtensionStateContextProvider: React.FC<{
378399
mcpButtonUnsubscribeRef.current()
379400
mcpButtonUnsubscribeRef.current = null
380401
}
402+
if (historyButtonClickedSubscriptionRef.current) {
403+
historyButtonClickedSubscriptionRef.current()
404+
historyButtonClickedSubscriptionRef.current = null
405+
}
381406
}
382407
}, [])
383408

0 commit comments

Comments
 (0)