toolbar-header.jsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import React from 'react'
  2. import PropTypes from 'prop-types'
  3. import { useTranslation } from 'react-i18next'
  4. import MenuButton from './menu-button'
  5. import CobrandingLogo from './cobranding-logo'
  6. import BackToProjectsButton from './back-to-projects-button'
  7. import UpgradePrompt from './upgrade-prompt'
  8. import ChatToggleButton from './chat-toggle-button'
  9. import LayoutDropdownButton from './layout-dropdown-button'
  10. import OnlineUsersWidget from './online-users-widget'
  11. import ProjectNameEditableLabel from './project-name-editable-label'
  12. import TrackChangesToggleButton from './track-changes-toggle-button'
  13. import HistoryToggleButton from './history-toggle-button'
  14. import ShareProjectButton from './share-project-button'
  15. import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
  16. import BackToEditorButton from './back-to-editor-button'
  17. import getMeta from '@/utils/meta'
  18. import { isSplitTestEnabled } from '@/utils/splitTestUtils'
  19. const [publishModalModules] = importOverleafModules('publishModal')
  20. const PublishButton = publishModalModules?.import.default
  21. const offlineModeToolbarButtons = importOverleafModules(
  22. 'offlineModeToolbarButtons'
  23. )
  24. // double opt-in
  25. const enableROMirrorOnClient =
  26. isSplitTestEnabled('ro-mirror-on-client') &&
  27. new URLSearchParams(window.location.search).get('ro-mirror-on-client') ===
  28. 'enabled'
  29. const ToolbarHeader = React.memo(function ToolbarHeader({
  30. cobranding,
  31. onShowLeftMenuClick,
  32. chatIsOpen,
  33. toggleChatOpen,
  34. reviewPanelOpen,
  35. toggleReviewPanelOpen,
  36. historyIsOpen,
  37. toggleHistoryOpen,
  38. unreadMessageCount,
  39. onlineUsers,
  40. goToUser,
  41. isRestrictedTokenMember,
  42. hasPublishPermissions,
  43. chatVisible,
  44. projectName,
  45. renameProject,
  46. hasRenamePermissions,
  47. openShareModal,
  48. trackChangesVisible,
  49. }) {
  50. const { t } = useTranslation()
  51. const shouldDisplayPublishButton = hasPublishPermissions && PublishButton
  52. return (
  53. <header
  54. className="toolbar toolbar-header toolbar-with-labels"
  55. role="navigation"
  56. aria-label={t('project_layout_sharing_submission')}
  57. >
  58. <div className="toolbar-left">
  59. <MenuButton onClick={onShowLeftMenuClick} />
  60. {cobranding && cobranding.logoImgUrl && (
  61. <CobrandingLogo {...cobranding} />
  62. )}
  63. <BackToProjectsButton />
  64. {enableROMirrorOnClient &&
  65. offlineModeToolbarButtons.map(
  66. ({ path, import: { default: OfflineModeToolbarButton } }) => {
  67. return <OfflineModeToolbarButton key={path} />
  68. }
  69. )}
  70. </div>
  71. {getMeta('ol-showUpgradePrompt') && <UpgradePrompt />}
  72. <ProjectNameEditableLabel
  73. className="toolbar-center"
  74. projectName={projectName}
  75. hasRenamePermissions={hasRenamePermissions}
  76. onChange={renameProject}
  77. />
  78. <div className="toolbar-right">
  79. <OnlineUsersWidget onlineUsers={onlineUsers} goToUser={goToUser} />
  80. {historyIsOpen ? (
  81. <BackToEditorButton onClick={toggleHistoryOpen} />
  82. ) : (
  83. <>
  84. {trackChangesVisible && (
  85. <TrackChangesToggleButton
  86. onMouseDown={toggleReviewPanelOpen}
  87. disabled={historyIsOpen}
  88. trackChangesIsOpen={reviewPanelOpen}
  89. />
  90. )}
  91. <ShareProjectButton onClick={openShareModal} />
  92. {shouldDisplayPublishButton && (
  93. <PublishButton cobranding={cobranding} />
  94. )}
  95. {!isRestrictedTokenMember && (
  96. <HistoryToggleButton onClick={toggleHistoryOpen} />
  97. )}
  98. <LayoutDropdownButton />
  99. {chatVisible && (
  100. <ChatToggleButton
  101. chatIsOpen={chatIsOpen}
  102. onClick={toggleChatOpen}
  103. unreadMessageCount={unreadMessageCount}
  104. />
  105. )}
  106. </>
  107. )}
  108. </div>
  109. </header>
  110. )
  111. })
  112. ToolbarHeader.propTypes = {
  113. onShowLeftMenuClick: PropTypes.func.isRequired,
  114. cobranding: PropTypes.object,
  115. chatIsOpen: PropTypes.bool,
  116. toggleChatOpen: PropTypes.func.isRequired,
  117. reviewPanelOpen: PropTypes.bool,
  118. toggleReviewPanelOpen: PropTypes.func.isRequired,
  119. historyIsOpen: PropTypes.bool,
  120. toggleHistoryOpen: PropTypes.func.isRequired,
  121. unreadMessageCount: PropTypes.number.isRequired,
  122. onlineUsers: PropTypes.array.isRequired,
  123. goToUser: PropTypes.func.isRequired,
  124. isRestrictedTokenMember: PropTypes.bool,
  125. hasPublishPermissions: PropTypes.bool,
  126. chatVisible: PropTypes.bool,
  127. projectName: PropTypes.string.isRequired,
  128. renameProject: PropTypes.func.isRequired,
  129. hasRenamePermissions: PropTypes.bool,
  130. openShareModal: PropTypes.func.isRequired,
  131. trackChangesVisible: PropTypes.bool,
  132. }
  133. export default ToolbarHeader