Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 38 additions & 7 deletions src/components/Layout/CustomLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import Head from '@docusaurus/Head';
import HomePageSkeleton from '../HomePageSkeleton';
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
import useTMB from '@site/src/hooks/useTmb';
import useTmbEnabled from '@site/src/hooks/useTmbEnabled';

const CustomLayout: React.FC = () => {
const { onRenderTMBCheck } = useTMB();
const [loader, setLoader] = useState(true);
const [isSilentLoginExcluded, setIsSilentLoginExcluded] = useState(false);
const isTMBEnabled =
typeof window !== 'undefined' && JSON.parse(localStorage.getItem('is_tmb_enabled') ?? 'false');
const [isTMBEnabled, isTmbLoading] = useTmbEnabled();

const initRef = useRef(false);

Expand All @@ -26,13 +26,32 @@ const CustomLayout: React.FC = () => {
initRef.current = true;
}, [onRenderTMBCheck]);

const hideMainElement = () => {
const mainElement = document.querySelector('[aria-label="Main"]') as HTMLElement;
if (mainElement) {
mainElement.style.display = 'none';
}
};

useEffect(() => {
isTMBEnabled && initSession();
}, [initSession, isTMBEnabled]);
// Don't execute any TMB-related code until we know if TMB is enabled
if (isTmbLoading) {
// Hide main element while TMB status is loading
hideMainElement();
setLoader(true);
return;
}

if (isTMBEnabled) {
// Hide main element while TMB is loading
hideMainElement();
initSession();
}
}, [initSession, isTMBEnabled, isTmbLoading]);

useEffect(() => {
// Only execute in browser environment
if (!ExecutionEnvironment.canUseDOM || isTMBEnabled) {
if (!ExecutionEnvironment.canUseDOM || isTmbLoading || isTMBEnabled) {
return;
}

Expand Down Expand Up @@ -64,11 +83,23 @@ const CustomLayout: React.FC = () => {
if ((willEventuallySSO || willEventuallySLO) && !isSilentLoginExcluded) {
mainElement.style.display = 'none';
setLoader(true);
} else {
} else if (!isTMBEnabled) {
// Only show main element if TMB is not enabled
// When TMB is enabled, the display will be controlled by the TMB loading effect
mainElement.style.display = '';
setLoader(false);
}
}, [isSilentLoginExcluded, isTMBEnabled]);
}, [isSilentLoginExcluded, isTMBEnabled, isTmbLoading]);

// Effect to restore main element display when TMB loading is complete
useEffect(() => {
if (isTMBEnabled && !loader) {
const mainElement = document.querySelector('[aria-label="Main"]') as HTMLElement;
if (mainElement) {
mainElement.style.display = '';
}
}
}, [loader, isTMBEnabled]);

return (
<>
Expand Down
48 changes: 48 additions & 0 deletions src/hooks/useTmbEnabled/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useState, useEffect } from 'react';
import { getTmbConfigUrl } from '@site/src/utils';

/**
* Hook to fetch and determine if TMB (Third-party Marketplace Business) is enabled
* @returns {[boolean, boolean]} A tuple containing [isTmbEnabled, isLoading]
*/
const useTmbEnabled = (): [boolean, boolean] => {
const [isTmbEnabled, setIsTmbEnabled] = useState(false);
const [isLoading, setIsLoading] = useState(true);

// Get the TMB config URL from utils
const configUrl = getTmbConfigUrl();

// Fetch TMB enabled status from remote config
useEffect(() => {
if (!configUrl) return;

const fetchTmbStatus = async () => {
setIsLoading(true);
try {
const response = await fetch(configUrl);
const data = await response.json();

// Use the "api" key from the response, default to false if undefined
const isEnabled = data?.api === true;

// Store the value in localStorage for other components to use
if (typeof window !== 'undefined') {
localStorage.setItem('is_tmb_enabled', JSON.stringify(!!isEnabled));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was thinking to have localstorage to override as a backdoor

Copy link
Contributor

@amam-deriv amam-deriv May 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

localstorage will override value from firebase as a backdoor, by default localstorage will be empty, once it is set, it will override, if its empty, read from firebase

}

setIsTmbEnabled(!!isEnabled);
} catch (error) {
console.error('Failed to fetch TMB status:', error);
setIsTmbEnabled(false);
} finally {
setIsLoading(false);
}
};

fetchTmbStatus();
}, [configUrl]);

return [isTmbEnabled, isLoading];
};

export default useTmbEnabled;
13 changes: 13 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,16 @@ export const scopesArrayToObject = (scopes: string[]) => {
export const findVirtualAccount = (accounts: IUserLoginAccount[]) => {
return accounts.find((item) => item.name.includes('VRTC'));
};

/**
* Returns the appropriate TMB config URL based on the environment
* @returns {string} The TMB config URL
*/
export const getTmbConfigUrl = () => {
if (typeof window === 'undefined') return '';

const isProduction = isHost('api.deriv.com');
return isProduction
? 'https://app-config-prod.firebaseio.com/remote_config/oauth/is_tmb_enabled.json'
: 'https://app-config-staging.firebaseio.com/remote_config/oauth/is_tmb_enabled.json';
};
Loading