From c63648a1b007eaa2a0cfc2ae27ca364f77545535 Mon Sep 17 00:00:00 2001 From: Joseph Garrone Date: Sat, 19 Oct 2024 02:19:41 +0200 Subject: [PATCH] #693 #692 --- ...skeysConditionalAuthenticate.useScript.tsx | 9 +++++- ...LoginRecoveryAuthnCodeConfig.useScript.tsx | 9 +++++- .../pages/WebauthnAuthenticate.useScript.tsx | 9 +++++- .../pages/WebauthnRegister.useScript.tsx | 9 +++++- src/tools/waitForElementMountedOnDom.ts | 30 +++++++++++++++++++ 5 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 src/tools/waitForElementMountedOnDom.ts diff --git a/src/login/pages/LoginPasskeysConditionalAuthenticate.useScript.tsx b/src/login/pages/LoginPasskeysConditionalAuthenticate.useScript.tsx index 9cd1c867..4807c6c1 100644 --- a/src/login/pages/LoginPasskeysConditionalAuthenticate.useScript.tsx +++ b/src/login/pages/LoginPasskeysConditionalAuthenticate.useScript.tsx @@ -2,6 +2,7 @@ import { useEffect } from "react"; import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags"; import { assert } from "keycloakify/tools/assert"; import { KcContext } from "keycloakify/login/KcContext/KcContext"; +import { waitForElementMountedOnDom } from "keycloakify/tools/waitForElementMountedOnDom"; type KcContextLike = { url: { @@ -67,6 +68,12 @@ export function useScript(params: { authButtonId: string; kcContext: KcContextLi return; } - insertScriptTags(); + (async () => { + await waitForElementMountedOnDom({ + elementId: authButtonId + }); + + insertScriptTags(); + })(); }, [isFetchingTranslations]); } diff --git a/src/login/pages/LoginRecoveryAuthnCodeConfig.useScript.tsx b/src/login/pages/LoginRecoveryAuthnCodeConfig.useScript.tsx index 8a5f9586..ef882462 100644 --- a/src/login/pages/LoginRecoveryAuthnCodeConfig.useScript.tsx +++ b/src/login/pages/LoginRecoveryAuthnCodeConfig.useScript.tsx @@ -1,5 +1,6 @@ import { useEffect } from "react"; import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags"; +import { waitForElementMountedOnDom } from "keycloakify/tools/waitForElementMountedOnDom"; type I18nLike = { msgStr: (key: "recovery-codes-download-file-header" | "recovery-codes-download-file-description" | "recovery-codes-download-file-date") => string; @@ -137,6 +138,12 @@ export function useScript(params: { olRecoveryCodesListId: string; i18n: I18nLik return; } - insertScriptTags(); + (async () => { + await waitForElementMountedOnDom({ + elementId: olRecoveryCodesListId + }); + + insertScriptTags(); + })(); }, [isFetchingTranslations]); } diff --git a/src/login/pages/WebauthnAuthenticate.useScript.tsx b/src/login/pages/WebauthnAuthenticate.useScript.tsx index bc8fde5a..0ffde595 100644 --- a/src/login/pages/WebauthnAuthenticate.useScript.tsx +++ b/src/login/pages/WebauthnAuthenticate.useScript.tsx @@ -2,6 +2,7 @@ import { useEffect } from "react"; import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags"; import { assert } from "keycloakify/tools/assert"; import { KcContext } from "keycloakify/login/KcContext/KcContext"; +import { waitForElementMountedOnDom } from "keycloakify/tools/waitForElementMountedOnDom"; type KcContextLike = { url: { @@ -59,6 +60,12 @@ export function useScript(params: { authButtonId: string; kcContext: KcContextLi return; } - insertScriptTags(); + (async () => { + await waitForElementMountedOnDom({ + elementId: authButtonId + }); + + insertScriptTags(); + })(); }, [isFetchingTranslations]); } diff --git a/src/login/pages/WebauthnRegister.useScript.tsx b/src/login/pages/WebauthnRegister.useScript.tsx index c1d8cd66..98f3dfa7 100644 --- a/src/login/pages/WebauthnRegister.useScript.tsx +++ b/src/login/pages/WebauthnRegister.useScript.tsx @@ -2,6 +2,7 @@ import { useEffect } from "react"; import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags"; import { assert } from "keycloakify/tools/assert"; import { KcContext } from "keycloakify/login/KcContext/KcContext"; +import { waitForElementMountedOnDom } from "keycloakify/tools/waitForElementMountedOnDom"; type KcContextLike = { url: { @@ -88,6 +89,12 @@ export function useScript(params: { authButtonId: string; kcContext: KcContextLi return; } - insertScriptTags(); + (async () => { + await waitForElementMountedOnDom({ + elementId: authButtonId + }); + + insertScriptTags(); + })(); }, [isFetchingTranslations]); } diff --git a/src/tools/waitForElementMountedOnDom.ts b/src/tools/waitForElementMountedOnDom.ts new file mode 100644 index 00000000..08934f74 --- /dev/null +++ b/src/tools/waitForElementMountedOnDom.ts @@ -0,0 +1,30 @@ +export async function waitForElementMountedOnDom(params: { + elementId: string; +}): Promise { + const { elementId } = params; + + const getElement = () => document.getElementById(elementId); + + const element = getElement(); + + if (element === null) { + let prElementPresentInTheDom_resolve: () => void; + const prElementPresentInTheDom = new Promise( + resolve => (prElementPresentInTheDom_resolve = resolve) + ); + + // Observe the dom for the element to be added + const observer = new MutationObserver(() => { + const element = getElement(); + if (element === null) { + return; + } + observer.disconnect(); + prElementPresentInTheDom_resolve(); + }); + + observer.observe(document.body, { childList: true, subtree: true }); + + await prElementPresentInTheDom; + } +}