diff --git a/services/web/frontend/js/features/settings/components/linking-section.tsx b/services/web/frontend/js/features/settings/components/linking-section.tsx index 857d7265d6..250fb9eef1 100644 --- a/services/web/frontend/js/features/settings/components/linking-section.tsx +++ b/services/web/frontend/js/features/settings/components/linking-section.tsx @@ -5,8 +5,10 @@ import importOverleafModules from '../../../../macros/import-overleaf-module.mac import { useSSOContext, SSOSubscription } from '../context/sso-context' import { SSOLinkingWidget } from './linking/sso-widget' import getMeta from '../../../utils/meta' +import { useBroadcastUser } from '@/shared/hooks/user-channel/use-broadcast-user' function LinkingSection() { + useBroadcastUser() const { t } = useTranslation() const { subscriptions } = useSSOContext() const ssoErrorMessage = getMeta('ol-ssoErrorMessage') as string diff --git a/services/web/frontend/js/shared/hooks/user-channel/use-broadcast-user.ts b/services/web/frontend/js/shared/hooks/user-channel/use-broadcast-user.ts new file mode 100644 index 0000000000..3a87d49129 --- /dev/null +++ b/services/web/frontend/js/shared/hooks/user-channel/use-broadcast-user.ts @@ -0,0 +1,12 @@ +import { useEffect } from 'react' +import { useUserContext } from '@/shared/context/user-context' +import { useUserChannel } from './use-user-channel' + +export const useBroadcastUser = () => { + const user = useUserContext() + const channel = useUserChannel() + + useEffect(() => { + channel?.postMessage(user) + }, [channel, user]) +} diff --git a/services/web/frontend/js/shared/hooks/user-channel/use-receive-user.ts b/services/web/frontend/js/shared/hooks/user-channel/use-receive-user.ts new file mode 100644 index 0000000000..5542d8d4e8 --- /dev/null +++ b/services/web/frontend/js/shared/hooks/user-channel/use-receive-user.ts @@ -0,0 +1,16 @@ +import { useEffect } from 'react' +import { useUserChannel } from './use-user-channel' + +export const useReceiveUser = ( + handleData: (data: Record) => void +) => { + const channel = useUserChannel() + + useEffect(() => { + const abortController = new AbortController() + channel?.addEventListener('message', ({ data }) => handleData(data), { + signal: abortController.signal, + }) + return () => abortController.abort() + }, [channel, handleData]) +} diff --git a/services/web/frontend/js/shared/hooks/user-channel/use-user-channel.ts b/services/web/frontend/js/shared/hooks/user-channel/use-user-channel.ts new file mode 100644 index 0000000000..29ae421a12 --- /dev/null +++ b/services/web/frontend/js/shared/hooks/user-channel/use-user-channel.ts @@ -0,0 +1,15 @@ +import { useEffect, useRef } from 'react' + +export const useUserChannel = (): BroadcastChannel | null => { + const channelRef = useRef(null) + + if (channelRef.current === null && 'BroadcastChannel' in window) { + channelRef.current = new BroadcastChannel('user') + } + + useEffect(() => { + return () => channelRef.current?.close() + }, []) + + return channelRef.current +}