diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 60524a1..d7f8258 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -48,6 +48,7 @@ import useBrowserTabIndicator from "./hooks/useBrowserTabIndicator"; import TipLink from "./components/core/TipLink"; import FeedbackCallNote from "./components/user-feedback/FeedbackCallNote"; import SelectAndEditModeToggleButton from "./components/select-and-edit/SelectAndEditModeToggleButton"; +import { useAppStore } from "./store/app-store"; const IS_OPENAI_DOWN = false; @@ -71,6 +72,8 @@ function App({ navbarComponent }: Props) { const { getToken } = useAuth(); const subscriberTier = useStore((state) => state.subscriberTier); + const { disableInSelectAndEditMode } = useAppStore(); + // Settings const [settings, setSettings] = usePersistedState( { @@ -174,6 +177,7 @@ function App({ navbarComponent }: Props) { setAppHistory([]); setCurrentVersion(null); setShouldIncludeResultImage(false); + disableInSelectAndEditMode(); }; const regenerate = () => { diff --git a/frontend/src/components/Preview.tsx b/frontend/src/components/Preview.tsx index 8dc2f22..d601f78 100644 --- a/frontend/src/components/Preview.tsx +++ b/frontend/src/components/Preview.tsx @@ -2,7 +2,6 @@ import { useEffect, useRef, useState } from "react"; import classNames from "classnames"; import useThrottle from "../hooks/useThrottle"; import EditPopup from "./select-and-edit/EditPopup"; -import { useAppStore } from "../store/app-store"; interface Props { code: string; @@ -11,8 +10,6 @@ interface Props { } function Preview({ code, device, doUpdate }: Props) { - const { inSelectAndEditMode } = useAppStore(); - const iframeRef = useRef(null); // Don't update code more often than every 200ms. @@ -51,12 +48,7 @@ function Preview({ code, device, doUpdate }: Props) { } )} > - + ); } diff --git a/frontend/src/components/select-and-edit/EditPopup.tsx b/frontend/src/components/select-and-edit/EditPopup.tsx index 5bc9d42..09192b3 100644 --- a/frontend/src/components/select-and-edit/EditPopup.tsx +++ b/frontend/src/components/select-and-edit/EditPopup.tsx @@ -2,33 +2,40 @@ import React, { useEffect, useRef, useState } from "react"; import { Textarea } from "../ui/textarea"; import { Button } from "../ui/button"; import { addHighlight, getAdjustedCoordinates, removeHighlight } from "./utils"; +import { useAppStore } from "../../store/app-store"; interface EditPopupProps { event: MouseEvent | null; - inSelectAndEditMode: boolean; - doUpdate: (updateInstruction: string, selectedElement?: HTMLElement) => void; iframeRef: React.RefObject; + doUpdate: (updateInstruction: string, selectedElement?: HTMLElement) => void; } const EditPopup: React.FC = ({ event, - inSelectAndEditMode, - doUpdate, iframeRef, + doUpdate, }) => { - // Edit state - const [selectedElement, setSelectedElement] = useState< - HTMLElement | undefined - >(undefined); - const [updateText, setUpdateText] = useState(""); + // App state + const { inSelectAndEditMode } = useAppStore(); + + // Create a wrapper ref to store inSelectAndEditMode so the value is not stale + // in a event listener + const inSelectAndEditModeRef = useRef(inSelectAndEditMode); + + // Update the ref whenever the state changes + useEffect(() => { + inSelectAndEditModeRef.current = inSelectAndEditMode; + }, [inSelectAndEditMode]); // Popup state const [popupVisible, setPopupVisible] = useState(false); const [popupPosition, setPopupPosition] = useState({ x: 0, y: 0 }); - // Create a wrapper ref to store inSelectAndEditMode so the value is not stale - // in a event listener - const inSelectAndEditModeRef = useRef(inSelectAndEditMode); + // Edit state + const [selectedElement, setSelectedElement] = useState< + HTMLElement | undefined + >(undefined); + const [updateText, setUpdateText] = useState(""); // Textarea ref for focusing const textareaRef = useRef(null); @@ -47,11 +54,6 @@ const EditPopup: React.FC = ({ setPopupVisible(false); } - // Update the ref whenever the state changes - useEffect(() => { - inSelectAndEditModeRef.current = inSelectAndEditMode; - }, [inSelectAndEditMode]); - // Remove highlight and reset state when not in select and edit mode useEffect(() => { if (!inSelectAndEditMode) { @@ -103,6 +105,15 @@ const EditPopup: React.FC = ({ textareaRef.current?.focus(); }, [event, iframeRef]); + // Focus the textarea when the popup is visible (we can't do this only when handling the click event + // because the textarea is not rendered yet) + // We need to also do it in the click event because popupVisible doesn't change values in that event + useEffect(() => { + if (popupVisible) { + textareaRef.current?.focus(); + } + }, [popupVisible]); + if (!popupVisible) return; return ( @@ -115,6 +126,12 @@ const EditPopup: React.FC = ({ value={updateText} onChange={(e) => setUpdateText(e.target.value)} placeholder="Tell the AI what to change about this element..." + onKeyDown={(e) => { + if (e.key === "Enter") { + e.preventDefault(); + onUpdate(updateText); + } + }} />
diff --git a/frontend/src/components/select-and-edit/SelectAndEditModeToggleButton.tsx b/frontend/src/components/select-and-edit/SelectAndEditModeToggleButton.tsx index f076c9b..2f76486 100644 --- a/frontend/src/components/select-and-edit/SelectAndEditModeToggleButton.tsx +++ b/frontend/src/components/select-and-edit/SelectAndEditModeToggleButton.tsx @@ -1,3 +1,4 @@ +import { GiClick } from "react-icons/gi"; import { useAppStore } from "../../store/app-store"; import { Button } from "../ui/button"; @@ -10,7 +11,10 @@ function SelectAndEditModeToggleButton() { className="flex items-center gap-x-2 dark:text-white dark:bg-gray-700 regenerate-btn" variant={inSelectAndEditMode ? "destructive" : "default"} > - {inSelectAndEditMode ? "Exit selection mode" : "🖱️ Select and Edit"} + + + {inSelectAndEditMode ? "Exit selection mode" : "Select and update"} + ); } diff --git a/frontend/src/store/app-store.ts b/frontend/src/store/app-store.ts index 26b7994..2b52513 100644 --- a/frontend/src/store/app-store.ts +++ b/frontend/src/store/app-store.ts @@ -5,6 +5,7 @@ interface AppStore { inSelectAndEditMode: boolean; inputMode: "image" | "video"; toggleInSelectAndEditMode: () => void; + disableInSelectAndEditMode: () => void; } export const useAppStore = create((set) => ({ @@ -12,4 +13,5 @@ export const useAppStore = create((set) => ({ inSelectAndEditMode: false, toggleInSelectAndEditMode: () => set((state) => ({ inSelectAndEditMode: !state.inSelectAndEditMode })), + disableInSelectAndEditMode: () => set({ inSelectAndEditMode: false }), }));