import { useEffect, useRef, useState } from 'react';
import { Button } from '@/components/ui/button';
import {
DESIGN_RESIZE,
HISTORY_UNDO,
HISTORY_REDO,
dispatcher,
useEditorState,
} from '@designcombo/core';
import logoDark from '@/assets/logo-dark.png';
import { Icons } from '../shared/icons';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import { ChevronDown, Download } from 'lucide-react';
import { Label } from '../ui/label';
import { Progress } from '../ui/progress';
import { download } from '@/utils/download';
const baseUrl = 'https://renderer.designcombo.dev';
// https://renderer.designcombo.dev/status/{id}
export default function Navbar() {
const handleUndo = () => {
dispatcher.dispatch(HISTORY_UNDO);
};
const handleRedo = () => {
dispatcher.dispatch(HISTORY_REDO);
};
const openLink = (url: string) => {
window.open(url, '_blank'); // '_blank' will open the link in a new tab
};
return (
);
}
interface IDownloadState {
renderId: string;
progress: number;
isDownloading: boolean;
}
const DownloadPopover = () => {
const [open, setOpen] = useState(false);
const popoverRef = useRef(null);
const [downloadState, setDownloadState] = useState({
progress: 0,
isDownloading: false,
renderId: '',
});
const {
trackItemIds,
trackItemsMap,
transitionIds,
transitionsMap,
tracks,
duration,
size,
} = useEditorState();
const handleExport = () => {
const payload = {
trackItemIds,
trackItemsMap,
transitionIds,
transitionsMap,
tracks,
size: size,
duration: duration - 750,
fps: 30,
projectId: 'main',
};
setDownloadState({
...downloadState,
isDownloading: true,
});
fetch(`${baseUrl}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
.then((res) => res.json())
.then(({ render }) => {
setDownloadState({
...downloadState,
renderId: render.id,
isDownloading: true,
});
});
};
useEffect(() => {
console.log('renderId', downloadState.renderId);
let interval: NodeJS.Timeout;
if (downloadState.renderId) {
interval = setInterval(() => {
fetch(`${baseUrl}/status/${downloadState.renderId}`)
.then((res) => res.json())
.then(({ render: { progress, output } }) => {
if (progress === 100) {
clearInterval(interval);
setDownloadState({
...downloadState,
renderId: '',
progress: 0,
isDownloading: false,
});
download(output, `${downloadState.renderId}`);
setOpen(false);
} else {
setDownloadState({
...downloadState,
progress,
isDownloading: true,
});
}
});
}, 1000);
}
return () => {
if (interval) clearInterval(interval);
};
}, [downloadState.renderId]);
return (
{downloadState.isDownloading ? (
<>
{parseInt(downloadState.progress.toString())}%
>
) : (
<>
>
)}
);
};
interface ResizeOptionProps {
label: string;
icon: string;
value: ResizeValue;
}
interface ResizeValue {
width: number;
height: number;
name: string;
}
const RESIZE_OPTIONS: ResizeOptionProps[] = [
{
label: '16:9',
icon: 'landscape',
value: {
width: 1920,
height: 1080,
name: '16:9',
},
},
{
label: '9:16',
icon: 'portrait',
value: {
width: 1080,
height: 1920,
name: '9:16',
},
},
{
label: '1:1',
icon: 'square',
value: {
width: 1080,
height: 1080,
name: '1:1',
},
},
];
const ResizeVideo = () => {
const handleResize = (payload: ResizeValue) => {
dispatcher.dispatch(DESIGN_RESIZE, {
payload,
});
};
return (
{RESIZE_OPTIONS.map((option, index) => (
))}
);
};
const ResizeOption = ({
label,
icon,
value,
handleResize,
}: ResizeOptionProps & { handleResize: (payload: ResizeValue) => void }) => {
const Icon = Icons[icon];
return (
handleResize(value)}
className="flex items-center gap-4 hover:bg-zinc-50/10 cursor-pointer"
>
{label}
Tiktok, Instagram
);
};