HotFix - Embed Flicker for newly converted static availability page (#3277)

* Add missing embed fingerprint

* Fix embed flicker for Availability page

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
This commit is contained in:
Hariom Balhara 2022-07-12 19:48:53 +05:30 committed by GitHub
parent 46266781b5
commit 8d40e7cfd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 34 deletions

View File

@ -1,11 +1,9 @@
import { UserPlan } from "@prisma/client";
import { GetStaticPaths, GetStaticPropsContext } from "next";
import { useEffect } from "react";
import { JSONObject } from "superjson/dist/types";
import { z } from "zod";
import { locationHiddenFilter, LocationObject } from "@calcom/app-store/locations";
import { useIsEmbed } from "@calcom/embed-core/embed-iframe";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { getDefaultEvent, getGroupName, getUsernameList } from "@calcom/lib/defaultEvents";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@ -20,14 +18,7 @@ export type AvailabilityPageProps = inferSSRProps<typeof getStaticProps>;
export default function Type(props: AvailabilityPageProps) {
const { t } = useLocale();
const isEmbed = useIsEmbed();
useEffect(() => {
// Embed background is handled in _document.tsx but this particular page(/[user][/type] is statically rendered and thus doesn't have `embed` param at that time)
// So, for static pages, handle the embed background here. Make sure to always keep it consistent with _document.tsx
if (isEmbed) {
document.body.style.background = "transparent";
}
}, [isEmbed]);
return props.away ? (
<div className="h-screen dark:bg-neutral-900">
<main className="mx-auto max-w-3xl px-4 py-24">

View File

@ -5,19 +5,13 @@ type Props = Record<string, unknown> & DocumentProps;
class MyDocument extends Document<Props> {
static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx);
const isEmbed = ctx.req?.url?.includes("embed=");
return { ...initialProps, isEmbed };
return { ...initialProps };
}
render() {
const props = this.props;
const { locale, gssp } = this.props.__NEXT_DATA__;
const { locale } = this.props.__NEXT_DATA__;
const dir = locale === "ar" || locale === "he" ? "rtl" : "ltr";
// gssp -> getServerSideProps allow us to know that this page was rendered server side and thus would have ctx.req.url with embed query param(if it was there in the request)
// In that case only, we should consider embed to be enabled. For other cases it should be handled at client side and the component should ensure that flicker due to changing css doesn't occur
const isEmbedCorrectlyDetected = gssp && props.isEmbed;
return (
<Html lang={locale} dir={dir}>
<Head>
@ -28,14 +22,31 @@ class MyDocument extends Document<Props> {
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#000000" />
<meta name="msapplication-TileColor" content="#ff0000" />
<meta name="theme-color" content="#ffffff" />
{/* Define isEmbed here so that it can be shared with App(embed-iframe) as well as the following code to change background and hide body */}
<script
dangerouslySetInnerHTML={{
__html: `
window.isEmbed = ()=> {
return location.search.includes("embed=")
}`,
}}
/>
</Head>
{/* Keep the embed hidden till parent initializes and gives it the appropriate styles */}
<body
className={isEmbedCorrectlyDetected ? "bg-transparent" : "bg-gray-100 dark:bg-neutral-900"}
style={isEmbedCorrectlyDetected ? { display: "none" } : {}}>
<body className="bg-gray-100 dark:bg-neutral-900">
<Main />
<NextScript />
{/* In case of Embed we want background to be transparent so that it merges into the website seamlessly. Also, we keep the body hidden here and embed logic would take care of showing the body when it's ready */}
{/* We are doing it on browser and not on server because there are some pages which are not SSRd */}
<script
dangerouslySetInnerHTML={{
__html: `
if (isEmbed()) {
document.body.style.display="none";
document.body.style.background="transparent";
}`,
}}></script>
</body>
</Html>
);

View File

@ -15,6 +15,7 @@ declare global {
};
CalComPageStatus: string;
CalComPlan: string;
isEmbed: () => boolean;
}
}
@ -214,24 +215,20 @@ function getEmbedType() {
}
}
const isEmbed = () => {
const namespace = getNamespace();
const _isValidNamespace = isValidNamespace(namespace);
if (parent !== window && !_isValidNamespace) {
log(
"Looks like you have iframed cal.com but not using Embed Snippet. Directly using an iframe isn't recommended."
);
}
return isValidNamespace(namespace);
};
export const useIsEmbed = () => {
// We can't simply return isEmbed() from this method.
// isEmbed() returns different values on server and browser, which messes up the hydration.
// TODO: We can avoid using document.URL and instead use Router.
const [_isEmbed, setIsEmbed] = useState<boolean | null>(null);
useEffect(() => {
setIsEmbed(isEmbed());
const namespace = getNamespace();
const _isValidNamespace = isValidNamespace(namespace);
if (parent !== window && !_isValidNamespace) {
log(
"Looks like you have iframed cal.com but not using Embed Snippet. Directly using an iframe isn't recommended."
);
}
setIsEmbed(window.isEmbed());
}, []);
return _isEmbed;
};
@ -373,7 +370,7 @@ function keepParentInformedAboutDimensionChanges() {
if (isBrowser) {
const url = new URL(document.URL);
embedStore.theme = (url.searchParams.get("theme") || "auto") as UiConfig["theme"];
if (url.searchParams.get("prerender") !== "true" && isEmbed()) {
if (url.searchParams.get("prerender") !== "true" && window.isEmbed()) {
log("Initializing embed-iframe");
// HACK
const pageStatus = window.CalComPageStatus;

View File

@ -3,6 +3,7 @@ require("dotenv").config({ path: path.join(__dirname, "..", "..", ".env") });
process.env.EMBED_PUBLIC_VERCEL_URL = process.env.VERCEL_URL;
process.env.EMBED_PUBLIC_WEBAPP_URL = process.env.NEXT_PUBLIC_WEBAPP_URL;
process.env.EMBED_PUBLIC_EMBED_LIB_URL = process.env.NEXT_PUBLIC_EMBED_LIB_URL;
process.env.EMBED_PUBLIC_EMBED_FINGER_PRINT = process.env.NEXT_PUBLIC_EMBED_FINGER_PRINT;
// Problem: typeof process.env.EMBED_PUBLIC_EMBED_LIB_URL is "undefined"(truthy) if process.env.NEXT_PUBLIC_EMBED_LIB_URL is undefined(falsy)
// This is probably because environment variables are always string, so this weird automatic conversion to string happens