Skip to content

Commit e0227a2

Browse files
authored
telemetry(amazonq): webview didLoadModule
1 parent 0d20307 commit e0227a2

File tree

4 files changed

+52
-9
lines changed

4 files changed

+52
-9
lines changed

packages/core/src/login/webview/vue/amazonq/backend_amazonq.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import { ToolkitError } from '../../../../shared/errors'
2323
import { withTelemetryContext } from '../../../../shared/telemetry/util'
2424
import { builderIdStartUrl } from '../../../../auth/sso/constants'
2525
import { RegionProfile } from '../../../../codewhisperer/models/model'
26+
import { randomUUID } from '../../../../shared/crypto'
27+
import globals from '../../../../shared/extensionGlobals'
2628
import { telemetry } from '../../../../shared/telemetry/telemetry'
2729
import { ProfileSwitchIntent } from '../../../../codewhisperer/region/regionProfileManager'
2830

@@ -162,6 +164,13 @@ export class AmazonQLoginWebview extends CommonAuthWebview {
162164
return
163165
} else if (featureAuthStates.amazonQ === 'pendingProfileSelection') {
164166
this.authState = 'PENDING_PROFILE_SELECTION'
167+
// possible that user starts with "profile selection" state therefore the timeout for auth flow should be disposed otherwise will emit failure
168+
this.loadMetadata?.loadTimeout?.dispose()
169+
this.loadMetadata = {
170+
traceId: randomUUID(),
171+
loadTimeout: undefined,
172+
start: globals.clock.Date.now(),
173+
}
165174
return
166175
}
167176
this.authState = 'LOGIN'

packages/core/src/login/webview/vue/backend.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export abstract class CommonAuthWebview extends VueWebview {
6969
* @param errorMessage IF an error is caught on the frontend, this is the message. It will result in a failure metric.
7070
* Otherwise we assume success.
7171
*/
72-
public setUiReady(state: 'login' | 'reauth', errorMessage?: string) {
72+
public setUiReady(state: 'login' | 'reauth' | 'selectProfile', errorMessage?: string) {
7373
if (errorMessage) {
7474
this.setLoadFailure(state, errorMessage)
7575
} else {

packages/core/src/login/webview/vue/regionProfileSelector.vue

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@
7979
<button id="signout" v-on:click="signout">Sign Out</button>
8080
</template>
8181
<template v-else>
82-
<button class="continue-button" v-on:click="onClickContinue()">Continue</button>
82+
<button
83+
class="continue-button"
84+
id="profile-selection-continue-button"
85+
v-on:click="onClickContinue()"
86+
>
87+
Continue
88+
</button>
8389
</template>
8490
</div>
8591
</div>
@@ -162,6 +168,18 @@ export default defineComponent({
162168
},
163169
},
164170
})
171+
172+
/**
173+
* The ID of the element we will use to determine that the UI has completed its initial load.
174+
*
175+
* This makes assumptions that we will be in a certain state of the UI (eg showing a form vs. a loading bar).
176+
* So if the UI flow changes, this may need to be updated.
177+
*/
178+
export function getReadyElementId() {
179+
// On every initial load, we ASSUME that the user will always be in the connection selection state,
180+
// which is why we specifically look for this button.
181+
return 'profile-selection-continue-button'
182+
}
165183
</script>
166184
<style scoped>
167185
@import './base.css';

packages/core/src/login/webview/vue/root.vue

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ configure app to AMAZONQ if for Amazon Q login
2323
import { PropType, defineComponent } from 'vue'
2424
import Login, { getReadyElementId as getLoginReadyElementId } from './login.vue'
2525
import Reauthenticate, { getReadyElementId as getReauthReadyElementId } from './reauthenticate.vue'
26-
import RegionProfileSelector from './regionProfileSelector.vue'
26+
import RegionProfileSelector, { getReadyElementId as getSelectProfileReadyElementId } from './regionProfileSelector.vue'
2727
import { AuthFlowState, FeatureId } from './types'
2828
import { WebviewClientFactory } from '../../../webviews/client'
2929
import { CommonAuthWebview } from './backend'
@@ -69,6 +69,11 @@ export default defineComponent({
6969
})
7070
}
7171
},
72+
async updated() {
73+
if (didLoad) {
74+
handleLoaded()
75+
}
76+
},
7277
methods: {
7378
async refreshAuthState() {
7479
await client.refreshAuthState()
@@ -78,6 +83,9 @@ export default defineComponent({
7883
if (this.authFlowState === 'LOGIN') {
7984
;(window as any).uiState = 'login'
8085
;(window as any).uiReadyElementId = getLoginReadyElementId()
86+
} else if (this.authFlowState === 'PENDING_PROFILE_SELECTION') {
87+
;(window as any).uiState = 'selectProfile'
88+
;(window as any).uiReadyElementId = getSelectProfileReadyElementId()
8189
} else if (this.authFlowState && this.authFlowState !== undefined) {
8290
;(window as any).uiState = 'reauth'
8391
;(window as any).uiReadyElementId = getReauthReadyElementId()
@@ -90,12 +98,14 @@ export default defineComponent({
9098
9199
// ---- START ---- The following handles the process of indicating the UI has loaded successfully.
92100
// TODO: Move this in to a reusable class for other webviews, it feels a bit messy here
93-
let didSetReady = false
101+
const didPageSetReady: { auth: boolean; selectProfile: boolean } = { auth: false, selectProfile: false }
94102
95103
// Setup error handlers to report. This may not actually be able to catch certain errors that we'd expect,
96104
// so this may have to be revisited.
97105
window.onerror = function (message) {
98-
if (didSetReady) {
106+
const uiState = (window as any).uiState
107+
const page: 'auth' | 'selectProfile' = uiState === 'login' || uiState === 'reauth' ? 'auth' : 'selectProfile'
108+
if (didPageSetReady[page]) {
99109
return
100110
}
101111
@@ -104,7 +114,9 @@ window.onerror = function (message) {
104114
document.addEventListener(
105115
'error',
106116
(e) => {
107-
if (didSetReady) {
117+
const uiState = (window as any).uiState
118+
const page: 'auth' | 'selectProfile' = uiState === 'login' || uiState === 'reauth' ? 'auth' : 'selectProfile'
119+
if (didPageSetReady[page]) {
108120
return
109121
}
110122
@@ -119,7 +131,9 @@ window.addEventListener('load', () => {
119131
})
120132
const handleLoaded = () => {
121133
// in case some unexpected behavior triggers this flow again, skip since we already emitted for this instance
122-
if (didSetReady) {
134+
const uiState = (window as any).uiState
135+
const page: 'auth' | 'selectProfile' = uiState === 'login' || uiState === 'reauth' ? 'auth' : 'selectProfile'
136+
if (didPageSetReady[page]) {
123137
return
124138
}
125139
@@ -131,9 +145,11 @@ const handleLoaded = () => {
131145
setUiReady((window as any).uiState)
132146
}
133147
}
134-
const setUiReady = (state: 'login' | 'reauth', errorMessage?: string) => {
148+
const setUiReady = (state: 'login' | 'reauth' | 'selectProfile', errorMessage?: string) => {
135149
client.setUiReady(state, errorMessage)
136-
didSetReady = true
150+
151+
const page = state === 'selectProfile' ? 'selectProfile' : 'auth'
152+
didPageSetReady[page] = true
137153
}
138154
// ---- END ----
139155
</script>

0 commit comments

Comments
 (0)