feat(Nextjs): Font loading in presentation page

This commit is contained in:
shiva raj badu 2025-08-10 22:35:14 +05:45
parent e98e0cea50
commit 3ae6a449c1
No known key found for this signature in database
4 changed files with 40 additions and 29 deletions

View file

@ -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);
};

View file

@ -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<GroupLayoutsProps> = ({
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 (
<div
onClick={() => onSelectLayoutGroup(group)}
@ -51,7 +33,7 @@ if(fonts){
</div>
)}
<div className="mb-3">
<div className="mb-3 ">
<h6 className="text-base capitalize font-medium text-gray-900 mb-1">
{group.name}
</h6>

View file

@ -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" : ""}`} >
<img src="/pdf.svg" alt="pdf export" width={30} height={30} />
<Image src={PDFIMAGE} alt="pdf export" width={30} height={30} />
Export as PDF
</Button>
<Button
@ -145,7 +147,7 @@ const Header = ({
variant="ghost"
className={`w-full flex justify-start text-[#5146E5] ${mobile ? "bg-white py-6" : ""}`}
>
<img src="/pptx.svg" alt="pptx export" width={30} height={30} />
<Image src={PPTXIMAGE} alt="pptx export" width={30} height={30} />
Export as PPTX
</Button>

View file

@ -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<PresentationPageProps> = ({
presentation_id,
}) => {
@ -28,7 +29,8 @@ const PresentationPage: React.FC<PresentationPageProps> = ({
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<PresentationPageProps> = ({
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<PresentationPageProps> = ({
}}
className="flex flex-1 relative pt-6"
>
{!isStreaming &&<SidePanel
<SidePanel
selectedSlide={selectedSlide}
onSlideClick={handleSlideClick}
loading={loading}
isMobilePanelOpen={isMobilePanelOpen}
setIsMobilePanelOpen={setIsMobilePanelOpen}
/>}
/>
<div className="flex-1 h-[calc(100vh-100px)] overflow-y-auto">
<div