editor-context.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import React, { createContext, useCallback, useContext, useEffect } from 'react'
  2. import PropTypes from 'prop-types'
  3. import usePersistedState from '../../infrastructure/persisted-state-hook'
  4. export const EditorContext = createContext()
  5. EditorContext.Provider.propTypes = {
  6. value: PropTypes.shape({
  7. cobranding: PropTypes.shape({
  8. logoImgUrl: PropTypes.string.isRequired,
  9. brandVariationName: PropTypes.string.isRequired,
  10. brandVariationHomeUrl: PropTypes.string.isRequired
  11. }),
  12. loading: PropTypes.bool,
  13. projectId: PropTypes.string.isRequired,
  14. isProjectOwner: PropTypes.bool
  15. })
  16. }
  17. export function EditorProvider({
  18. children,
  19. loading,
  20. chatIsOpenAngular,
  21. setChatIsOpenAngular,
  22. openDoc,
  23. onlineUsersArray
  24. }) {
  25. const cobranding = window.brandVariation
  26. ? {
  27. logoImgUrl: window.brandVariation.logo_url,
  28. brandVariationName: window.brandVariation.name,
  29. brandVariationHomeUrl: window.brandVariation.home_url
  30. }
  31. : undefined
  32. const ownerId =
  33. window._ide.$scope.project && window._ide.$scope.project.owner
  34. ? window._ide.$scope.project.owner._id
  35. : null
  36. const [chatIsOpen, setChatIsOpen] = usePersistedState(
  37. 'editor.ui.chat.open',
  38. false
  39. )
  40. const toggleChatOpen = useCallback(() => {
  41. setChatIsOpen(!chatIsOpen)
  42. setChatIsOpenAngular(!chatIsOpen)
  43. }, [chatIsOpen, setChatIsOpenAngular, setChatIsOpen])
  44. // updates React's `chatIsOpen` state when the chat is opened by Angular.
  45. // In order to prevent race conditions with `toggleChatOpen` it's not a 1:1 binding:
  46. // Angular forces the React state to `true`, but can only set it to `false` when
  47. // the React state is explicitly `true`.
  48. useEffect(() => {
  49. if (chatIsOpenAngular) {
  50. setChatIsOpen(true)
  51. } else if (chatIsOpen) {
  52. setChatIsOpen(false)
  53. }
  54. }, [chatIsOpenAngular, chatIsOpen, setChatIsOpen])
  55. const editorContextValue = {
  56. cobranding,
  57. loading,
  58. projectId: window.project_id,
  59. isProjectOwner: ownerId === window.user.id,
  60. openDoc,
  61. onlineUsersArray,
  62. ui: {
  63. chatIsOpen,
  64. toggleChatOpen
  65. }
  66. }
  67. return (
  68. <EditorContext.Provider value={editorContextValue}>
  69. {children}
  70. </EditorContext.Provider>
  71. )
  72. }
  73. EditorProvider.propTypes = {
  74. children: PropTypes.any,
  75. loading: PropTypes.bool,
  76. chatIsOpenAngular: PropTypes.bool,
  77. setChatIsOpenAngular: PropTypes.func.isRequired,
  78. openDoc: PropTypes.func.isRequired,
  79. onlineUsersArray: PropTypes.array.isRequired
  80. }
  81. export function useEditorContext(propTypes) {
  82. const data = useContext(EditorContext)
  83. PropTypes.checkPropTypes(propTypes, data, 'data', 'EditorContext.Provider')
  84. return data
  85. }