migrate historyButtonClicked to protobus (#3977)

* migrate historyButtonClicked

* add webview provider type filtering

---------

Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>
This commit is contained in:
Evan 2025-06-02 15:23:19 -07:00 committed by GitHub
parent b38994f1e8
commit d85c8ceeb2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 114 additions and 21 deletions

View File

@ -0,0 +1,5 @@
---
"claude-dev": minor
---
Migrate historyButtonClicked to protobus

View File

@ -31,4 +31,7 @@ service UiService {
// Subscribe to MCP button clicked events
rpc subscribeToMcpButtonClicked(WebviewProviderTypeRequest) returns (stream Empty);
// Subscribe to history button click events
rpc subscribeToHistoryButtonClicked(WebviewProviderTypeRequest) returns (stream Empty);
}

View File

@ -0,0 +1,66 @@
import { Controller } from "../index"
import { Empty } from "@shared/proto/common"
import { WebviewProviderType, WebviewProviderTypeRequest } from "@shared/proto/ui"
import { StreamingResponseHandler, getRequestRegistry } from "../grpc-handler"
// Keep track of active subscriptions with their provider type
const activeHistoryButtonClickedSubscriptions = new Map<StreamingResponseHandler, WebviewProviderType>()
/**
* Subscribe to history button clicked events
* @param controller The controller instance
* @param request The webview provider type request
* @param responseStream The streaming response handler
* @param requestId The ID of the request (passed by the gRPC handler)
*/
export async function subscribeToHistoryButtonClicked(
controller: Controller,
request: WebviewProviderTypeRequest,
responseStream: StreamingResponseHandler,
requestId?: string,
): Promise<void> {
// Extract the provider type from the request
const providerType = request.providerType
console.log(`[DEBUG] set up history button subscription for ${WebviewProviderType[providerType]} webview`)
// Add this subscription to the active subscriptions with its provider type
activeHistoryButtonClickedSubscriptions.set(responseStream, providerType)
// Register cleanup when the connection is closed
const cleanup = () => {
activeHistoryButtonClickedSubscriptions.delete(responseStream)
}
// Register the cleanup function with the request registry if we have a requestId
if (requestId) {
getRequestRegistry().registerRequest(requestId, cleanup, { type: "history_button_clicked_subscription" }, responseStream)
}
}
/**
* Send a history button clicked event to all active subscribers
* @param webviewType Optional filter to send only to a specific webview type
*/
export async function sendHistoryButtonClickedEvent(webviewType?: WebviewProviderType): Promise<void> {
// Send the event to all active subscribers matching the webview type (if specified)
const promises = Array.from(activeHistoryButtonClickedSubscriptions.entries()).map(async ([responseStream, providerType]) => {
// Skip subscribers of different types if webview type is specified
if (webviewType !== undefined && webviewType !== providerType) {
return
}
try {
const event: Empty = {}
await responseStream(
event,
false, // Not the last message
)
} catch (error) {
console.error(`Error sending history button clicked event to ${WebviewProviderType[providerType]}:`, error)
// Remove the subscription if there was an error
activeHistoryButtonClickedSubscriptions.delete(responseStream)
}
})
await Promise.all(promises)
}

View File

@ -18,6 +18,8 @@ import { telemetryService } from "./services/posthog/telemetry/TelemetryService"
import { v4 as uuidv4 } from "uuid"
import { WebviewProviderType as WebviewProviderTypeEnum } from "@shared/proto/ui"
import { WebviewProviderType } from "./shared/webview/types"
import { sendHistoryButtonClickedEvent } from "./core/controller/ui/subscribeToHistoryButtonClicked"
/*
Built using https://github.com/microsoft/vscode-webview-ui-toolkit
@ -175,21 +177,14 @@ export async function activate(context: vscode.ExtensionContext) {
)
context.subscriptions.push(
vscode.commands.registerCommand("cline.historyButtonClicked", (webview: any) => {
WebviewProvider.getAllInstances().forEach((instance) => {
const openHistory = async (instance?: WebviewProvider) => {
instance?.controller.postMessageToWebview({
type: "action",
action: "historyButtonClicked",
})
}
const isSidebar = !webview
if (isSidebar) {
openHistory(WebviewProvider.getSidebarInstance())
} else {
WebviewProvider.getTabInstances().forEach(openHistory)
}
})
vscode.commands.registerCommand("cline.historyButtonClicked", async (webview: any) => {
console.log("[DEBUG] historyButtonClicked", webview)
// Pass the webview type to the event sender
const isSidebar = !webview
const webviewType = isSidebar ? WebviewProviderTypeEnum.SIDEBAR : WebviewProviderTypeEnum.TAB
// Send event to all subscribers using the gRPC streaming method
await sendHistoryButtonClickedEvent(webviewType)
}),
)

View File

@ -41,7 +41,6 @@ export interface ExtensionMessage {
action?:
| "chatButtonClicked"
| "settingsButtonClicked"
| "historyButtonClicked"
| "didBecomeVisible"
| "accountLogoutClicked"
| "accountButtonClicked"

View File

@ -196,9 +196,6 @@ export const ExtensionStateContextProvider: React.FC<{
case "settingsButtonClicked":
navigateToSettings()
break
case "historyButtonClicked":
navigateToHistory()
break
case "accountButtonClicked":
navigateToAccount()
break
@ -272,9 +269,14 @@ export const ExtensionStateContextProvider: React.FC<{
// References to store subscription cancellation functions
const stateSubscriptionRef = useRef<(() => void) | null>(null)
const mcpButtonUnsubscribeRef = useRef<(() => void) | null>(null)
const historyButtonClickedSubscriptionRef = useRef<(() => void) | null>(null)
// Subscribe to state updates and UI events using the gRPC streaming API
useEffect(() => {
// Determine the webview provider type
const webviewType =
window.WEBVIEW_PROVIDER_TYPE === "sidebar" ? WebviewProviderTypeEnum.SIDEBAR : WebviewProviderTypeEnum.TAB
// Set up state subscription
stateSubscriptionRef.current = StateServiceClient.subscribeToState(EmptyRequest.create({}), {
onResponse: (response) => {
@ -348,8 +350,7 @@ export const ExtensionStateContextProvider: React.FC<{
// Subscribe to MCP button clicked events with webview type
mcpButtonUnsubscribeRef.current = UiServiceClient.subscribeToMcpButtonClicked(
WebviewProviderTypeRequest.create({
providerType:
window.WEBVIEW_PROVIDER_TYPE === "sidebar" ? WebviewProviderTypeEnum.SIDEBAR : WebviewProviderTypeEnum.TAB,
providerType: webviewType,
}),
{
onResponse: () => {
@ -365,6 +366,26 @@ export const ExtensionStateContextProvider: React.FC<{
},
)
// Set up history button clicked subscription with webview type
historyButtonClickedSubscriptionRef.current = UiServiceClient.subscribeToHistoryButtonClicked(
WebviewProviderTypeRequest.create({
providerType: webviewType,
}),
{
onResponse: () => {
// When history button is clicked, navigate to history view
console.log("[DEBUG] Received history button clicked event from gRPC stream")
navigateToHistory()
},
onError: (error) => {
console.error("Error in history button clicked subscription:", error)
},
onComplete: () => {
console.log("History button clicked subscription completed")
},
},
)
// Still send the webviewDidLaunch message for other initialization
vscode.postMessage({ type: "webviewDidLaunch" })
@ -378,6 +399,10 @@ export const ExtensionStateContextProvider: React.FC<{
mcpButtonUnsubscribeRef.current()
mcpButtonUnsubscribeRef.current = null
}
if (historyButtonClickedSubscriptionRef.current) {
historyButtonClickedSubscriptionRef.current()
historyButtonClickedSubscriptionRef.current = null
}
}
}, [])