Repository: Mintplex-Labs/anything-llm
File: frontend/src/hooks/usePromptInputStorage.js (JavaScript)

Code before:
 *   "workspace-slug": "another draft message..."
 * }
 * ```
 *
 * @param {Object} props
 * @param {Function} props.onChange - Callback invoked when restoring saved value, receives `{ target: { value: string } }`
 * @param {string} props.promptInput - Current prompt input value to sync
 * @param {Function} props.setPromptInput - State setter function for prompt input
 * @returns {void}
 */
export default function usePromptInputStorage({
  onChange,
  promptInput,
  setPromptInput,
}) {
  const { threadSlug = null, slug: workspaceSlug } = useParams();
  useEffect(() => {
    // Get the user prompt input map from localStorage
    let promptInputMap = localStorage.getItem(USER_PROMPT_INPUT_MAP);

    // Attempt to deserialize the prompt input map
    try {
      promptInputMap = promptInputMap ? JSON.parse(promptInputMap) : {};
    } catch (error) {
      promptInputMap = {};
    }

    // If there is a thread slug, use it, otherwise the user is probably in the default thread and use the workspace slug
    const userPromptInputValue = promptInputMap[threadSlug ?? workspaceSlug];
    if (userPromptInputValue) {
      setPromptInput(userPromptInputValue);
      // Notify parent component so message state is synchronized
      onChange({ target: { value: userPromptInputValue } });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Set the user prompt input map to localStorage (debounced by 300ms)
  const debouncedWriteToStorage = useMemo(
    () =>
      debounce((value, slug) => {
        let promptInputMap = localStorage.getItem(USER_PROMPT_INPUT_MAP);

        // Attempt to deserialize the prompt input map
        try {
          promptInputMap = promptInputMap ? JSON.parse(promptInputMap) : {};
        } catch (error) {
          promptInputMap = {};
        }

        // Set the user prompt input value to the prompt input map by the thread slug or workspace slug (if in the default thread)

Review comment (suggestion):
Just use `safeJSONParse(promptInputMap, {})` - does the same thing. Should be in `request` in utils.

Code after:
 *   "thread-slug": "user's draft message...",
 *   "workspace-slug": "another draft message..."
 * }
 * ```
 *
 * @param {Object} props
 * @param {Function} props.onChange - Callback invoked when restoring saved value, receives `{ target: { value: string } }`
 * @param {string} props.promptInput - Current prompt input value to sync
 * @param {Function} props.setPromptInput - State setter function for prompt input
 * @returns {void}
 */
export default function usePromptInputStorage({
  onChange,
  promptInput,
  setPromptInput,
}) {
  const { threadSlug = null, slug: workspaceSlug } = useParams();
  useEffect(() => {
    const serializedPromptInputMap =
      localStorage.getItem(USER_PROMPT_INPUT_MAP) || "{}";

    const promptInputMap = safeJsonParse(serializedPromptInputMap, {});

    const userPromptInputValue = promptInputMap[threadSlug ?? workspaceSlug];
    if (userPromptInputValue) {
      setPromptInput(userPromptInputValue);
      // Notify parent component so message state is synchronized
      onChange({ target: { value: userPromptInputValue } });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const debouncedWriteToStorage = useMemo(
    () =>
      debounce((value, slug) => {
        const serializedPromptInputMap =
          localStorage.getItem(USER_PROMPT_INPUT_MAP) || "{}";
        const promptInputMap = safeJsonParse(serializedPromptInputMap, {});
        promptInputMap[slug] = value;
        localStorage.setItem(
          USER_PROMPT_INPUT_MAP,
          JSON.stringify(promptInputMap)
        );
      }, 500),
    []
  );

  useEffect(() => {
    debouncedWriteToStorage(promptInput, threadSlug ?? workspaceSlug);

    return () => {