返回 presentation-ai
GifSearchControls.tsx
1 "use client";
2
3 import { type TElement } from "platejs";
4 import { useEditorRef } from "platejs/react";
5 import React from "react";
6
7 import { type RootImage as RootImageType } from "@/components/notebook/presentation/utils/parser";
8 import { SharedGifSearchControls } from "@/components/presentation/shared/SharedGifSearchControls";
9 import { useDebouncedSave } from "@/hooks/presentation/useDebouncedSave";
10 import { usePresentationState } from "@/states/presentation-state";
11
12 interface GifSearchControlsProps {
13 element: TElement & RootImageType;
14 slideId?: string;
15 isRootImage: boolean;
16 onPick?: () => void;
17 }
18
19 export function GifSearchControls({
20 element,
21 slideId,
22 isRootImage,
23 onPick,
24 }: GifSearchControlsProps) {
25 const editor = useEditorRef(slideId);
26 const { saveImmediately } = useDebouncedSave();
27
28 const handleSelect = React.useCallback(
29 async (url: string) => {
30 // Get the latest state directly from the store to avoid stale closures
31 const { setSlides, clearRootImageGeneration } =
32 usePresentationState.getState();
33
34 if (isRootImage) {
35 if (slideId) clearRootImageGeneration(slideId);
36 setSlides((slides) =>
37 slides.map((slide) =>
38 slide.id === slideId
39 ? {
40 ...slide,
41 rootImage: {
42 ...slide.rootImage!,
43 url: url,
44 imageSource: "gif" as const,
45 },
46 }
47 : slide,
48 ),
49 );
50 await saveImmediately();
51 } else {
52 editor.tf.setNodes({
53 ...element,
54 url: url,
55 imageSource: "gif",
56 });
57 await saveImmediately();
58 }
59 onPick?.();
60 },
61 [isRootImage, slideId, editor, element, onPick, saveImmediately],
62 );
63
64 return (
65 <SharedGifSearchControls onGifSelect={handleSelect} className="h-full" />
66 );
67 }
68
68 lines Plain Text