From 3ae6a449c1fe1b29413bcc5ede764b9fdb7dedda Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Sun, 10 Aug 2025 22:35:14 +0545 Subject: [PATCH] feat(Nextjs): Font loading in presentation page --- .../hooks/useFontLoader.tsx | 16 +++++++++++++ .../outline/components/GroupLayouts.tsx | 24 +++---------------- .../presentation/components/Header.tsx | 8 ++++--- .../components/PresentationPage.tsx | 21 ++++++++++++---- 4 files changed, 40 insertions(+), 29 deletions(-) create mode 100644 servers/nextjs/app/(presentation-generator)/hooks/useFontLoader.tsx diff --git a/servers/nextjs/app/(presentation-generator)/hooks/useFontLoader.tsx b/servers/nextjs/app/(presentation-generator)/hooks/useFontLoader.tsx new file mode 100644 index 00000000..3921a1b7 --- /dev/null +++ b/servers/nextjs/app/(presentation-generator)/hooks/useFontLoader.tsx @@ -0,0 +1,16 @@ + +export const useFontLoader = ( fonts:string[]) => { + const injectFonts = (fontUrls: string[]) => { + fontUrls.forEach((fontUrl) => { + if (!fontUrl) return; + let newFontUrl = fontUrl.includes('fonts.googleapis') ? fontUrl : `https://localhost:5000${fontUrl}`; + const existingStyle = document.querySelector(`style[data-font-url="${newFontUrl}"]`); + if (existingStyle) return; + const style = document.createElement("style"); + style.setAttribute("data-font-url", newFontUrl); + style.textContent = `@import url('${newFontUrl}');`; + document.head.appendChild(style); + }); + }; + injectFonts(fonts); +}; \ No newline at end of file diff --git a/servers/nextjs/app/(presentation-generator)/outline/components/GroupLayouts.tsx b/servers/nextjs/app/(presentation-generator)/outline/components/GroupLayouts.tsx index 1e6971d6..acfd0a31 100644 --- a/servers/nextjs/app/(presentation-generator)/outline/components/GroupLayouts.tsx +++ b/servers/nextjs/app/(presentation-generator)/outline/components/GroupLayouts.tsx @@ -2,6 +2,7 @@ import { CheckCircle } from "lucide-react"; import React from "react"; import { LayoutGroup } from "../types/index"; import { useLayout } from "../../context/LayoutContext"; +import { useFontLoader } from "../../hooks/useFontLoader"; interface GroupLayoutsProps { group: LayoutGroup; onSelectLayoutGroup: (group: LayoutGroup) => void; @@ -16,26 +17,7 @@ const GroupLayouts: React.FC = ({ const { getFullDataByGroup,getCustomTemplateFonts } = useLayout(); const layoutGroup = getFullDataByGroup(group.id); const fonts = getCustomTemplateFonts(group.id.split("custom-")[1]); -if(fonts){ - const injectFonts = (fontUrls: string[]) => { - console.log('font are applied',fontUrls); - fontUrls.forEach((fontUrl) => { - if (!fontUrl) return; - const existingStyle = document.querySelector(`style[data-font-url="${fontUrl}"]`); - if (existingStyle) return; - const fileName = fontUrl.split("/").pop() || "CustomFont"; - const baseName = fileName.replace(/\.[a-zA-Z0-9]+$/, ""); - const fontFamily = baseName.replace(/[^A-Za-z0-9_-]/g, "_"); - const ext = (fileName.split(".").pop() || "ttf").toLowerCase(); - const format = ext === "otf" ? "opentype" : ext === "woff" ? "woff" : ext === "woff2" ? "woff2" : "truetype"; - const style = document.createElement("style"); - style.setAttribute("data-font-url", fontUrl); - style.textContent = `@font-face { font-family: '${fontFamily}'; src: url('${fontUrl}') format('${format}'); font-display: swap; }`; - document.head.appendChild(style); - }); - }; - injectFonts(fonts); -} + useFontLoader(fonts || []); return (
onSelectLayoutGroup(group)} @@ -51,7 +33,7 @@ if(fonts){
)} -
+
{group.name}
diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx index 601037ab..eef0e152 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx @@ -26,7 +26,9 @@ import { toast } from "sonner"; import Announcement from "@/components/Announcement"; import { PptxPresentationModel } from "@/types/pptx_models"; import HeaderNav from "../../components/HeaderNab"; - +import PDFIMAGE from "@/public/pdf.svg"; +import PPTXIMAGE from "@/public/pptx.svg"; +import Image from "next/image"; const Header = ({ presentation_id, @@ -137,7 +139,7 @@ const Header = ({ onClick={handleExportPdf} variant="ghost" className={`pb-4 border-b rounded-none border-gray-300 w-full flex justify-start text-[#5146E5] ${mobile ? "bg-white py-6 border-none rounded-lg" : ""}`} > - pdf export + pdf export Export as PDF diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx index d88aba0d..a0a38371 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { useCallback, useState } from "react"; +import React, { useEffect, useState } from "react"; import { useSelector } from "react-redux"; import { RootState } from "@/store/store"; import { Skeleton } from "@/components/ui/skeleton"; @@ -18,7 +18,8 @@ import { } from "../hooks"; import { PresentationPageProps } from "../types"; import LoadingState from "./LoadingState"; - +import { useLayout } from "../../context/LayoutContext"; +import { useFontLoader } from "../../hooks/useFontLoader"; const PresentationPage: React.FC = ({ presentation_id, }) => { @@ -28,7 +29,8 @@ const PresentationPage: React.FC = ({ const [isFullscreen, setIsFullscreen] = useState(false); const [error, setError] = useState(false); const [isMobilePanelOpen, setIsMobilePanelOpen] = useState(false); - + const {getCustomTemplateFonts} = useLayout(); + const { presentationData, isStreaming } = useSelector( (state: RootState) => state.presentationGeneration ); @@ -73,6 +75,15 @@ const PresentationPage: React.FC = ({ handleSlideChange(newSlide, presentationData); }; + + useEffect(() => { + if(!loading && !isStreaming && presentationData?.slides && presentationData?.slides.length > 0){ + const presentation_id = presentationData?.slides[0].layout.split(":")[0].split("custom-")[1]; + const fonts = getCustomTemplateFonts(presentation_id); + + useFontLoader(fonts || []); + } + }, [presentationData,loading,isStreaming]); // Presentation Mode View if (isPresentMode) { return ( @@ -120,13 +131,13 @@ const PresentationPage: React.FC = ({ }} className="flex flex-1 relative pt-6" > - {!isStreaming &&} + />