diff --git a/packages/frontend/lib/connectUI.ts b/packages/frontend/lib/connectUI.ts index 92f44baa68..c7ae4469a1 100644 --- a/packages/frontend/lib/connectUI.ts +++ b/packages/frontend/lib/connectUI.ts @@ -2,17 +2,19 @@ import type { MaybePromise } from '@nangohq/types'; import type { ConnectUIEvent, ConnectUIEventToken } from './types'; export interface ConnectUIProps { - sessionToken: string; + sessionToken?: string; baseURL?: string; onEvent?: (event: ConnectUIEvent) => MaybePromise; } export class ConnectUI { + iframe: HTMLIFrameElement | null = null; + + private isReady = false; private listener: ((this: Window, ev: MessageEvent) => any) | null = null; private sessionToken; private baseURL; private onEvent; - iframe: HTMLIFrameElement | null = null; constructor({ sessionToken, baseURL = 'http://localhost:5173', onEvent }: ConnectUIProps) { this.sessionToken = sessionToken; @@ -59,8 +61,9 @@ export class ConnectUI { switch (evt.type) { case 'ready': { - const data: ConnectUIEventToken = { type: 'session_token', sessionToken: this.sessionToken }; - this.iframe?.contentWindow?.postMessage(data, '*'); + this.isReady = true; + this.sendSessionToken(); + break; } case 'close': { @@ -80,6 +83,16 @@ export class ConnectUI { window.addEventListener('message', this.listener, false); } + /** + * Set the session token and send it to the Connect UI iframe + */ + setSessionToken(sessionToken: string) { + this.sessionToken = sessionToken; + if (this.isReady) { + this.sendSessionToken(); + } + } + /** * Close UI and clear state */ @@ -92,4 +105,13 @@ export class ConnectUI { this.iframe = null; } } + + private sendSessionToken() { + if (!this.sessionToken) { + return; + } + + const data: ConnectUIEventToken = { type: 'session_token', sessionToken: this.sessionToken }; + this.iframe?.contentWindow?.postMessage(data, '*'); + } } diff --git a/packages/webapp/src/pages/Connection/List.tsx b/packages/webapp/src/pages/Connection/List.tsx index c295087b31..80fbe4e048 100644 --- a/packages/webapp/src/pages/Connection/List.tsx +++ b/packages/webapp/src/pages/Connection/List.tsx @@ -110,16 +110,11 @@ export default function ConnectionList() { }; }, [debouncedSearch]); - const onClickConnectUI = async () => { + const onClickConnectUI = () => { if (!environmentAndAccount) { return; } - const res = await apiConnectSessions(env); - if ('error' in res.json) { - return; - } - const nango = new Nango({ host: environmentAndAccount.host || baseUrl(), websocketsPath: environmentAndAccount.environment.websockets_path || '', @@ -128,7 +123,6 @@ export default function ConnectionList() { connectUI.current = nango.openConnectUI({ baseURL: globalEnv.connectUrl, - sessionToken: res.json.data.token, onEvent: (event) => { if (event.type === 'close') { // we refresh on close so user can see the diff @@ -136,6 +130,16 @@ export default function ConnectionList() { } } }); + + // We defer the token creation so the iframe can open and display a loading screen + // instead of blocking the main loop and no visual clue for the end user + setTimeout(async () => { + const res = await apiConnectSessions(env); + if ('error' in res.json) { + return; + } + connectUI.current!.setSessionToken(res.json.data.token); + }, 10); }; if (error) {