| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- import {
- DropdownItem,
- DropdownHeader,
- DropdownDivider,
- } from '@/shared/components/dropdown/dropdown-menu'
- import {
- IdeLayout,
- IdeView,
- useLayoutContext,
- } from '@/shared/context/layout-context'
- import React from 'react'
- import { useTranslation } from 'react-i18next'
- import { DetachRole } from '@/shared/context/detach-context'
- import OLSpinner from '@/shared/components/ol/ol-spinner'
- import { isMac } from '@/shared/utils/os'
- import { Shortcut } from '@/shared/components/shortcut'
- import classNames from 'classnames'
- import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
- import { useFeatureFlag } from '@/shared/context/split-test-context'
- import SplitTestBadge from '@/shared/components/split-test-badge'
- type LayoutOption =
- | 'sideBySide'
- | 'editorOnly'
- | 'pdfOnly'
- | 'detachedPdf'
- | 'focusMode'
- const getActiveLayoutOption = ({
- pdfLayout,
- view,
- detachRole,
- }: {
- pdfLayout: IdeLayout
- view: IdeView | null
- detachRole?: DetachRole
- }): LayoutOption | null => {
- if (view === 'history') {
- return null
- }
- if (detachRole === 'detacher') {
- return 'detachedPdf'
- }
- if (pdfLayout === 'flat' && (view === 'editor' || view === 'file')) {
- return 'editorOnly'
- }
- if (pdfLayout === 'flat' && view === 'pdf') {
- return 'pdfOnly'
- }
- if (pdfLayout === 'sideBySide') {
- return 'sideBySide'
- }
- return null
- }
- const LayoutDropdownItem = ({
- active,
- disabled = false,
- processing = false,
- leadingIcon,
- trailingIcon,
- onClick,
- children,
- }: {
- active: boolean
- leadingIcon: React.ReactNode
- trailingIcon?: React.ReactNode
- onClick: () => void
- children: React.ReactNode
- processing?: boolean
- disabled?: boolean
- }) => {
- if (processing) {
- leadingIcon = <OLSpinner size="sm" />
- } else if (active) {
- leadingIcon = 'check'
- }
- return (
- <DropdownItem
- active={active}
- aria-current={active}
- disabled={disabled}
- onClick={onClick}
- leadingIcon={leadingIcon}
- trailingIcon={trailingIcon}
- className={classNames({ 'dropdown-item-wide': isMac })}
- >
- {children}
- </DropdownItem>
- )
- }
- const shortcuts: Record<LayoutOption, string[] | null> = isMac
- ? {
- editorOnly: ['⌃', '⌘', '←'],
- pdfOnly: ['⌃', '⌘', '→'],
- sideBySide: ['⌃', '⌘', '↓'],
- detachedPdf: ['⌃', '⌘', '↑'],
- focusMode: ['⌘', '⇧', 'M'],
- }
- : {
- editorOnly: null,
- pdfOnly: null,
- sideBySide: null,
- detachedPdf: null,
- focusMode: ['⌃', '⇧', 'M'],
- }
- export default function ChangeLayoutOptions() {
- const {
- detachIsLinked,
- detachRole,
- view,
- pdfLayout,
- handleChangeLayout,
- handleDetach,
- focusMode,
- setFocusMode,
- } = useLayoutContext()
- const { t } = useTranslation()
- const { sendEvent } = useEditorAnalytics()
- const focusModeEnabled = useFeatureFlag('focus-mode')
- const detachable = 'BroadcastChannel' in window
- const activeLayoutOption = getActiveLayoutOption({
- pdfLayout,
- view,
- detachRole,
- })
- const waitingForDetachedLink = !detachIsLinked && detachRole === 'detacher'
- return (
- <>
- <DropdownHeader>{t('layout_options')}</DropdownHeader>
- <LayoutDropdownItem
- onClick={() => handleChangeLayout('sideBySide')}
- active={activeLayoutOption === 'sideBySide'}
- leadingIcon="splitscreen_right"
- trailingIcon={
- shortcuts.sideBySide && <Shortcut keys={shortcuts.sideBySide} />
- }
- >
- {t('split_view')}
- </LayoutDropdownItem>
- <LayoutDropdownItem
- onClick={() => handleChangeLayout('flat', 'editor')}
- active={activeLayoutOption === 'editorOnly'}
- leadingIcon="edit"
- trailingIcon={
- shortcuts.editorOnly && <Shortcut keys={shortcuts.editorOnly} />
- }
- >
- {t('editor_only')}
- </LayoutDropdownItem>
- <LayoutDropdownItem
- onClick={() => handleChangeLayout('flat', 'pdf')}
- active={activeLayoutOption === 'pdfOnly'}
- leadingIcon="picture_as_pdf"
- trailingIcon={
- shortcuts.pdfOnly && <Shortcut keys={shortcuts.pdfOnly} />
- }
- >
- {t('pdf_only')}
- </LayoutDropdownItem>
- <LayoutDropdownItem
- onClick={() => handleDetach()}
- active={activeLayoutOption === 'detachedPdf' && detachIsLinked}
- disabled={!detachable}
- leadingIcon="open_in_new"
- trailingIcon={
- shortcuts.detachedPdf && <Shortcut keys={shortcuts.detachedPdf} />
- }
- processing={waitingForDetachedLink}
- >
- {t('open_pdf_in_separate_tab')}
- </LayoutDropdownItem>
- {focusModeEnabled && (
- <>
- <DropdownDivider />
- <LayoutDropdownItem
- onClick={() => {
- setFocusMode(!focusMode)
- sendEvent('focus-mode-toggle', { focusMode: !focusMode })
- }}
- active={focusMode}
- leadingIcon="crop_free"
- trailingIcon={
- <span className="d-flex align-items-center gap-2">
- <SplitTestBadge
- splitTestName="focus-mode"
- displayOnVariants={['enabled']}
- />
- {shortcuts.focusMode && <Shortcut keys={shortcuts.focusMode} />}
- </span>
- }
- >
- {t('focus_mode')}
- </LayoutDropdownItem>
- </>
- )}
- </>
- )
- }
|