user-features-context.tsx 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import {
  2. createContext,
  3. FC,
  4. useCallback,
  5. useContext,
  6. useEffect,
  7. useState,
  8. } from 'react'
  9. import { User } from '../../../../types/user'
  10. import { useUserContext } from './user-context'
  11. import { useReceiveUser } from '../hooks/user-channel/use-receive-user'
  12. import { getJSON } from '@/infrastructure/fetch-json'
  13. import { useEditorContext } from './editor-context'
  14. import getMeta from '@/utils/meta'
  15. export const UserFeaturesContext = createContext<User['features']>(undefined)
  16. const hasUnlimitedAi = getMeta('ol-hasUnlimitedAi')
  17. export const UserFeaturesProvider: FC<React.PropsWithChildren> = ({
  18. children,
  19. }) => {
  20. const user = useUserContext()
  21. const { writefullInstance } = useEditorContext()
  22. const [features, setFeatures] = useState(user.features || {})
  23. useReceiveUser(
  24. useCallback(data => {
  25. if (data?.features) {
  26. setFeatures(data.features)
  27. }
  28. }, [])
  29. )
  30. useEffect(() => {
  31. const listener = async ({ isPremium }: { isPremium: boolean }) => {
  32. // todo: quota clean-up: remove once we are transitioned off aiErrorAssistant naming
  33. const hasPremiumQuota = hasUnlimitedAi
  34. const alreadyPremium =
  35. features?.aiErrorAssistant === isPremium ||
  36. hasPremiumQuota === isPremium
  37. if (alreadyPremium) {
  38. // the user is premium on writefull and has the AI assist, no need to refresh the features
  39. return
  40. }
  41. const newFeatures = await getJSON('/user/features')
  42. setFeatures(newFeatures)
  43. }
  44. writefullInstance?.addEventListener('writefull-login-complete', listener)
  45. return () => {
  46. writefullInstance?.removeEventListener(
  47. 'writefull-login-complete',
  48. listener
  49. )
  50. }
  51. }, [features?.aiErrorAssistant, writefullInstance])
  52. return (
  53. <UserFeaturesContext.Provider value={features}>
  54. {children}
  55. </UserFeaturesContext.Provider>
  56. )
  57. }
  58. export function useUserFeaturesContext() {
  59. const context = useContext(UserFeaturesContext)
  60. if (!context) {
  61. throw new Error(
  62. 'useUserFeaturesContext is only available inside UserFeaturesContext'
  63. )
  64. }
  65. return context
  66. }