返回 presentation-ai
RecordingPreviewDialog.tsx
根目录 / src / components / notebook / presentation / recording / RecordingPreviewDialog.tsx
1 "use client";
2
3 import { useMemo, useRef } from "react";
4
5 import { Button } from "@/components/ui/button";
6 import {
7 Credenza,
8 CredenzaContent,
9 CredenzaFooter,
10 CredenzaHeader,
11 CredenzaTitle,
12 } from "@/components/ui/credenza";
13 import { usePresentationRecordingState } from "@/states/presentation-recording-state";
14
15 function RecordingPreviewDialog() {
16 const { blobUrl, setBlobUrl, reset } = usePresentationRecordingState();
17 const open = Boolean(blobUrl);
18 const url = blobUrl ?? undefined;
19 const aRef = useRef<HTMLAnchorElement | null>(null);
20
21 const fileName = useMemo(() => {
22 const d = new Date();
23 const pad = (n: number) => String(n).padStart(2, "0");
24 return `presentation-${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}.webm`;
25 }, []);
26
27 return (
28 <Credenza open={open} onOpenChange={(v) => !v && setBlobUrl(null)}>
29 <CredenzaContent className="z-9999 max-w-2xl">
30 <CredenzaHeader>
31 <CredenzaTitle>Recording preview</CredenzaTitle>
32 </CredenzaHeader>
33 <div className="aspect-video w-full overflow-hidden rounded-lg border border-border">
34 {url && <video src={url} controls className="h-full w-full" />}
35 </div>
36 <CredenzaFooter>
37 <Button
38 variant="secondary"
39 onClick={() => {
40 setBlobUrl(null);
41 reset();
42 }}
43 >
44 Discard
45 </Button>
46 <a ref={aRef} href={url} download={fileName}>
47 <Button>Download</Button>
48 </a>
49 </CredenzaFooter>
50 </CredenzaContent>
51 </Credenza>
52 );
53 }
54
55 export default RecordingPreviewDialog;
56
56 lines Plain Text