Merge pull request #31924 from overleaf/ds-removing-useIsNewEditorEnabled-4

[Part 4] Removing the usage of `useIsNewEditorEnabled` for editor tear down

GitOrigin-RevId: 4c1194bb011630f83ecf7334f9ad0deb6ab52580
This commit is contained in:
Davinder Singh
2026-03-05 09:49:01 +00:00
committed by Copybot
parent 05acd6b769
commit d023f721b7
10 changed files with 31 additions and 324 deletions
@@ -1147,7 +1147,6 @@
"n_more_updates_below_plural": "",
"name": "",
"name_usage_explanation": "",
"navigate_log_source": "",
"navigation": "",
"need_anything_contact_us_at": "",
"need_contact_group_admin_to_make_changes": "",
@@ -1,18 +1,13 @@
import { memo } from 'react'
import PreviewLogEntryHeader from '../../preview/components/preview-log-entry-header'
import PdfLogEntryContent from './pdf-log-entry-content'
import HumanReadableLogsHints from '../../../ide/human-readable-logs/HumanReadableLogsHints'
import getMeta from '@/utils/meta'
import { ErrorLevel, LogEntry, SourceLocation } from '../util/types'
import NewLogEntry from '@/features/pdf-preview/components/log-entry'
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
import useHandleLogEntryClick from '../hooks/use-handle-log-entry-click'
function PdfLogEntry({
autoExpand,
ruleId,
headerTitle,
headerIcon,
rawContent,
logType,
formattedContent,
@@ -31,7 +26,6 @@ function PdfLogEntry({
level: ErrorLevel
autoExpand?: boolean
ruleId?: string
headerIcon?: React.ReactElement
rawContent?: string
logType?: string
formattedContent?: React.ReactNode
@@ -45,8 +39,6 @@ function PdfLogEntry({
logEntry?: LogEntry
id?: string
}) {
const showAiErrorAssistant = getMeta('ol-showAiFeatures')
if (ruleId && HumanReadableLogsHints[ruleId]) {
const hint = HumanReadableLogsHints[ruleId]
formattedContent = hint.formattedContent(contentDetails)
@@ -60,58 +52,25 @@ function PdfLogEntry({
onSourceLocationClick,
})
const newEditor = useIsNewEditorEnabled()
if (newEditor) {
return (
<NewLogEntry
autoExpand={autoExpand}
index={index}
id={id}
logEntry={logEntry}
ruleId={ruleId}
headerTitle={headerTitle}
formattedContent={formattedContent}
rawContent={rawContent}
logType={logType}
level={level}
contentDetails={contentDetails}
entryAriaLabel={entryAriaLabel}
sourceLocation={sourceLocation}
onSourceLocationClick={handleLogEntryLinkClick}
showSourceLocationLink={showSourceLocationLink}
extraInfoURL={extraInfoURL}
/>
)
}
return (
<div
className="log-entry"
aria-label={entryAriaLabel}
data-ruleid={ruleId}
data-log-entry-id={id}
>
<PreviewLogEntryHeader
level={level}
sourceLocation={sourceLocation}
headerTitle={headerTitle}
headerIcon={headerIcon}
logType={logType}
showSourceLocationLink={showSourceLocationLink}
onSourceLocationClick={handleLogEntryLinkClick}
/>
{(rawContent || formattedContent || showAiErrorAssistant) && (
<PdfLogEntryContent
rawContent={rawContent}
formattedContent={formattedContent}
extraInfoURL={extraInfoURL}
index={index}
logEntry={logEntry}
/>
)}
</div>
<NewLogEntry
autoExpand={autoExpand}
index={index}
id={id}
logEntry={logEntry}
ruleId={ruleId}
headerTitle={headerTitle}
formattedContent={formattedContent}
rawContent={rawContent}
logType={logType}
level={level}
contentDetails={contentDetails}
entryAriaLabel={entryAriaLabel}
sourceLocation={sourceLocation}
onSourceLocationClick={handleLogEntryLinkClick}
showSourceLocationLink={showSourceLocationLink}
extraInfoURL={extraInfoURL}
/>
)
}
@@ -256,12 +256,10 @@ export default memo(PdfPreviewError)
function ErrorLogEntry({
autoExpand = true,
title,
headerIcon,
children,
}: {
autoExpand?: boolean
title: string
headerIcon?: React.ReactElement
children: React.ReactNode
}) {
const { t } = useTranslation()
@@ -270,7 +268,6 @@ function ErrorLogEntry({
<PdfLogEntry
autoExpand={autoExpand}
headerTitle={title}
headerIcon={headerIcon}
formattedContent={children}
entryAriaLabel={t('compile_error_entry_description')}
level="error"
@@ -1,123 +0,0 @@
import classNames from 'classnames'
import { useState, useRef, MouseEventHandler } from 'react'
import { useTranslation } from 'react-i18next'
import useResizeObserver from '../hooks/use-resize-observer'
import OLTooltip from '@/shared/components/ol/ol-tooltip'
import OLButton from '@/shared/components/ol/ol-button'
import MaterialIcon from '@/shared/components/material-icon'
import { ErrorLevel, SourceLocation } from '@/features/pdf-preview/util/types'
function PreviewLogEntryHeader({
sourceLocation,
level,
headerTitle,
headerIcon,
logType,
showSourceLocationLink = true,
onSourceLocationClick,
}: {
headerTitle: string | React.ReactNode
level: ErrorLevel
headerIcon?: React.ReactElement
logType?: string
sourceLocation?: SourceLocation
showSourceLocationLink?: boolean
onSourceLocationClick?: MouseEventHandler<HTMLButtonElement>
}) {
const { t } = useTranslation()
const logLocationSpanRef = useRef<HTMLSpanElement>(null)
const [locationSpanOverflown, setLocationSpanOverflown] = useState(false)
useResizeObserver(
logLocationSpanRef,
locationSpanOverflown,
checkLocationSpanOverflow
)
const file = sourceLocation ? sourceLocation.file : null
const line = sourceLocation ? sourceLocation.line : null
const logEntryHeaderClasses = classNames('log-entry-header', {
'log-entry-header-error': level === 'error',
'log-entry-header-warning': level === 'warning',
'log-entry-header-info': level === 'info',
'log-entry-header-typesetting': level === 'typesetting',
'log-entry-header-raw': level === 'raw',
'log-entry-header-success': level === 'success',
})
const logEntryLocationBtnClasses = classNames('log-entry-header-link', {
'log-entry-header-link-error': level === 'error',
'log-entry-header-link-warning': level === 'warning',
'log-entry-header-link-typesetting': level === 'typesetting',
'log-entry-header-link-raw': level === 'raw',
'log-entry-header-link-info': level === 'info',
'log-entry-header-link-success': level === 'success',
})
const headerLogLocationTitle = t('navigate_log_source', {
location: file + (line ? `, ${line}` : ''),
})
function checkLocationSpanOverflow(observedElement: ResizeObserverEntry) {
const spanEl = observedElement.target
const isOverflowing = spanEl.scrollWidth > spanEl.clientWidth
setLocationSpanOverflown(isOverflowing)
}
const locationLinkText =
showSourceLocationLink && file ? `${file}${line ? `, ${line}` : ''}` : null
// Because we want an ellipsis on the left-hand side (e.g. "...longfilename.tex"), the
// `log-entry-header-link-location` class has text laid out from right-to-left using the CSS
// rule `direction: rtl;`.
// This works most of the times, except when the first character of the filename is considered
// a punctuation mark, like `/` (e.g. `/foo/bar/baz.sty`). In this case, because of
// right-to-left writing rules, the punctuation mark is moved to the right-side of the string,
// resulting in `...bar/baz.sty/` instead of `...bar/baz.sty`.
// To avoid this edge-case, we wrap the `logLocationLinkText` in two directional formatting
// characters:
// * \u202A LEFT-TO-RIGHT EMBEDDING Treat the following text as embedded left-to-right.
// * \u202C POP DIRECTIONAL FORMATTING End the scope of the last LRE, RLE, RLO, or LRO.
// This essentially tells the browser that, althought the text is laid out from right-to-left,
// the wrapped portion of text should follow left-to-right writing rules.
const locationLink = locationLinkText ? (
<OLButton
variant="ghost"
className={logEntryLocationBtnClasses}
aria-label={headerLogLocationTitle}
onClick={onSourceLocationClick}
>
<MaterialIcon type="link" />
<span
ref={logLocationSpanRef}
className="log-entry-header-link-location"
translate="no"
>
{`\u202A${locationLinkText}\u202C`}
</span>
</OLButton>
) : null
const headerTitleText = logType ? `${logType} ${headerTitle}` : headerTitle
return (
<div className={logEntryHeaderClasses}>
{headerIcon ? (
<div className="log-entry-header-icon-container">{headerIcon}</div>
) : null}
<h3 className="log-entry-header-title">{headerTitleText}</h3>
{locationSpanOverflown && locationLinkText && locationLink ? (
<OLTooltip
id={locationLinkText}
description={locationLinkText}
overlayProps={{ placement: 'left' }}
tooltipProps={{ className: 'log-location-tooltip', translate: 'no' }}
>
{locationLink}
</OLTooltip>
) : (
locationLink
)}
</div>
)
}
export default PreviewLogEntryHeader
@@ -33,7 +33,6 @@ import ReviewPanelMoreCommentsButton from './review-panel-more-comments-button'
import useMoreCommments from '../hooks/use-more-comments'
import { Decoration } from '@codemirror/view'
import { debounce } from 'lodash'
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
type AggregatedRanges = {
changes: Change<EditOperation>[]
@@ -47,7 +46,6 @@ const ReviewPanelCurrentFile: FC = () => {
const threads = useThreadsContext()
const state = useCodeMirrorStateContext()
const [hoveredEntry, setHoveredEntry] = useState<string | null>(null)
const newEditor = useIsNewEditorEnabled()
const hoverTimeout = useRef<number>(0)
const handleEntryEnter = useCallback((id: string) => {
@@ -248,8 +246,7 @@ const ReviewPanelCurrentFile: FC = () => {
const positioningRes = positionItems(
containerRef.current,
previousFocusedItem.current.get(docId),
docId,
newEditor
docId
)
onEntriesPositioned()
@@ -261,7 +258,7 @@ const ReviewPanelCurrentFile: FC = () => {
)
}
}
}, [ranges?.docId, onEntriesPositioned, newEditor])
}, [ranges?.docId, onEntriesPositioned])
useEffect(() => {
const timer = window.setTimeout(() => {
@@ -1,16 +1,13 @@
import { FC, memo, useMemo } from 'react'
import ReviewPanelTabs from './review-panel-tabs'
import ReviewPanelHeader from './review-panel-header'
import ReviewPanelCurrentFile from './review-panel-current-file'
import { ReviewPanelOverview } from './review-panel-overview'
import classnames from 'classnames'
import { useReviewPanelStyles } from '@/features/review-panel/hooks/use-review-panel-styles'
import { useReviewPanelViewContext } from '../context/review-panel-view-context'
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
const ReviewPanel: FC<{ mini?: boolean }> = ({ mini = false }) => {
const choosenSubView = useReviewPanelViewContext()
const newEditor = useIsNewEditorEnabled()
const activeSubView = useMemo(
() => (mini ? 'cur_file' : choosenSubView),
@@ -27,8 +24,6 @@ const ReviewPanel: FC<{ mini?: boolean }> = ({ mini = false }) => {
return (
<div className={className} style={style} data-testid="review-panel">
<div id="review-panel-inner" className="review-panel-inner">
{!newEditor && !mini && <ReviewPanelHeader />}
{activeSubView === 'cur_file' && <ReviewPanelCurrentFile />}
{activeSubView === 'overview' && <ReviewPanelOverview />}
@@ -1,9 +1,7 @@
import { useLayoutContext } from '@/shared/context/layout-context'
import { useRangesContext } from '../context/ranges-context'
import { useThreadsContext } from '@/features/review-panel/context/threads-context'
import { hasActiveRange } from '@/features/review-panel/utils/has-active-range'
import { useRailContext } from '@/features/ide-react/context/rail-context'
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
import { useCallback } from 'react'
export default function useReviewPanelLayout(): {
@@ -21,30 +19,16 @@ export default function useReviewPanelLayout(): {
openTab: openRailTab,
setIsOpen: setRailIsOpen,
} = useRailContext()
const { reviewPanelOpen: reviewPanelOpenOldEditor, setReviewPanelOpen } =
useLayoutContext()
const newEditor = useIsNewEditorEnabled()
const reviewPanelOpen = newEditor
? selectedRailTab === 'review-panel' && railIsOpen
: reviewPanelOpenOldEditor
const reviewPanelOpen = selectedRailTab === 'review-panel' && railIsOpen
const openReviewPanel = useCallback(() => {
if (newEditor) {
openRailTab('review-panel')
} else {
setReviewPanelOpen(true)
}
}, [newEditor, setReviewPanelOpen, openRailTab])
openRailTab('review-panel')
}, [openRailTab])
const closeReviewPanel = useCallback(() => {
if (newEditor) {
setRailIsOpen(false)
} else {
setReviewPanelOpen(false)
}
}, [newEditor, setReviewPanelOpen, setRailIsOpen])
setRailIsOpen(false)
}, [setRailIsOpen])
const hasCommentOrChange = hasActiveRange(ranges, threads)
const showPanel = reviewPanelOpen || !!hasCommentOrChange
@@ -1,15 +1,13 @@
import { debounce } from 'lodash'
export const OFFSET_FOR_ENTRIES_ABOVE = 70
const COLLAPSED_HEADER_HEIGHT = 42
const GAP_BETWEEN_ENTRIES = 4
export const positionItems = debounce(
(
element: HTMLDivElement,
previousFocusedItemIndex: number | undefined,
docId: string,
newEditor: boolean
docId: string
) => {
const items = Array.from(
element.querySelectorAll<HTMLDivElement>('.review-panel-entry')
@@ -42,11 +40,7 @@ export const positionItems = debounce(
return
}
const activeItemTop = getTopPosition(
activeItem,
activeItemIndex === 0,
newEditor
)
const activeItemTop = getTopPosition(activeItem, activeItemIndex === 0)
const positions: [HTMLElement, number][] = []
positions.push([activeItem, activeItemTop])
@@ -56,7 +50,7 @@ export const positionItems = debounce(
for (let i = activeItemIndex - 1; i >= 0; i--) {
const item = items[i]
const height = item.offsetHeight
let top = getTopPosition(item, i === 0, newEditor)
let top = getTopPosition(item, i === 0)
const bottom = top + height
if (bottom > topLimit) {
top = topLimit - height - GAP_BETWEEN_ENTRIES
@@ -70,7 +64,7 @@ export const positionItems = debounce(
for (let i = activeItemIndex + 1; i < items.length; i++) {
const item = items[i]
const height = item.offsetHeight
let top = getTopPosition(item, false, newEditor)
let top = getTopPosition(item, false)
if (top < bottomLimit) {
top = bottomLimit + GAP_BETWEEN_ENTRIES
}
@@ -92,16 +86,8 @@ export const positionItems = debounce(
{ leading: false, trailing: true, maxWait: 1000 }
)
function getTopPosition(
item: HTMLDivElement,
isFirstEntry: boolean,
newEditor: boolean
) {
function getTopPosition(item: HTMLDivElement, isFirstEntry: boolean) {
const offset = isFirstEntry ? 0 : OFFSET_FOR_ENTRIES_ABOVE
if (newEditor) {
return Math.max(offset, Number(item.dataset.top))
}
return Math.max(COLLAPSED_HEADER_HEIGHT + offset, Number(item.dataset.top))
return Math.max(offset, Number(item.dataset.top))
}
@@ -253,77 +253,6 @@
}
}
.log-entry-header-error {
background-color: var(--content-danger);
}
.log-entry-header-link-error {
@include ol-button-variant(
$color: var(--content-primary-dark),
$background: var(--bg-danger-02),
$hover-background: var(--red-70)
);
}
.log-entry-header-warning {
background-color: var(--content-warning-dark);
}
.log-entry-header-link-warning {
@include ol-button-variant(
$color: var(--content-primary-dark),
$background: var(--bg-warning-01),
$hover-background: var(--bg-warning-02)
);
}
.log-entry-header-typesetting {
background-color: var(--blue-50);
}
.log-entry-header-link-typesetting {
@include ol-button-variant(
$color: var(--content-primary-dark),
$background: var(--blue-60),
$hover-background: var(--blue-70)
);
}
.log-entry-header-raw,
.log-entry-header-info {
background-color: var(--bg-dark-tertiary);
}
.log-entry-header-link-raw,
.log-entry-header-link-info {
@include ol-button-variant(
$color: var(--content-primary-dark),
$background: var(--bg-dark-secondary),
$hover-background: var(--bg-dark-primary)
);
}
.log-entry-header-success {
background-color: var(--green-50);
}
.log-entry-header-link-success {
@include ol-button-variant(
$color: var(--content-primary-dark),
$background: var(--green-60),
$hover-background: var(--green-70)
);
}
.log-entry-header-title {
@include body-base;
flex-grow: 1;
font-weight: bold;
margin: 0;
color: var(--content-primary-dark);
}
.log-entry-header-link {
color: var(--content-primary-dark);
border-width: 0;
@@ -470,19 +399,4 @@
display: flex;
justify-content: flex-end;
}
.log-entry-header-error {
background-color: var(--red-10);
.log-entry-header-title {
@include heading-sm;
color: var(--red-50);
}
}
.log-entry-header-raw {
background-color: var(--neutral-60);
padding: var(--spacing-04) var(--spacing-06);
}
}
-1
View File
@@ -1477,7 +1477,6 @@
"name": "Name",
"name_usage_explanation": "Your name will be displayed to your collaborators (so they know who theyre working with).",
"native": "Native",
"navigate_log_source": "Navigate to log position in source code: __location__",
"navigation": "Navigation",
"nearly_activated": "Youre one step away from activating your __appName__ account!",
"need_20_plus_users_discount": "20+ users? <0>Contact sales</0> to get the best discounts.",