fix: wait for background to load in survey loading indicator (#3011)

This commit is contained in:
Dhruwang Jariwala
2024-08-15 12:23:47 +05:30
committed by GitHub
parent 3dc3edb83e
commit 3e25ef4b5a
3 changed files with 26 additions and 7 deletions
@@ -1,6 +1,6 @@
import { LegalFooter } from "@/app/s/[surveyId]/components/LegalFooter";
import { SurveyLoadingAnimation } from "@/app/s/[surveyId]/components/SurveyLoadingAnimation";
import React from "react";
import React, { useState } from "react";
import { cn } from "@formbricks/lib/cn";
import { TProduct, TProductStyling } from "@formbricks/types/product";
import { TSurvey, TSurveyStyling } from "@formbricks/types/surveys/types";
@@ -36,6 +36,13 @@ export const LinkSurveyWrapper = ({
webAppUrl,
}: LinkSurveyWrapperProps) => {
//for embedded survey strip away all surrounding css
const [isBackgroundLoaded, setIsBackgroundLoaded] = useState(false);
const handleBackgroundLoaded = (isLoaded: boolean) => {
if (isLoaded) {
setIsBackgroundLoaded(true);
}
};
const styling = determineStyling();
if (isEmbed)
return (
@@ -52,8 +59,8 @@ export const LinkSurveyWrapper = ({
else
return (
<div>
<SurveyLoadingAnimation survey={survey} />
<MediaBackground survey={survey} product={product}>
<SurveyLoadingAnimation survey={survey} isBackgroundLoaded={isBackgroundLoaded} />
<MediaBackground survey={survey} product={product} onBackgroundLoaded={handleBackgroundLoaded}>
<div className="flex max-h-dvh min-h-dvh items-end justify-center overflow-clip md:items-center">
{!styling.isLogoHidden && product.logo?.url && <ClientLogo product={product} />}
<div className="h-full w-full space-y-6 p-0 md:max-w-md">
@@ -7,14 +7,18 @@ import { LoadingSpinner } from "@formbricks/ui/LoadingSpinner";
interface SurveyLoadingAnimationProps {
survey: TSurvey;
isBackgroundLoaded?: boolean;
}
export const SurveyLoadingAnimation = ({ survey }: SurveyLoadingAnimationProps) => {
export const SurveyLoadingAnimation = ({
survey,
isBackgroundLoaded = true,
}: SurveyLoadingAnimationProps) => {
const [isHidden, setIsHidden] = useState(false);
const [minTimePassed, setMinTimePassed] = useState(false);
const [isMediaLoaded, setIsMediaLoaded] = useState(false); // Tracks if all media (images, iframes) are fully loaded
const [isSurveyPackageLoaded, setIsSurveyPackageLoaded] = useState(false); // Tracks if the survey package has been loaded into the DOM
const isReadyToTransition = isMediaLoaded && minTimePassed && isBackgroundLoaded;
const cardId = survey.welcomeCard.enabled ? `questionCard--1` : `questionCard-0`;
// Function to check if all media elements (images and iframes) within the survey card are loaded
@@ -96,13 +100,13 @@ export const SurveyLoadingAnimation = ({ survey }: SurveyLoadingAnimationProps)
<div
className={cn(
"absolute inset-0 z-[5000] flex items-center justify-center transition-colors duration-1000",
isMediaLoaded && minTimePassed ? "bg-transparent" : "bg-white",
isReadyToTransition ? "bg-transparent" : "bg-white",
isHidden && "hidden"
)}>
<div
className={cn(
"flex flex-col items-center space-y-4",
isMediaLoaded && minTimePassed ? "animate-surveyExit" : "animate-surveyLoading"
isReadyToTransition ? "animate-surveyExit" : "animate-surveyLoading"
)}>
<Image src={Logo} alt="Logo" className={cn("w-32 transition-all duration-1000 md:w-40")} />
<LoadingSpinner />
+8
View File
@@ -13,6 +13,7 @@ interface MediaBackgroundProps {
isEditorView?: boolean;
isMobilePreview?: boolean;
ContentRef?: React.RefObject<HTMLDivElement>;
onBackgroundLoaded?: (isLoaded: boolean) => void;
}
export const MediaBackground: React.FC<MediaBackgroundProps> = ({
@@ -22,6 +23,7 @@ export const MediaBackground: React.FC<MediaBackgroundProps> = ({
isEditorView = false,
isMobilePreview = false,
ContentRef,
onBackgroundLoaded,
}) => {
const animatedBackgroundRef = useRef<HTMLVideoElement>(null);
const [backgroundLoaded, setBackgroundLoaded] = useState(false);
@@ -75,6 +77,12 @@ export const MediaBackground: React.FC<MediaBackgroundProps> = ({
}
}, [background?.bg, background?.bgType]);
useEffect(() => {
if (backgroundLoaded && onBackgroundLoaded) {
onBackgroundLoaded(true);
}
}, [backgroundLoaded, onBackgroundLoaded]);
const baseClasses = "absolute inset-0 h-full w-full transition-opacity duration-500";
const loadedClass = backgroundLoaded ? "opacity-100" : "opacity-0";