monaco-editor-lsp-next/src/hooks/use-problem.ts

129 lines
4.0 KiB
TypeScript
Raw Normal View History

import { getPath } from "@/lib/utils";
import { EditorLanguage } from "@prisma/client";
import { useCallback, useEffect, useMemo } from "react";
import { useMonacoTheme } from "@/hooks/use-monaco-theme";
import { useProblemStore } from "@/providers/problem-store-provider";
/**
* Generates a localStorage key for storing the editor language of a problem.
* Format: "lang_{problemId}"
*/
const getProblemLangStorageKey = (problemId: string) => `lang_${problemId}`;
/**
* Generates a localStorage key for storing the editor content of a problem for a specific language.
* Format: "{language}_{problemId}"
*/
const getProblemValueStorageKey = (problemId: string, language: EditorLanguage) =>
`${language}_${problemId}`;
/**
* Retrieves the stored editor language for a specific problem.
* Falls back to the global language if no stored value is found.
*/
const getStoredProblemLang = (problemId: string, globalLang: EditorLanguage) =>
(localStorage.getItem(getProblemLangStorageKey(problemId)) as EditorLanguage) ?? globalLang;
/**
* Retrieves the stored editor content for a specific problem and language.
* Falls back to the default template if no stored value is found.
*/
const getStoredProblemValue = (
problemId: string,
defaultValue: string,
language: EditorLanguage
) => localStorage.getItem(getProblemValueStorageKey(problemId, language)) ?? defaultValue;
export const useProblem = () => {
const { currentTheme } = useMonacoTheme();
const {
hydrated,
editor,
globalLang,
currentLang,
currentValue,
setEditor,
setGlobalLang,
setCurrentLang,
setCurrentValue,
problemId,
templates,
editorLanguageConfigs,
languageServerConfigs,
} = useProblemStore((state) => state);
// Get the default template for the current language from the templates list
const currentTemplate = useMemo(
() => templates.find((t) => t.language === currentLang)?.template || "",
[templates, currentLang]
);
const currentEditorLanguageConfig = useMemo(
() => editorLanguageConfigs.find((c) => c.language === currentLang),
[editorLanguageConfigs, currentLang]
);
const currentLanguageServerConfig = useMemo(
() => languageServerConfigs.find((c) => c.language === currentLang),
[languageServerConfigs, currentLang]
);
const currentPath = useMemo(
() => (currentEditorLanguageConfig ? getPath(problemId, currentEditorLanguageConfig) : ""),
[problemId, currentEditorLanguageConfig]
);
// On initialization, load the stored language and corresponding code content
useEffect(() => {
const storedLang = getStoredProblemLang(problemId, globalLang);
setCurrentLang(storedLang);
const storedValue = getStoredProblemValue(problemId, currentTemplate, storedLang);
setCurrentValue(storedValue);
}, [problemId, globalLang, currentTemplate, setCurrentLang, setCurrentValue]);
// Change the language and update localStorage and state accordingly
const changeLang = useCallback(
(newLang: EditorLanguage) => {
if (!problemId || newLang === currentLang) return;
// Update the stored language in localStorage
localStorage.setItem(getProblemLangStorageKey(problemId), newLang);
setCurrentLang(newLang);
setGlobalLang(newLang);
},
[problemId, currentLang, setCurrentLang, setGlobalLang]
);
// Update the stored code content when the editor value changes, specific to the current language
const changeValue = useCallback(
(newValue: string) => {
if (!problemId || newValue === currentValue) return;
localStorage.setItem(getProblemValueStorageKey(problemId, currentLang), newValue);
setCurrentValue(newValue);
},
[problemId, currentValue, currentLang, setCurrentValue]
);
return {
hydrated,
editor,
setEditor,
globalLang,
currentLang,
currentValue,
problemId,
templates,
editorLanguageConfigs,
languageServerConfigs,
currentTemplate,
currentEditorLanguageConfig,
currentLanguageServerConfig,
currentPath,
currentTheme,
changeLang,
changeValue,
};
};