tutorial-context.tsx 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import getMeta from '@/utils/meta'
  2. import {
  3. createContext,
  4. FC,
  5. MutableRefObject,
  6. useCallback,
  7. useContext,
  8. useMemo,
  9. useRef,
  10. useState,
  11. } from 'react'
  12. export const TutorialContext = createContext<
  13. | {
  14. deactivateTutorial: (tutorial: string) => void
  15. inactiveTutorials: string[]
  16. currentPopup: string | null
  17. currentPopupRef: MutableRefObject<string | null>
  18. setCurrentPopup: (value: string | null) => void
  19. }
  20. | undefined
  21. >(undefined)
  22. export const TutorialProvider: FC<React.PropsWithChildren> = ({ children }) => {
  23. const [inactiveTutorials, setInactiveTutorials] = useState(
  24. () => getMeta('ol-inactiveTutorials') || []
  25. )
  26. const [currentPopup, setCurrentPopupState] = useState<string | null>(null)
  27. const currentPopupRef = useRef<string | null>(null)
  28. const setCurrentPopup = useCallback((value: string | null) => {
  29. currentPopupRef.current = value
  30. setCurrentPopupState(value)
  31. }, [])
  32. const deactivateTutorial = useCallback(
  33. (tutorialKey: string) => {
  34. setInactiveTutorials([...inactiveTutorials, tutorialKey])
  35. },
  36. [inactiveTutorials]
  37. )
  38. const value = useMemo(
  39. () => ({
  40. deactivateTutorial,
  41. inactiveTutorials,
  42. currentPopup,
  43. currentPopupRef,
  44. setCurrentPopup,
  45. }),
  46. [deactivateTutorial, inactiveTutorials, currentPopup, setCurrentPopup]
  47. )
  48. return (
  49. <TutorialContext.Provider value={value}>
  50. {children}
  51. </TutorialContext.Provider>
  52. )
  53. }
  54. export function useTutorialContext() {
  55. const context = useContext(TutorialContext)
  56. if (!context) {
  57. throw new Error(
  58. 'useTutorialContext is only available inside TutorialProvider'
  59. )
  60. }
  61. return context
  62. }