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:
@@ -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
|
||||
+2
-5
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1477,7 +1477,6 @@
|
||||
"name": "Name",
|
||||
"name_usage_explanation": "Your name will be displayed to your collaborators (so they know who they’re working with).",
|
||||
"native": "Native",
|
||||
"navigate_log_source": "Navigate to log position in source code: __location__",
|
||||
"navigation": "Navigation",
|
||||
"nearly_activated": "You’re one step away from activating your __appName__ account!",
|
||||
"need_20_plus_users_discount": "20+ users? <0>Contact sales</0> to get the best discounts.",
|
||||
|
||||
Reference in New Issue
Block a user