| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- import { forwardRef, memo, MouseEventHandler } from 'react'
- import {
- Dropdown,
- DropdownMenu,
- DropdownToggle,
- } from '@/shared/components/dropdown/dropdown-menu'
- import OLDropdownMenuItem from '@/shared/components/ol/ol-dropdown-menu-item'
- import MaterialIcon from '@/shared/components/material-icon'
- import classNames from 'classnames'
- import { useTrackChangesStateActionsContext } from '../context/track-changes-state-context'
- import { useUserContext } from '@/shared/context/user-context'
- import { useTranslation } from 'react-i18next'
- import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
- import usePersistedState from '@/shared/hooks/use-persisted-state'
- import { sendMB } from '@/infrastructure/event-tracking'
- import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
- import { useProjectContext } from '@/shared/context/project-context'
- import { useCodeMirrorViewContext } from '@/features/source-editor/components/codemirror-context'
- import { useEditorContext } from '@/shared/context/editor-context'
- import { useTrackingChangesMode } from '@/shared/hooks/use-tracking-changes-mode'
- function ReviewModeSwitcher() {
- const { t } = useTranslation()
- const user = useUserContext()
- const { saveTrackChangesForCurrentUser, saveTrackChanges } =
- useTrackChangesStateActionsContext()
- const mode = useTrackingChangesMode()
- const { permissionsLevel } = useIdeReactContext()
- const { write, trackedWrite } = usePermissionsContext()
- const { features } = useProjectContext()
- const { setUpgradeTrackChangesModal } = useEditorContext()
- const showViewOption = permissionsLevel === 'readOnly'
- const view = useCodeMirrorViewContext()
- return (
- <div className="review-mode-switcher-container">
- <Dropdown className="review-mode-switcher" align="end">
- <DropdownToggle
- as={ModeSwitcherToggleButton}
- id="review-mode-switcher"
- />
- <DropdownMenu flip={false}>
- <OLDropdownMenuItem
- disabled={!write}
- onClick={() => {
- if (mode === 'edit') {
- view.focus()
- return
- }
- sendMB('editing-mode-change', {
- role: permissionsLevel,
- previousMode: mode,
- newMode: 'edit',
- })
- if (user?.id) {
- saveTrackChangesForCurrentUser(false)
- } else {
- saveTrackChanges({ on_for_guests: false })
- }
- view.focus()
- }}
- description={t('edit_content_directly')}
- leadingIcon="edit"
- active={write && mode === 'edit'}
- >
- {t('editing')}
- </OLDropdownMenuItem>
- <OLDropdownMenuItem
- disabled={permissionsLevel === 'readOnly'}
- onClick={() => {
- if (mode === 'review') {
- view.focus()
- return
- }
- if (!features.trackChanges) {
- setUpgradeTrackChangesModal({
- show: true,
- location: 'review-switcher',
- })
- } else {
- sendMB('editing-mode-change', {
- role: permissionsLevel,
- previousMode: mode,
- newMode: 'review',
- })
- if (user?.id) {
- saveTrackChangesForCurrentUser(true)
- } else {
- saveTrackChanges({ on_for_guests: true })
- }
- view.focus()
- }
- }}
- description={
- permissionsLevel === 'review' && !trackedWrite
- ? t('comment_only')
- : t('edits_become_suggestions')
- }
- leadingIcon="rate_review"
- active={trackedWrite && mode === 'review'}
- >
- {t('reviewing')}
- </OLDropdownMenuItem>
- {showViewOption && (
- <OLDropdownMenuItem
- description={t('can_view_content')}
- leadingIcon="visibility"
- active={mode === 'view'}
- >
- {t('viewing')}
- </OLDropdownMenuItem>
- )}
- </DropdownMenu>
- </Dropdown>
- </div>
- )
- }
- const ModeSwitcherToggleButton = forwardRef<
- HTMLButtonElement,
- { onClick: MouseEventHandler<HTMLButtonElement>; 'aria-expanded': boolean }
- >(({ onClick, 'aria-expanded': ariaExpanded }, ref) => {
- const { t } = useTranslation()
- const mode = useTrackingChangesMode()
- if (mode === 'edit') {
- return (
- <ModeSwitcherToggleButtonContent
- ref={ref}
- onClick={onClick}
- className="editing"
- iconType="edit"
- label={t('editing')}
- ariaExpanded={ariaExpanded}
- />
- )
- } else if (mode === 'review') {
- return (
- <ModeSwitcherToggleButtonContent
- ref={ref}
- onClick={onClick}
- className="reviewing"
- iconType="rate_review"
- label={t('reviewing')}
- ariaExpanded={ariaExpanded}
- />
- )
- }
- return (
- <ModeSwitcherToggleButtonContent
- ref={ref}
- onClick={onClick}
- className="viewing"
- iconType="visibility"
- label={t('viewing')}
- ariaExpanded={ariaExpanded}
- />
- )
- })
- const ModeSwitcherToggleButtonContent = forwardRef<
- HTMLButtonElement,
- {
- onClick: MouseEventHandler<HTMLButtonElement>
- className: string
- iconType: string
- label: string
- ariaExpanded: boolean
- }
- >(({ onClick, className, iconType, label, ariaExpanded }, ref) => {
- const [isFirstTimeUsed, setIsFirstTimeUsed] = usePersistedState(
- `modeSwitcherFirstTimeUsed`,
- true
- )
- return (
- <button
- className={classNames('review-mode-switcher-toggle-button', className, {
- 'review-mode-switcher-toggle-button-expanded': isFirstTimeUsed,
- })}
- ref={ref}
- onClick={event => {
- setIsFirstTimeUsed(false)
- onClick(event)
- }}
- aria-expanded={ariaExpanded}
- aria-label={label}
- >
- <MaterialIcon type={iconType} />
- <div className="review-mode-switcher-toggle-label">{label}</div>
- <MaterialIcon type="keyboard_arrow_down" />
- </button>
- )
- })
- ModeSwitcherToggleButton.displayName = 'ModeSwitcherToggleButton'
- ModeSwitcherToggleButtonContent.displayName = 'ModeSwitcherToggleButtonContent'
- export default memo(ReviewModeSwitcher)
|