fix: Embed theme not working using Embed API (#10163)
## What does this PR do? Fixes #10187 See [Tests Done](https://www.loom.com/share/f03e0191b60143d8b45a505042dbfa11) ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How should this be tested? - [x] Configure embed to use `dark` theme and verify that dark theme is shown on event booking page(when user has light theme set). This is failing in main - Additional Tests for embed to avoid any new regression - [x] - Configure "auto" theme using embed API and see it reacts to system theme - [x] - Don't configure any theme and see that "light" theme is shown even when we switch system theme(Because User has configured light theme in App) - Tests outside embed to avoid any new regression - [x] - See that light theme is shown even after switching system theme - [x] - Now, switch the user theme to dark and see that it reflects the change. ## Mandatory Tasks [x] Make sure you have self-reviewed the code. A decent size PR without self-review might be rejected.
This commit is contained in:
@@ -3,7 +3,7 @@ import type { GroupBase, Props, InputProps, SingleValue, MultiValue } from "reac
|
||||
import ReactSelect, { components } from "react-select";
|
||||
|
||||
import classNames from "@calcom/lib/classNames";
|
||||
import useTheme from "@calcom/lib/hooks/useTheme";
|
||||
import { useGetTheme } from "@calcom/lib/hooks/useTheme";
|
||||
|
||||
export type SelectProps<
|
||||
Option,
|
||||
@@ -30,7 +30,7 @@ function Select<
|
||||
Group extends GroupBase<Option> = GroupBase<Option>
|
||||
>({ className, ...props }: SelectProps<Option, IsMulti, Group>) {
|
||||
const [mounted, setMounted] = useState<boolean>(false);
|
||||
const { resolvedTheme, forcedTheme } = useTheme();
|
||||
const { resolvedTheme, forcedTheme } = useGetTheme();
|
||||
const hasDarkTheme = !forcedTheme && resolvedTheme === "dark";
|
||||
const darkThemeColors = {
|
||||
/** Dark Theme starts */
|
||||
|
||||
@@ -48,6 +48,12 @@ type AppPropsWithChildren = AppProps & {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
const getEmbedNamespace = (query: ReturnType<typeof useRouter>["query"]) => {
|
||||
// Mostly embed query param should be available on server. Use that there.
|
||||
// Use the most reliable detection on client
|
||||
return typeof window !== "undefined" ? window.getEmbedNamespace() : (query.embed as string) || null;
|
||||
};
|
||||
|
||||
const CustomI18nextProvider = (props: AppPropsWithChildren) => {
|
||||
/**
|
||||
* i18n should never be clubbed with other queries, so that it's caching can be managed independently.
|
||||
@@ -87,7 +93,7 @@ const CalcomThemeProvider = (props: CalcomThemeProps) => {
|
||||
// Use namespace of embed to ensure same namespaced embed are displayed with same theme. This allows different embeds on the same website to be themed differently
|
||||
// One such example is our Embeds Demo and Testing page at http://localhost:3100
|
||||
// Having `getEmbedNamespace` defined on window before react initializes the app, ensures that embedNamespace is available on the first mount and can be used as part of storageKey
|
||||
const embedNamespace = typeof window !== "undefined" ? window.getEmbedNamespace() : null;
|
||||
const embedNamespace = getEmbedNamespace(router.query);
|
||||
const isEmbedMode = typeof embedNamespace === "string";
|
||||
|
||||
return (
|
||||
@@ -158,10 +164,10 @@ function getThemeProviderProps({
|
||||
? ThemeSupport.None
|
||||
: ThemeSupport.App;
|
||||
|
||||
const isBookingPageThemSupportRequired = themeSupport === ThemeSupport.Booking;
|
||||
const isBookingPageThemeSupportRequired = themeSupport === ThemeSupport.Booking;
|
||||
const themeBasis = props.themeBasis;
|
||||
|
||||
if ((isBookingPageThemSupportRequired || isEmbedMode) && !themeBasis) {
|
||||
if ((isBookingPageThemeSupportRequired || isEmbedMode) && !themeBasis) {
|
||||
console.warn(
|
||||
"`themeBasis` is required for booking page theme support. Not providing it will cause theme flicker."
|
||||
);
|
||||
@@ -184,7 +190,7 @@ function getThemeProviderProps({
|
||||
`embed-theme-${embedNamespace}${appearanceIdSuffix}${embedExplicitlySetThemeSuffix}`
|
||||
: themeSupport === ThemeSupport.App
|
||||
? "app-theme"
|
||||
: isBookingPageThemSupportRequired
|
||||
: isBookingPageThemeSupportRequired
|
||||
? `booking-theme${appearanceIdSuffix}`
|
||||
: undefined;
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ export default function Type({ slug, user, booking, away, isBrandingHidden, resc
|
||||
);
|
||||
}
|
||||
|
||||
Type.isBookingPage = true;
|
||||
Type.PageWrapper = PageWrapper;
|
||||
|
||||
async function getDynamicGroupPageProps(context: GetServerSidePropsContext) {
|
||||
|
||||
@@ -278,7 +278,7 @@ export default function Success(props: SuccessProps) {
|
||||
|
||||
// This is a weird case where the same route can be opened in booking flow as a success page or as a booking detail page from the app
|
||||
// As Booking Page it has to support configured theme, but as booking detail page it should not do any change. Let Shell.tsx handle it.
|
||||
useTheme(isSuccessBookingPage ? props.profile.theme : undefined);
|
||||
useTheme(isSuccessBookingPage ? props.profile.theme : "system");
|
||||
useBrandColors({
|
||||
brandColor: props.profile.brandColor,
|
||||
darkBrandColor: props.profile.darkBrandColor,
|
||||
|
||||
@@ -39,6 +39,7 @@ export default function Type({ slug, user, booking, away, isBrandingHidden, isTe
|
||||
}
|
||||
|
||||
Type.PageWrapper = PageWrapper;
|
||||
Type.isBookingPage = true;
|
||||
|
||||
async function getUserPageProps(context: GetServerSidePropsContext) {
|
||||
const { link, slug } = paramsSchema.parse(context.params);
|
||||
|
||||
@@ -60,3 +60,4 @@ export default function Page(props: Props) {
|
||||
}
|
||||
|
||||
Page.PageWrapper = PageWrapper;
|
||||
Page.isBookingPage = true;
|
||||
|
||||
@@ -37,4 +37,5 @@ export default function Page(props: Props) {
|
||||
return <UserPage {...(props as UserPageProps)} />;
|
||||
}
|
||||
|
||||
Page.isBookingPage = true;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
@@ -42,6 +42,7 @@ export default function Type({ slug, user, booking, away, isBrandingHidden, org
|
||||
}
|
||||
|
||||
Type.PageWrapper = PageWrapper;
|
||||
Type.isBookingPage = true;
|
||||
|
||||
const paramsSchema = z.object({
|
||||
type: z.string().transform((s) => slugify(s)),
|
||||
|
||||
Reference in New Issue
Block a user