import { Button, Group, Stack, Textarea } from "@mantine/core"; import { usePubSub } from "create-pubsub/react"; import { type ChangeEvent, type KeyboardEvent, type ReactNode, useCallback, useEffect, useRef, useState, } from "react"; import { useLocation } from "wouter"; import { handleEnterKeyDown } from "../../../modules/keyboard"; import { addLogEntry } from "../../../modules/logEntries"; import { postMessageToParentWindow } from "../../../modules/parentWindow"; import { settingsPubSub } from "../../../modules/pubSub"; import { getRandomQuerySuggestion } from "../../../modules/querySuggestions"; import { sleepUntilIdle } from "../../../modules/sleep"; import { searchAndRespond } from "../../../modules/textGeneration"; interface SearchFormState { textAreaValue: string; suggestedQuery: string; } export default function SearchForm({ query, updateQuery, additionalButtons, }: { query: string; updateQuery: (query: string) => void; additionalButtons?: ReactNode; }) { const textAreaRef = useRef(null); const defaultSuggestedQuery = "Anything you need!"; const [state, setState] = useState({ textAreaValue: query, suggestedQuery: defaultSuggestedQuery, }); const [, navigate] = useLocation(); const [settings] = usePubSub(settingsPubSub); const handleMount = useCallback(async () => { await sleepUntilIdle(); searchAndRespond(); }, []); const fetchQuerySuggestion = useCallback(async () => { try { return await getRandomQuerySuggestion(); } catch (error) { addLogEntry("Failed to get query suggestion"); return defaultSuggestedQuery; } }, []); const handleInitialSuggestion = useCallback(async () => { const suggestion = await fetchQuerySuggestion(); setState((prev) => ({ ...prev, suggestedQuery: suggestion })); }, [fetchQuerySuggestion]); useEffect(() => { handleMount(); handleInitialSuggestion(); }, [handleMount, handleInitialSuggestion]); const handleInputChange = async (event: ChangeEvent) => { const text = event.target.value; setState((prev) => ({ ...prev, textAreaValue: text })); if (text.length === 0) { try { const suggestion = await getRandomQuerySuggestion(); setState((prev) => ({ ...prev, suggestedQuery: suggestion })); } catch (error) { addLogEntry("Failed to get query suggestion"); setState((prev) => ({ ...prev, suggestedQuery: defaultSuggestedQuery, })); } } }; const handleClearButtonClick = async () => { textAreaRef.current?.focus(); setState((prev) => ({ ...prev, textAreaValue: "", })); addLogEntry("User cleaned the search query field"); const suggestion = await fetchQuerySuggestion(); setState((prev) => ({ ...prev, suggestedQuery: suggestion, })); }; const startSearching = useCallback(() => { const queryToEncode = state.textAreaValue.trim().length >= 1 ? state.textAreaValue : state.suggestedQuery; setState((prev) => ({ ...prev, textAreaValue: queryToEncode })); const queryString = `q=${encodeURIComponent(queryToEncode)}`; postMessageToParentWindow({ queryString, hash: "" }); navigate(`/?${queryString}`, { replace: true }); updateQuery(queryToEncode); searchAndRespond(); addLogEntry( `User submitted a search with ${queryToEncode.length} characters length`, ); }, [state.textAreaValue, state.suggestedQuery, updateQuery, navigate]); const handleSubmit = (event: { preventDefault: () => void }) => { event.preventDefault(); startSearching(); }; const handleKeyDown = (event: KeyboardEvent) => { handleEnterKeyDown(event, settings, () => handleSubmit(event)); }; return (