Merge pull request #20583 from overleaf/dk-review-gotoposition

Goto position when clicking on review entry in Overview tab

GitOrigin-RevId: 17c9cefed339537afa994778ffbc01cfb294bf46
This commit is contained in:
David 2024-09-26 15:13:54 +01:00 committed by Copybot
parent e253b48bc0
commit 2801b3baad
6 changed files with 52 additions and 20 deletions

View file

@ -15,11 +15,12 @@ import { ThreadId } from '../../../../../types/review-panel/review-panel'
import { Decoration } from '@codemirror/view'
export const ReviewPanelAddComment: FC<{
docId: string
from: number
to: number
value: Decoration
top: number | undefined
}> = ({ from, to, value, top }) => {
}> = ({ from, to, value, top, docId }) => {
const { t } = useTranslation()
const view = useCodeMirrorViewContext()
const state = useCodeMirrorStateContext()
@ -113,6 +114,7 @@ export const ReviewPanelAddComment: FC<{
return (
<ReviewPanelEntry
docId={docId}
top={top}
position={from}
op={{

View file

@ -21,7 +21,9 @@ export const ReviewPanelChange = memo<{
aggregate?: Change<DeleteOperation>
top?: number
editable?: boolean
}>(({ change, aggregate, top, editable = true }) => {
docId: string
hoverRanges?: boolean
}>(({ change, aggregate, top, docId, hoverRanges, editable = true }) => {
const { t } = useTranslation()
const { acceptChanges, rejectChanges } = useRangesActionsContext()
const permissions = usePermissionsContext()
@ -42,6 +44,8 @@ export const ReviewPanelChange = memo<{
top={top}
op={change.op}
position={change.op.p}
docId={docId}
hoverRanges={hoverRanges}
>
<div className="review-panel-entry-indicator">
<MaterialIcon type="edit" className="review-panel-entry-icon" />

View file

@ -8,8 +8,10 @@ import { ReviewPanelCommentContent } from './review-panel-comment-content'
export const ReviewPanelComment = memo<{
comment: Change<CommentOperation>
docId: string
top?: number
}>(({ comment, top }) => {
hoverRanges?: boolean
}>(({ comment, top, docId, hoverRanges }) => {
const threads = useThreadsContext()
const thread = threads?.[comment.op.t]
@ -22,9 +24,11 @@ export const ReviewPanelComment = memo<{
className={classnames('review-panel-entry-comment', {
'review-panel-entry-loaded': !!threads?.[comment.op.t],
})}
docId={docId}
top={top}
op={comment.op}
position={comment.op.p}
hoverRanges={hoverRanges}
>
<div className="review-panel-entry-indicator">
<MaterialIcon type="comment" className="review-panel-entry-icon" />

View file

@ -251,6 +251,7 @@ const ReviewPanelCurrentFile: FC = () => {
const { id, from, to, value, top } = entry
return (
<ReviewPanelAddComment
docId={ranges!.docId}
key={id}
from={from}
to={to}
@ -264,6 +265,7 @@ const ReviewPanelCurrentFile: FC = () => {
change =>
positions.has(change.id) && (
<ReviewPanelChange
docId={ranges!.docId}
key={change.id}
change={change}
top={positions.get(change.id)}
@ -276,6 +278,7 @@ const ReviewPanelCurrentFile: FC = () => {
comment =>
positions.has(comment.id) && (
<ReviewPanelComment
docId={ranges!.docId}
key={comment.id}
comment={comment}
top={positions.get(comment.id)}

View file

@ -5,44 +5,56 @@ import {
useCodeMirrorViewContext,
} from '@/features/source-editor/components/codemirror-editor'
import { isSelectionWithinOp } from '../utils/is-selection-within-op'
import { EditorSelection } from '@codemirror/state'
import { EditorView } from '@codemirror/view'
import classNames from 'classnames'
import { highlightRanges } from '@/features/source-editor/extensions/ranges'
import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
export const ReviewPanelEntry: FC<{
position: number
op: AnyOperation
docId: string
top?: number
className?: string
selectLineOnFocus?: boolean
}> = ({ children, position, top, op, className, selectLineOnFocus = true }) => {
hoverRanges?: boolean
}> = ({
children,
position,
top,
op,
className,
selectLineOnFocus = true,
docId,
hoverRanges = true,
}) => {
const state = useCodeMirrorStateContext()
const view = useCodeMirrorViewContext()
const { openDocId } = useEditorManagerContext()
const [focused, setFocused] = useState(false)
const highlighted = isSelectionWithinOp(op, state.selection.main)
const focusHandler = useCallback(() => {
setTimeout(() => {
// without setTimeout, error "EditorView.update are not allowed while an update is in progress" can occur
// this can be avoided by using onClick rather than onFocus but it will then not pick up <Tab> or <Shift+Tab> events for focusing entries
if (selectLineOnFocus) {
view.dispatch({
selection: EditorSelection.cursor(position),
effects: EditorView.scrollIntoView(position, { y: 'center' }),
})
openDocId(docId, { gotoOffset: position, keepCurrentView: true })
}
}, 0)
setFocused(true)
}, [view, position, selectLineOnFocus])
}, [selectLineOnFocus, docId, openDocId, position])
return (
<div
onFocus={focusHandler}
onBlur={() => setFocused(false)}
onMouseEnter={() => view.dispatch(highlightRanges(op))}
onMouseLeave={() => view.dispatch(highlightRanges())}
onMouseEnter={() => {
if (hoverRanges) {
view.dispatch(highlightRanges(op))
}
}}
onMouseLeave={() => {
if (hoverRanges) {
view.dispatch(highlightRanges())
}
}}
role="button"
tabIndex={position + 1}
className={classNames(

View file

@ -82,11 +82,18 @@ export const ReviewPanelOverviewFile: FC<{
change={change}
aggregate={aggregates.get(change.id)}
editable={false}
docId={doc.doc.id}
hoverRanges={false}
/>
))}
{unresolvedComments.map(comment => (
<ReviewPanelComment key={comment.id} comment={comment} />
<ReviewPanelComment
key={comment.id}
comment={comment}
docId={doc.doc.id}
hoverRanges={false}
/>
))}
</div>
)}