editor-navigation-toolbar-root.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import React, { useCallback } from 'react'
  2. import PropTypes from 'prop-types'
  3. import ToolbarHeader from './toolbar-header'
  4. import { useEditorContext } from '../../../shared/context/editor-context'
  5. import { useChatContext } from '../../chat/context/chat-context'
  6. import { useLayoutContext } from '../../../shared/context/layout-context'
  7. import { useProjectContext } from '../../../shared/context/project-context'
  8. const projectContextPropTypes = {
  9. name: PropTypes.string.isRequired,
  10. features: PropTypes.shape({
  11. trackChangesVisible: PropTypes.bool,
  12. }).isRequired,
  13. }
  14. const editorContextPropTypes = {
  15. cobranding: PropTypes.object,
  16. loading: PropTypes.bool,
  17. isRestrictedTokenMember: PropTypes.bool,
  18. renameProject: PropTypes.func.isRequired,
  19. isProjectOwner: PropTypes.bool,
  20. permissionsLevel: PropTypes.string,
  21. }
  22. const layoutContextPropTypes = {
  23. chatIsOpen: PropTypes.bool,
  24. setChatIsOpen: PropTypes.func.isRequired,
  25. reviewPanelOpen: PropTypes.bool,
  26. setReviewPanelOpen: PropTypes.func.isRequired,
  27. view: PropTypes.string,
  28. setView: PropTypes.func.isRequired,
  29. setLeftMenuShown: PropTypes.func.isRequired,
  30. pdfLayout: PropTypes.string.isRequired,
  31. }
  32. const chatContextPropTypes = {
  33. markMessagesAsRead: PropTypes.func.isRequired,
  34. unreadMessageCount: PropTypes.number.isRequired,
  35. }
  36. const EditorNavigationToolbarRoot = React.memo(
  37. function EditorNavigationToolbarRoot({
  38. onlineUsersArray,
  39. openDoc,
  40. openShareProjectModal,
  41. }) {
  42. const {
  43. name: projectName,
  44. features: { trackChangesVisible },
  45. } = useProjectContext(projectContextPropTypes)
  46. const {
  47. cobranding,
  48. loading,
  49. isRestrictedTokenMember,
  50. renameProject,
  51. isProjectOwner,
  52. permissionsLevel,
  53. } = useEditorContext(editorContextPropTypes)
  54. const {
  55. reattach,
  56. detach,
  57. detachMode,
  58. detachRole,
  59. changeLayout,
  60. chatIsOpen,
  61. setChatIsOpen,
  62. reviewPanelOpen,
  63. setReviewPanelOpen,
  64. view,
  65. setView,
  66. setLeftMenuShown,
  67. pdfLayout,
  68. } = useLayoutContext(layoutContextPropTypes)
  69. const { markMessagesAsRead, unreadMessageCount } = useChatContext(
  70. chatContextPropTypes
  71. )
  72. const toggleChatOpen = useCallback(() => {
  73. if (!chatIsOpen) {
  74. markMessagesAsRead()
  75. }
  76. setChatIsOpen(value => !value)
  77. }, [chatIsOpen, setChatIsOpen, markMessagesAsRead])
  78. const toggleReviewPanelOpen = useCallback(
  79. () => setReviewPanelOpen(value => !value),
  80. [setReviewPanelOpen]
  81. )
  82. const toggleHistoryOpen = useCallback(() => {
  83. setView(view === 'history' ? 'editor' : 'history')
  84. }, [view, setView])
  85. const togglePdfView = useCallback(() => {
  86. setView(view === 'pdf' ? 'editor' : 'pdf')
  87. }, [view, setView])
  88. const handleChangeLayout = useCallback(
  89. (newLayout, newView) => {
  90. changeLayout(newLayout, newView)
  91. },
  92. [changeLayout]
  93. )
  94. const openShareModal = useCallback(() => {
  95. openShareProjectModal(isProjectOwner)
  96. }, [openShareProjectModal, isProjectOwner])
  97. const onShowLeftMenuClick = useCallback(
  98. () => setLeftMenuShown(value => !value),
  99. [setLeftMenuShown]
  100. )
  101. const goToUser = useCallback(
  102. user => {
  103. if (user.doc && typeof user.row === 'number') {
  104. openDoc(user.doc, { gotoLine: user.row + 1 })
  105. }
  106. },
  107. [openDoc]
  108. )
  109. // using {display: 'none'} as 1:1 migration from Angular's ng-hide. Using
  110. // `loading ? null : <ToolbarHeader/>` causes UI glitches
  111. return (
  112. <ToolbarHeader
  113. reattach={reattach}
  114. detach={detach}
  115. detachMode={detachMode}
  116. detachRole={detachRole}
  117. style={loading ? { display: 'none' } : {}}
  118. cobranding={cobranding}
  119. onShowLeftMenuClick={onShowLeftMenuClick}
  120. handleChangeLayout={handleChangeLayout}
  121. chatIsOpen={chatIsOpen}
  122. unreadMessageCount={unreadMessageCount}
  123. toggleChatOpen={toggleChatOpen}
  124. reviewPanelOpen={reviewPanelOpen}
  125. toggleReviewPanelOpen={toggleReviewPanelOpen}
  126. historyIsOpen={view === 'history'}
  127. toggleHistoryOpen={toggleHistoryOpen}
  128. onlineUsers={onlineUsersArray}
  129. goToUser={goToUser}
  130. isRestrictedTokenMember={isRestrictedTokenMember}
  131. hasPublishPermissions={
  132. permissionsLevel === 'owner' || permissionsLevel === 'readAndWrite'
  133. }
  134. projectName={projectName}
  135. renameProject={renameProject}
  136. hasRenamePermissions={permissionsLevel === 'owner'}
  137. openShareModal={openShareModal}
  138. pdfViewIsOpen={view === 'pdf'}
  139. pdfButtonIsVisible={pdfLayout === 'flat'}
  140. togglePdfView={togglePdfView}
  141. trackChangesVisible={trackChangesVisible}
  142. pdfLayout={pdfLayout}
  143. view={view}
  144. />
  145. )
  146. }
  147. )
  148. EditorNavigationToolbarRoot.propTypes = {
  149. onlineUsersArray: PropTypes.array.isRequired,
  150. openDoc: PropTypes.func.isRequired,
  151. openShareProjectModal: PropTypes.func.isRequired,
  152. }
  153. export default EditorNavigationToolbarRoot