mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 13:13:45 +01:00
[WEB] Move Review Toggle into the toolbar - 2 (#34578)
* wip of adding Review Toggle into the toolbar * renaming to isToolbarMigration * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * removing extra comments --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> GitOrigin-RevId: 2c0b54ae983a32c083def8e9e64ddd0fb7ddf334
This commit is contained in:
committed by
Copybot
co-authored by
Copilot Autofix powered by AI
parent
b04fea4726
commit
6613ef2f18
+105
-71
@@ -18,8 +18,9 @@ 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'
|
||||
import { useFeatureFlag } from '@/shared/context/split-test-context'
|
||||
|
||||
function ReviewModeSwitcher() {
|
||||
function ReviewModeDropdownItems() {
|
||||
const { t } = useTranslation()
|
||||
const user = useUserContext()
|
||||
const { saveTrackChangesForCurrentUser, saveTrackChanges } =
|
||||
@@ -32,6 +33,108 @@ function ReviewModeSwitcher() {
|
||||
const showViewOption = permissionsLevel === 'readOnly'
|
||||
const view = useCodeMirrorViewContext()
|
||||
|
||||
return (
|
||||
<>
|
||||
<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>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function ReviewModeSwitcher() {
|
||||
const isToolbarMigration = useFeatureFlag('writefull-toolbar-migration')
|
||||
|
||||
if (isToolbarMigration) {
|
||||
return (
|
||||
<Dropdown className="review-mode-switcher" align="end">
|
||||
<DropdownToggle
|
||||
as={ModeSwitcherToggleButton}
|
||||
id="review-mode-switcher"
|
||||
/>
|
||||
<DropdownMenu
|
||||
flip={false}
|
||||
popperConfig={{ strategy: 'fixed' }}
|
||||
// renderOnMount ensures the menu is in the DOM on mount so Popper.js
|
||||
// can calculate its position correctly when using strategy: 'fixed'
|
||||
// inside the toolbar's stacking context
|
||||
renderOnMount
|
||||
>
|
||||
<ReviewModeDropdownItems />
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
|
||||
// Portal variant (default): sticky container keeps the button floating
|
||||
// over the editor at top-right of the scroll area.
|
||||
return (
|
||||
<div className="review-mode-switcher-container">
|
||||
<Dropdown className="review-mode-switcher" align="end">
|
||||
@@ -40,76 +143,7 @@ function ReviewModeSwitcher() {
|
||||
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>
|
||||
)}
|
||||
<ReviewModeDropdownItems />
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
||||
+3
-1
@@ -5,11 +5,13 @@ import ReviewPanel from './review-panel'
|
||||
import ReviewModeSwitcher from './review-mode-switcher'
|
||||
import useReviewPanelLayout from '../hooks/use-review-panel-layout'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { useFeatureFlag } from '@/shared/context/split-test-context'
|
||||
|
||||
function ReviewPanelContainer() {
|
||||
const view = useCodeMirrorViewContext()
|
||||
const { showPanel, mini } = useReviewPanelLayout()
|
||||
const { focusMode } = useLayoutContext()
|
||||
const isToolbarMigration = useFeatureFlag('writefull-toolbar-migration')
|
||||
|
||||
if (!view) {
|
||||
return null
|
||||
@@ -17,7 +19,7 @@ function ReviewPanelContainer() {
|
||||
|
||||
return ReactDOM.createPortal(
|
||||
<>
|
||||
{!focusMode && <ReviewModeSwitcher />}
|
||||
{!focusMode && !isToolbarMigration && <ReviewModeSwitcher />}
|
||||
{showPanel && <ReviewPanel mini={mini} />}
|
||||
</>,
|
||||
view.scrollDOM
|
||||
|
||||
@@ -18,6 +18,7 @@ import useDropdown from '../../../shared/hooks/use-dropdown'
|
||||
import { getPanel } from '@codemirror/view'
|
||||
import { createToolbarPanel } from '../extensions/toolbar/toolbar-panel'
|
||||
import EditorSwitch from './editor-switch'
|
||||
import ReviewModeSwitcher from '@/features/review-panel/components/review-mode-switcher'
|
||||
import SwitchToPDFButton from './switch-to-pdf-button'
|
||||
import { DetacherSynctexControl } from '../../pdf-preview/components/detach-synctex-control'
|
||||
import DetachCompileButtonWrapper from '../../pdf-preview/components/detach-compile-button-wrapper'
|
||||
@@ -33,6 +34,7 @@ import Breadcrumbs from '@/features/source-editor/extensions/breadcrumbs'
|
||||
import classNames from 'classnames'
|
||||
import { useUserSettingsContext } from '@/shared/context/user-settings-context'
|
||||
import { useFeatureFlag } from '@/shared/context/split-test-context'
|
||||
import { useProjectContext } from '@/shared/context/project-context'
|
||||
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import ReviewPanelHeaderBuffer from '@/features/review-panel/components/review-panel-header-buffer'
|
||||
@@ -69,6 +71,8 @@ const Toolbar = memo(function Toolbar() {
|
||||
userSettings: { breadcrumbs },
|
||||
} = useUserSettingsContext()
|
||||
const visualPreviewEnabled = useFeatureFlag('visual-preview')
|
||||
const isToolbarMigration = useFeatureFlag('writefull-toolbar-migration')
|
||||
const { features } = useProjectContext()
|
||||
const { focusMode } = useLayoutContext()
|
||||
|
||||
const [overflowed, setOverflowed] = useState(false)
|
||||
@@ -234,6 +238,13 @@ const Toolbar = memo(function Toolbar() {
|
||||
|
||||
<div className="ol-cm-toolbar-button-group ol-cm-toolbar-end">
|
||||
{!visualPreviewEnabled && <EditorSwitch />}
|
||||
{/* trackChangesVisible controls provider/UI availability; trackChanges
|
||||
(checked inside the switcher) controls the actual feature entitlement.
|
||||
Users with trackChangesVisible:true but trackChanges:false see the
|
||||
switcher and get an upgrade modal when clicking "Reviewing". */}
|
||||
{isToolbarMigration && features.trackChangesVisible && (
|
||||
<ReviewModeSwitcher />
|
||||
)}
|
||||
{sourceEditorToolbarEndButtons.map(
|
||||
({ import: { default: Component }, path }) => (
|
||||
<Component key={path} />
|
||||
|
||||
@@ -11,6 +11,27 @@ $rp-type-blue: #6b7797;
|
||||
--review-panel-width: 230px;
|
||||
--review-panel-width-mini: 24px;
|
||||
--review-panel-color-scheme: dark;
|
||||
--review-mode-switcher-reviewing-bg: var(--yellow-10);
|
||||
--review-mode-switcher-reviewing-hover-bg: var(--yellow-20);
|
||||
--review-mode-switcher-reviewing-color: var(--yellow-60);
|
||||
|
||||
@include theme('default') {
|
||||
.ide-redesign-main {
|
||||
--review-panel-bg-color: var(--bg-dark-secondary);
|
||||
--review-panel-color: var(--content-primary-dark);
|
||||
--review-panel-color-secondary: var(--content-secondary-dark);
|
||||
--review-panel-header-bg-color: var(--bg-dark-primary);
|
||||
--review-panel-footer-bg-color: var(--bg-dark-primary);
|
||||
--review-panel-entry-bg-color: var(--bg-dark-primary);
|
||||
--review-panel-empty-state-bg-color: var(--bg-dark-primary);
|
||||
--review-panel-button-hover-bg-color: var(--bg-dark-tertiary);
|
||||
--review-panel-border-color: var(--border-divider-dark);
|
||||
--review-panel-color-scheme: dark;
|
||||
--review-mode-switcher-reviewing-bg: var(--yellow-70);
|
||||
--review-mode-switcher-reviewing-hover-bg: var(--yellow-60);
|
||||
--review-mode-switcher-reviewing-color: var(--yellow-10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include theme('light') {
|
||||
@@ -752,3 +773,53 @@ del.review-panel-content-highlight {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ol-cm-toolbar {
|
||||
.review-mode-switcher {
|
||||
// In the toolbar the component is in normal flex flow — no absolute positioning.
|
||||
position: static;
|
||||
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
.review-mode-switcher-toggle-button.editing {
|
||||
background-color: var(--review-panel-button-hover-bg-color);
|
||||
}
|
||||
|
||||
.review-mode-switcher-toggle-button.reviewing {
|
||||
background-color: var(--review-mode-switcher-reviewing-hover-bg);
|
||||
}
|
||||
|
||||
.review-mode-switcher-toggle-button.viewing {
|
||||
background-color: var(--blue-20);
|
||||
}
|
||||
|
||||
// In the toolbar the label text does not expand on hover (would shift other buttons)
|
||||
.review-mode-switcher-toggle-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.review-mode-switcher-toggle-button {
|
||||
border-radius: var(--border-radius-base);
|
||||
padding: var(--spacing-01) var(--spacing-02);
|
||||
gap: var(--spacing-01);
|
||||
height: auto;
|
||||
cursor: pointer;
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--content-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
&.editing {
|
||||
background-color: var(--toolbar-alt-bg-color);
|
||||
color: var(--toolbar-btn-color);
|
||||
}
|
||||
|
||||
&.reviewing {
|
||||
background-color: var(--review-mode-switcher-reviewing-bg);
|
||||
color: var(--review-mode-switcher-reviewing-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +295,12 @@
|
||||
z-index: 10; // Prevent track changes showing over toolbar
|
||||
}
|
||||
|
||||
// Isolate secondary toolbar rows so they paint below the main toolbar (z-index: 10)
|
||||
// and its dropdowns, which would otherwise be obscured due to DOM order.
|
||||
.ol-cm-toolbar-wrapper > .writefull {
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
Toggle Switch
|
||||
***************************************/
|
||||
|
||||
Reference in New Issue
Block a user