import { forwardRef, memo, MouseEventHandler, useRef, useState } from 'react' import { Dropdown, DropdownMenu, DropdownToggle, } from '@/features/ui/components/bootstrap-5/dropdown-menu' import OLDropdownMenuItem from '@/features/ui/components/ol/ol-dropdown-menu-item' import MaterialIcon from '@/shared/components/material-icon' import classNames from 'classnames' import { useTrackChangesStateActionsContext, useTrackChangesStateContext, } 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 { useEditorContext } from '@/shared/context/editor-context' import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context' import { useProjectContext } from '@/shared/context/project-context' import UpgradeTrackChangesModal from './upgrade-track-changes-modal' import { ReviewModePromo } from '@/features/review-panel-new/components/review-mode-promo' import useTutorial from '@/shared/hooks/promotions/use-tutorial' import { useLayoutContext } from '@/shared/context/layout-context' import { useCodeMirrorViewContext } from '@/features/source-editor/components/codemirror-context' type Mode = 'view' | 'review' | 'edit' const useCurrentMode = (): Mode => { const trackChanges = useTrackChangesStateContext() const user = useUserContext() const trackChangesForCurrentUser = trackChanges?.onForEveryone || (user?.id && trackChanges?.onForMembers[user.id]) || (!user?.id && trackChanges?.onForGuests) const { permissionsLevel } = useIdeReactContext() if (permissionsLevel === 'readOnly') { return 'view' } else if (permissionsLevel === 'review') { return 'review' } else if (trackChangesForCurrentUser) { return 'review' } else { return 'edit' } } function ReviewModeSwitcher() { const { t } = useTranslation() const user = useUserContext() const { saveTrackChangesForCurrentUser, saveTrackChanges } = useTrackChangesStateActionsContext() const mode = useCurrentMode() const { permissionsLevel } = useIdeReactContext() const { write, trackedWrite } = usePermissionsContext() const { features } = useProjectContext() const [showUpgradeModal, setShowUpgradeModal] = useState(false) const showViewOption = permissionsLevel === 'readOnly' const view = useCodeMirrorViewContext() return (
{ 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')} { if (mode === 'review') { view.focus() return } if (!features.trackChanges) { setShowUpgradeModal(true) } 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')} {showViewOption && ( {t('viewing')} )}
) } const ModeSwitcherToggleButton = forwardRef< HTMLButtonElement, { onClick: MouseEventHandler; 'aria-expanded': boolean } >(({ onClick, 'aria-expanded': ariaExpanded }, ref) => { const { t } = useTranslation() const mode = useCurrentMode() if (mode === 'edit') { return ( ) } else if (mode === 'review') { return ( ) } return ( ) }) const ModeSwitcherToggleButtonContent = forwardRef< HTMLButtonElement, { onClick: MouseEventHandler className: string iconType: string label: string ariaExpanded: boolean currentMode: string } >(({ onClick, className, iconType, label, ariaExpanded, currentMode }, ref) => { const [isFirstTimeUsed, setIsFirstTimeUsed] = usePersistedState( `modeSwitcherFirstTimeUsed`, true ) const tutorialProps = useTutorial('review-mode', { name: 'review-mode-notification', }) const user = useUserContext() const { features } = useProjectContext() const { reviewPanelOpen } = useLayoutContext() const { inactiveTutorials } = useEditorContext() const hasCompletedReviewModeTutorial = inactiveTutorials.includes('review-mode') const canShowReviewModePromo = reviewPanelOpen && currentMode !== 'review' && features.trackChanges && user.signUpDate && user.signUpDate < '2025-03-15' && !hasCompletedReviewModeTutorial const containerRef = useRef(null) return ( <> {canShowReviewModePromo && ( )} ) }) ModeSwitcherToggleButton.displayName = 'ModeSwitcherToggleButton' ModeSwitcherToggleButtonContent.displayName = 'ModeSwitcherToggleButtonContent' export default memo(ReviewModeSwitcher)