Update
This commit is contained in:
85
resources/js/components/editor/EditorSkeleton.jsx
Normal file
85
resources/js/components/editor/EditorSkeleton.jsx
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import { useLayoutEffect, useState } from 'react';
|
||||||
|
import { Skeleton } from '@/components/ui/skeleton';
|
||||||
|
import { LAYOUT_CONSTANTS, calculateOptimalMaxWidth, calculateResponsiveWidth, calculateResponsiveScale } from '@/modules/editor/utils/layout-constants';
|
||||||
|
|
||||||
|
// Hook for responsive dimensions (same as Editor)
|
||||||
|
const useResponsiveDimensions = () => {
|
||||||
|
const [dimensions, setDimensions] = useState(() => ({
|
||||||
|
maxWidth: calculateOptimalMaxWidth(),
|
||||||
|
responsiveWidth: calculateResponsiveWidth(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const newMaxWidth = calculateOptimalMaxWidth();
|
||||||
|
const newResponsiveWidth = calculateResponsiveWidth();
|
||||||
|
setDimensions({
|
||||||
|
maxWidth: newMaxWidth,
|
||||||
|
responsiveWidth: newResponsiveWidth,
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return dimensions;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hook for responsive canvas scale (same as EditorCanvas)
|
||||||
|
const useResponsiveCanvas = (maxWidth = 350) => {
|
||||||
|
const [scale, setScale] = useState(() => calculateResponsiveScale(maxWidth));
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
setScale(calculateResponsiveScale(maxWidth));
|
||||||
|
}, [maxWidth]);
|
||||||
|
|
||||||
|
return scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
const EditorSkeleton = () => {
|
||||||
|
const { maxWidth, responsiveWidth } = useResponsiveDimensions();
|
||||||
|
const scale = useResponsiveCanvas(maxWidth);
|
||||||
|
const displayWidth = LAYOUT_CONSTANTS.CANVAS_WIDTH * scale;
|
||||||
|
const displayHeight = LAYOUT_CONSTANTS.CANVAS_HEIGHT * scale;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative mx-auto flex min-h-[88vh] flex-col space-y-2" style={{ width: `${responsiveWidth}px` }}>
|
||||||
|
{/* Header Skeleton - EditorHeader currently returns empty <></> */}
|
||||||
|
<div className="mx-auto" style={{ width: `${responsiveWidth}px` }}>
|
||||||
|
{/* Header is empty in actual component, so we skip it */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Canvas Skeleton - matching EditorCanvas structure */}
|
||||||
|
<div className="flex w-full justify-center">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: `${displayWidth}px`,
|
||||||
|
height: `${displayHeight}px`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Skeleton
|
||||||
|
className="origin-top-left rounded-3xl border bg-white shadow-sm dark:bg-black bg-gradient-to-r from-muted via-background to-muted bg-[length:200%_100%] animate-shimmer"
|
||||||
|
style={{
|
||||||
|
width: `${LAYOUT_CONSTANTS.CANVAS_WIDTH}px`,
|
||||||
|
height: `${LAYOUT_CONSTANTS.CANVAS_HEIGHT}px`,
|
||||||
|
transform: `scale(${scale})`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Controls Skeleton - matching EditorControls structure */}
|
||||||
|
<div className="mx-auto flex items-center justify-center gap-2" style={{ width: `${responsiveWidth}px` }}>
|
||||||
|
{/* Play/Pause button */}
|
||||||
|
<Skeleton className="h-12 w-12 rounded-full border shadow-sm bg-gradient-to-r from-muted via-background to-muted bg-[length:200%_100%] animate-shimmer" />
|
||||||
|
|
||||||
|
{/* Edit button */}
|
||||||
|
<Skeleton className="h-12 w-12 rounded-full border shadow-sm bg-gradient-to-r from-muted via-background to-muted bg-[length:200%_100%] animate-shimmer" />
|
||||||
|
|
||||||
|
{/* Refresh button */}
|
||||||
|
<Skeleton className="h-12 w-12 rounded-full border shadow-sm bg-gradient-to-r from-muted via-background to-muted bg-[length:200%_100%] animate-shimmer" />
|
||||||
|
|
||||||
|
{/* Download button */}
|
||||||
|
<Skeleton className="h-12 w-12 rounded-full border shadow-sm bg-gradient-to-r from-muted via-background to-muted bg-[length:200%_100%] animate-shimmer" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditorSkeleton;
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import EditorSkeleton from '@/components/editor/EditorSkeleton.jsx';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import BrandLogo from './partials/BrandLogo.jsx';
|
import BrandLogo from './partials/BrandLogo.jsx';
|
||||||
import FAQDiscord from './partials/FAQDiscord.jsx';
|
import FAQDiscord from './partials/FAQDiscord.jsx';
|
||||||
@@ -24,13 +25,7 @@ const Home = ({ faqData, popularKeywords }) => {
|
|||||||
<div className="min-h-[100vh] space-y-0 bg-neutral-50 py-6 dark:bg-black">
|
<div className="min-h-[100vh] space-y-0 bg-neutral-50 py-6 dark:bg-black">
|
||||||
<BrandLogo className="pb-2" />
|
<BrandLogo className="pb-2" />
|
||||||
<div className="to-muted/10 w-full bg-gradient-to-b from-transparent dark:from-transparent dark:to-neutral-900">
|
<div className="to-muted/10 w-full bg-gradient-to-b from-transparent dark:from-transparent dark:to-neutral-900">
|
||||||
{isClient && Editor ? (
|
{isClient && Editor ? <Editor /> : <EditorSkeleton />}
|
||||||
<Editor />
|
|
||||||
) : (
|
|
||||||
<div className="flex h-96 items-center justify-center">
|
|
||||||
<div className="text-muted-foreground">Loading editor...</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-16">
|
<div className="space-y-16">
|
||||||
<Hero />
|
<Hero />
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { MemeCard } from '@/components/custom/meme-card';
|
import { MemeCard } from '@/components/custom/meme-card';
|
||||||
|
import EditorSkeleton from '@/components/editor/EditorSkeleton';
|
||||||
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from '@/components/ui/breadcrumb';
|
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from '@/components/ui/breadcrumb';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { KeywordBadge } from '@/components/ui/keyword-badge';
|
import { KeywordBadge } from '@/components/ui/keyword-badge';
|
||||||
import { Spinner } from '@/components/ui/spinner';
|
|
||||||
import Footer from '@/pages/home/partials/Footer';
|
import Footer from '@/pages/home/partials/Footer';
|
||||||
import { Link } from '@inertiajs/react';
|
import { Link } from '@inertiajs/react';
|
||||||
import { ArrowLeft } from 'lucide-react';
|
import { ArrowLeft } from 'lucide-react';
|
||||||
@@ -94,14 +94,7 @@ export default function MemeShow({ meme, relatedMemes }: Props) {
|
|||||||
setInitialText={(setText) => setText('add your meme caption here')}
|
setInitialText={(setText) => setText('add your meme caption here')}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex h-96 items-center justify-center text-center">
|
<EditorSkeleton />
|
||||||
<div className="space-y-2">
|
|
||||||
<Spinner />
|
|
||||||
<div className="text-muted-foreground" data-nosnippet>
|
|
||||||
Loading meme video editor...
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="container mx-auto grid justify-center gap-5 lg:grid-cols-1" id="more-info">
|
<div className="container mx-auto grid justify-center gap-5 lg:grid-cols-1" id="more-info">
|
||||||
|
|||||||
Reference in New Issue
Block a user