diff --git a/src/vs/workbench/contrib/chat/browser/widget/chatPetWidget.ts b/src/vs/workbench/contrib/chat/browser/widget/chatPetWidget.ts index 6d0e21d96b199b..2b576d34203d85 100644 --- a/src/vs/workbench/contrib/chat/browser/widget/chatPetWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/widget/chatPetWidget.ts @@ -82,6 +82,10 @@ function getSpriteSources(): Record, source: string): boolean { + return image.getAttribute('src') === source; +} + export function getChatPetBaseState(hasActiveRequest: boolean, needsInput: boolean, idleExpired: boolean): ChatPetState { if (needsInput) { return 'clapping'; @@ -435,7 +439,7 @@ export class ChatPetWidget extends Disposable { private _renderState(state: ChatPetState, restart = false): void { const sources = getSpriteSources()[state]; const source = this._motionReduced ? sources.reducedMotion : sources.animated; - if (!restart && this._activeImage?.src === source) { + if (!restart && this._activeImage && isChatPetImageSource(this._activeImage, source)) { this._button.element.dataset.state = state; this._renderedState = state; return; @@ -454,7 +458,7 @@ export class ChatPetWidget extends Disposable { } private _onImageLoad(image: HTMLImageElement): void { - if (image !== this._pendingImage || image.src !== this._pendingSource || this._pendingState === undefined) { + if (image !== this._pendingImage || this._pendingSource === undefined || !isChatPetImageSource(image, this._pendingSource) || this._pendingState === undefined) { return; } diff --git a/src/vs/workbench/contrib/chat/test/browser/widget/chatPetWidget.test.ts b/src/vs/workbench/contrib/chat/test/browser/widget/chatPetWidget.test.ts index e65ecda6f0218c..f19fd311df1df5 100644 --- a/src/vs/workbench/contrib/chat/test/browser/widget/chatPetWidget.test.ts +++ b/src/vs/workbench/contrib/chat/test/browser/widget/chatPetWidget.test.ts @@ -5,7 +5,7 @@ import assert from 'assert'; import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../../base/test/common/utils.js'; -import { doesChatPetStateTrackCursor, getChatPetBaseState, getChatPetBuddyName, getChatPetClickInteraction, getChatPetGazeDirection, getChatPetHorizontalPosition, getChatPetSpriteName } from '../../../browser/widget/chatPetWidget.js'; +import { doesChatPetStateTrackCursor, getChatPetBaseState, getChatPetBuddyName, getChatPetClickInteraction, getChatPetGazeDirection, getChatPetHorizontalPosition, getChatPetSpriteName, isChatPetImageSource } from '../../../browser/widget/chatPetWidget.js'; suite('ChatPetWidget', () => { @@ -99,6 +99,20 @@ suite('ChatPetWidget', () => { ]); }); + test('matches sprite sources without browser URL normalization', () => { + const source = 'vscode-file://vscode-app/Applications/Visual Studio Code - Insiders.app/pet.gif'; + const image = document.createElement('img'); + image.src = source; + + assert.deepStrictEqual([ + image.src === source, + isChatPetImageSource(image, source), + ], [ + false, + true, + ]); + }); + test('maps the cursor to pixel-snapped gaze directions', () => { assert.deepStrictEqual([ getChatPetGazeDirection(10, 0, 0, 0),