Skip to content

Commit 2358ce1

Browse files
authored
fix(amazonq): duplicate messages in flare chat (aws#7097)
## Problem when the flare chat panel refreshes on log in/log out, the message listener never gets disposed of, causing the next webview instantiation to have two message listeners that are forwarding messages to the ui ## Solution dispose of the message listener when the webview gets disposed --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 44b6933 commit 2358ce1

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

packages/amazonq/src/lsp/chat/activation.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ import { AuthUtil } from 'aws-core-vscode/codewhisperer'
1515
import { updateConfigurationRequestType } from '@aws/language-server-runtimes/protocol'
1616

1717
export async function activate(languageClient: LanguageClient, encryptionKey: Buffer, mynahUIPath: string) {
18+
const disposables = globals.context.subscriptions
19+
1820
// Make sure we've sent an auth profile to the language server before even initializing the UI
1921
await updateProfile(languageClient)
2022

2123
const provider = new AmazonQChatViewProvider(mynahUIPath)
2224

23-
globals.context.subscriptions.push(
25+
disposables.push(
2426
window.registerWebviewViewProvider(AmazonQChatViewProvider.viewType, provider, {
2527
webviewOptions: {
2628
retainContextWhenHidden: true,
@@ -36,12 +38,18 @@ export async function activate(languageClient: LanguageClient, encryptionKey: Bu
3638
registerLanguageServerEventListener(languageClient, provider)
3739

3840
provider.onDidResolveWebview(() => {
39-
if (provider.webview) {
40-
DefaultAmazonQAppInitContext.instance.getAppsToWebViewMessageListener().onMessage((msg) => {
41-
provider.webview?.postMessage(msg).then(undefined, (e) => {
42-
getLogger().error('webView.postMessage failed: %s', (e as Error).message)
43-
})
41+
const disposable = DefaultAmazonQAppInitContext.instance.getAppsToWebViewMessageListener().onMessage((msg) => {
42+
provider.webview?.postMessage(msg).then(undefined, (e) => {
43+
getLogger().error('webView.postMessage failed: %s', (e as Error).message)
4444
})
45+
})
46+
47+
if (provider.webviewView) {
48+
disposables.push(
49+
provider.webviewView.onDidDispose(() => {
50+
disposable.dispose()
51+
})
52+
)
4553
}
4654

4755
registerMessageListeners(languageClient, provider, encryptionKey)
@@ -50,7 +58,7 @@ export async function activate(languageClient: LanguageClient, encryptionKey: Bu
5058
// register event listeners from the legacy agent flow
5159
await registerLegacyChatListeners(globals.context)
5260

53-
globals.context.subscriptions.push(
61+
disposables.push(
5462
AuthUtil.instance.regionProfileManager.onDidChangeRegionProfile(async () => {
5563
void updateProfile(languageClient)
5664
await provider.refreshWebview()

packages/amazonq/src/lsp/chat/webviewProvider.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
import {
77
EventEmitter,
88
CancellationToken,
9-
Webview,
109
WebviewView,
1110
WebviewViewProvider,
1211
WebviewViewResolveContext,
1312
Uri,
13+
Webview,
1414
} from 'vscode'
1515
import * as path from 'path'
1616
import {
@@ -29,7 +29,8 @@ export class AmazonQChatViewProvider implements WebviewViewProvider {
2929
private readonly onDidResolveWebviewEmitter = new EventEmitter<void>()
3030
public readonly onDidResolveWebview = this.onDidResolveWebviewEmitter.event
3131

32-
webview: Webview | undefined
32+
webviewView?: WebviewView
33+
webview?: Webview
3334

3435
connectorAdapterPath?: string
3536
uiPath?: string
@@ -41,8 +42,6 @@ export class AmazonQChatViewProvider implements WebviewViewProvider {
4142
context: WebviewViewResolveContext,
4243
_token: CancellationToken
4344
) {
44-
this.webview = webviewView.webview
45-
4645
const lspDir = Uri.parse(LanguageServerResolver.defaultDir())
4746
const dist = Uri.joinPath(globals.context.extensionUri, 'dist')
4847

@@ -77,7 +76,16 @@ export class AmazonQChatViewProvider implements WebviewViewProvider {
7776

7877
webviewView.webview.html = await this.getWebviewContent()
7978

79+
this.webviewView = webviewView
80+
this.webview = this.webviewView.webview
81+
8082
this.onDidResolveWebviewEmitter.fire()
83+
globals.context.subscriptions.push(
84+
this.webviewView.onDidDispose(() => {
85+
this.webviewView = undefined
86+
this.webview = undefined
87+
})
88+
)
8189
performance.mark(amazonqMark.open)
8290
}
8391

0 commit comments

Comments
 (0)