From db23262611e41baae4ac12542f2cc5ae09daf670 Mon Sep 17 00:00:00 2001 From: Domagoj Kriskovic Date: Fri, 25 Oct 2024 15:04:55 +0200 Subject: [PATCH] Scroll selection anchor into view when adding new comment (#21328) * Scroll selection anchor into view when adding new comment * check if cursor is near viewport edge GitOrigin-RevId: 57d4195f7ce1513a56249365b45b3959b4ea813f --- .../components/review-tooltip-menu.tsx | 15 ++++++++---- .../utils/is-cursor-near-edge.ts | 23 +++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 services/web/frontend/js/features/source-editor/utils/is-cursor-near-edge.ts diff --git a/services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx b/services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx index 7c2bde4997..50c154dcc9 100644 --- a/services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx +++ b/services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx @@ -18,7 +18,7 @@ import { buildAddNewCommentRangeEffect, reviewTooltipStateField, } from '@/features/source-editor/extensions/review-tooltip' -import { getTooltip } from '@codemirror/view' +import { EditorView, getTooltip } from '@codemirror/view' import useViewerPermissions from '@/shared/hooks/use-viewer-permissions' import usePreviousValue from '@/shared/hooks/use-previous-value' import { useLayoutContext } from '@/shared/context/layout-context' @@ -28,6 +28,7 @@ import { useRangesContext, } from '../context/ranges-context' import { isInsertOperation } from '@/utils/operations' +import { isCursorNearViewportEdge } from '@/features/source-editor/utils/is-cursor-near-edge' const ReviewTooltipMenu: FC = () => { const state = useCodeMirrorStateContext() @@ -75,9 +76,15 @@ const ReviewTooltipMenuContent: FC<{ setReviewPanelOpen(true) setView('cur_file') - view.dispatch({ - effects: buildAddNewCommentRangeEffect(state.selection.main), - }) + const commentPos = state.selection.main.anchor + const effects = isCursorNearViewportEdge(view, commentPos) + ? [ + buildAddNewCommentRangeEffect(state.selection.main), + EditorView.scrollIntoView(commentPos, { y: 'center' }), + ] + : [buildAddNewCommentRangeEffect(state.selection.main)] + + view.dispatch({ effects }) setShow(false) }, [setReviewPanelOpen, setView, setShow, view, state.selection.main]) diff --git a/services/web/frontend/js/features/source-editor/utils/is-cursor-near-edge.ts b/services/web/frontend/js/features/source-editor/utils/is-cursor-near-edge.ts new file mode 100644 index 0000000000..6878a2e798 --- /dev/null +++ b/services/web/frontend/js/features/source-editor/utils/is-cursor-near-edge.ts @@ -0,0 +1,23 @@ +import { EditorView } from '@codemirror/view' + +const TOP_EDGE_THRESHOLD = 100 +const BOTTOM_EDGE_THRESHOLD = 200 + +export function isCursorNearViewportEdge(view: EditorView, pos: number) { + const cursorCoords = view.coordsAtPos(pos) + + if (!cursorCoords) { + return false + } + + const scrollInfo = view.scrollDOM.getBoundingClientRect() + + // check if the cursor is near the top of the viewport + if (Math.abs(cursorCoords.bottom - scrollInfo.top) <= TOP_EDGE_THRESHOLD) { + return true + } + // check if the cursor is near the bottom of the viewport + const viewportHeight = view.scrollDOM.clientHeight + const viewportBottom = scrollInfo.top + viewportHeight + return Math.abs(cursorCoords.bottom - viewportBottom) <= BOTTOM_EDGE_THRESHOLD +}