editor-context.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import React, { createContext, useCallback, useContext, useEffect } from 'react'
  2. import PropTypes from 'prop-types'
  3. import useScopeValue from './util/scope-value-hook'
  4. import useBrowserWindow from '../hooks/use-browser-window'
  5. import { useIdeContext } from './ide-context'
  6. export const EditorContext = createContext()
  7. EditorContext.Provider.propTypes = {
  8. value: PropTypes.shape({
  9. cobranding: PropTypes.shape({
  10. logoImgUrl: PropTypes.string.isRequired,
  11. brandVariationName: PropTypes.string.isRequired,
  12. brandVariationId: PropTypes.number.isRequired,
  13. brandId: PropTypes.number.isRequired,
  14. brandVariationHomeUrl: PropTypes.string.isRequired,
  15. publishGuideHtml: PropTypes.string,
  16. partner: PropTypes.string,
  17. brandedMenu: PropTypes.string,
  18. submitBtnHtml: PropTypes.string,
  19. }),
  20. hasPremiumCompile: PropTypes.bool,
  21. loading: PropTypes.bool,
  22. projectRootDocId: PropTypes.string,
  23. projectId: PropTypes.string.isRequired,
  24. projectName: PropTypes.string.isRequired,
  25. renameProject: PropTypes.func.isRequired,
  26. isProjectOwner: PropTypes.bool,
  27. isRestrictedTokenMember: PropTypes.bool,
  28. rootFolder: PropTypes.object,
  29. }),
  30. }
  31. export function EditorProvider({ children, settings }) {
  32. const ide = useIdeContext()
  33. const cobranding = window.brandVariation
  34. ? {
  35. logoImgUrl: window.brandVariation.logo_url,
  36. brandVariationName: window.brandVariation.name,
  37. brandVariationId: window.brandVariation.id,
  38. brandId: window.brandVariation.brand_id,
  39. brandVariationHomeUrl: window.brandVariation.home_url,
  40. publishGuideHtml: window.brandVariation.publish_guide_html,
  41. partner: window.brandVariation.partner,
  42. brandedMenu: window.brandVariation.branded_menu,
  43. submitBtnHtml: window.brandVariation.submit_button_html,
  44. }
  45. : undefined
  46. const [loading] = useScopeValue('state.loading')
  47. const [projectRootDocId] = useScopeValue('project.rootDoc_id')
  48. const [projectName, setProjectName] = useScopeValue('project.name')
  49. const [compileGroup] = useScopeValue('project.features.compileGroup')
  50. const [rootFolder] = useScopeValue('rootFolder')
  51. const [ownerId] = useScopeValue('project.owner._id')
  52. const renameProject = useCallback(
  53. newName => {
  54. setProjectName(oldName => {
  55. if (oldName !== newName) {
  56. settings.saveProjectSettings({ name: newName }).catch(response => {
  57. setProjectName(oldName)
  58. const { data, status } = response
  59. if (status === 400) {
  60. return ide.showGenericMessageModal('Error renaming project', data)
  61. } else {
  62. return ide.showGenericMessageModal(
  63. 'Error renaming project',
  64. 'Please try again in a moment'
  65. )
  66. }
  67. })
  68. }
  69. return newName
  70. })
  71. },
  72. [settings, ide, setProjectName]
  73. )
  74. const { setTitle } = useBrowserWindow()
  75. useEffect(() => {
  76. setTitle(
  77. `${projectName ? projectName + ' - ' : ''}Online LaTeX Editor ${
  78. window.ExposedSettings.appName
  79. }`
  80. )
  81. }, [projectName, setTitle])
  82. const editorContextValue = {
  83. cobranding,
  84. hasPremiumCompile: compileGroup === 'priority',
  85. loading,
  86. projectId: window.project_id,
  87. projectRootDocId,
  88. projectName: projectName || '', // initially might be empty in Angular
  89. renameProject,
  90. isProjectOwner: ownerId === window.user.id,
  91. isRestrictedTokenMember: window.isRestrictedTokenMember,
  92. rootFolder,
  93. }
  94. return (
  95. <EditorContext.Provider value={editorContextValue}>
  96. {children}
  97. </EditorContext.Provider>
  98. )
  99. }
  100. EditorProvider.propTypes = {
  101. children: PropTypes.any,
  102. settings: PropTypes.any.isRequired,
  103. }
  104. export function useEditorContext(propTypes) {
  105. const context = useContext(EditorContext)
  106. if (!context) {
  107. throw new Error('useEditorContext is only available inside EditorProvider')
  108. }
  109. PropTypes.checkPropTypes(propTypes, context, 'data', 'EditorContext.Provider')
  110. return context
  111. }