Просмотр исходного кода

Dont show "add comment" tooltip when text is selected via search (#23341)

* Dont show "add comment" tooltip when text is selected via search

* remove the tooltip if selection changes

* handle empty selection

* use tr.effects.some for mouseUp check

* avoid creating new create function each time

* use useEventListener

GitOrigin-RevId: 18d96fe6fdefcd55f88849cf880f804d4c963f4d
Domagoj Kriskovic 1 год назад
Родитель
Сommit
6ee3ff63e4

+ 27 - 32
services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx

@@ -1,8 +1,6 @@
 import {
   CSSProperties,
-  Dispatch,
   FC,
-  SetStateAction,
   useCallback,
   useEffect,
   useMemo,
@@ -35,6 +33,7 @@ import { useModalsContext } from '@/features/ide-react/context/modals-context'
 import { numberOfChangesInSelection } from '../utils/changes-in-selection'
 import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
 import classNames from 'classnames'
+import useEventListener from '@/shared/hooks/use-event-listener'
 
 const TRACK_CHANGES_ON_WIDGET_HEIGHT = 25
 const CM_LINE_RIGHT_PADDING = 2
@@ -45,6 +44,8 @@ const ReviewTooltipMenu: FC = () => {
   const view = useCodeMirrorViewContext()
   const isViewer = useViewerPermissions()
   const [show, setShow] = useState(true)
+  const { setView } = useReviewPanelViewActionsContext()
+  const { setReviewPanelOpen } = useLayoutContext()
 
   const tooltipState = state.field(reviewTooltipStateField, false)?.tooltip
   const previousTooltipState = usePreviousValue(tooltipState)
@@ -55,6 +56,24 @@ const ReviewTooltipMenu: FC = () => {
     }
   }, [tooltipState, previousTooltipState])
 
+  const addComment = useCallback(() => {
+    setReviewPanelOpen(true)
+    setView('cur_file')
+
+    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])
+
+  useEventListener('add-new-review-comment', addComment)
+
   if (isViewer || !show || !tooltipState) {
     return null
   }
@@ -66,19 +85,18 @@ const ReviewTooltipMenu: FC = () => {
   }
 
   return ReactDOM.createPortal(
-    <ReviewTooltipMenuContent setShow={setShow} />,
+    <ReviewTooltipMenuContent onAddComment={addComment} />,
     tooltipView.dom
   )
 }
 
-const ReviewTooltipMenuContent: FC<{
-  setShow: Dispatch<SetStateAction<boolean>>
-}> = ({ setShow }) => {
+const ReviewTooltipMenuContent: FC<{ onAddComment: () => void }> = ({
+  onAddComment,
+}) => {
   const { t } = useTranslation()
   const view = useCodeMirrorViewContext()
   const state = useCodeMirrorStateContext()
-  const { setReviewPanelOpen, reviewPanelOpen } = useLayoutContext()
-  const { setView } = useReviewPanelViewActionsContext()
+  const { reviewPanelOpen } = useLayoutContext()
   const ranges = useRangesContext()
   const { acceptChanges, rejectChanges } = useRangesActionsContext()
   const { showGenericConfirmModal } = useModalsContext()
@@ -86,29 +104,6 @@ const ReviewTooltipMenuContent: FC<{
   const [tooltipStyle, setTooltipStyle] = useState<CSSProperties | undefined>()
   const [visible, setVisible] = useState(false)
 
-  const addComment = useCallback(() => {
-    setReviewPanelOpen(true)
-    setView('cur_file')
-
-    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])
-
-  useEffect(() => {
-    window.addEventListener('add-new-review-comment', addComment)
-    return () => {
-      window.removeEventListener('add-new-review-comment', addComment)
-    }
-  }, [addComment])
-
   const changeIdsInSelection = useMemo(() => {
     return (ranges?.changes ?? [])
       .filter(({ op }) => {
@@ -219,7 +214,7 @@ const ReviewTooltipMenuContent: FC<{
     >
       <button
         className="review-tooltip-menu-button review-tooltip-add-comment-button"
-        onClick={addComment}
+        onClick={onAddComment}
       >
         <MaterialIcon type="chat" />
         {t('add_comment')}

+ 30 - 9
services/web/frontend/js/features/source-editor/extensions/review-tooltip.ts

@@ -13,6 +13,7 @@ import {
   Range,
   SelectionRange,
   EditorState,
+  Transaction,
 } from '@codemirror/state'
 import { isSplitTestEnabled } from '@/utils/splitTestUtils'
 import { v4 as uuid } from 'uuid'
@@ -119,14 +120,29 @@ export const reviewTooltipStateField = StateField.define<{
       }
     }
 
-    const isMouseDown = tr.state.field(mouseDownStateField)
-    if (!isMouseDown && !tr.state.selection.main.empty) {
-      tooltip = buildTooltip(tr.state)
-    } else if (tooltip && tr.state.selection.main.empty) {
-      tooltip = null
+    if (tr.state.selection.main.empty) {
+      return { tooltip: null, addCommentRanges }
+    }
+
+    if (
+      !tr.effects.some(effect => effect.is(mouseUpEffect)) &&
+      tr.annotation(Transaction.userEvent) !== 'select' &&
+      tr.annotation(Transaction.userEvent) !== 'select.pointer'
+    ) {
+      if (tr.selection) {
+        // selection was changed, remove the tooltip
+        return { tooltip: null, addCommentRanges }
+      }
+      // for any other update, we keep the tooltip because it could be created in previous transaction
+      // and we are still waiting for "mouse up" event to show it
+      return { tooltip, addCommentRanges }
     }
 
-    return { tooltip, addCommentRanges }
+    const isMouseDown = tr.state.field(mouseDownStateField)
+    // if "isMouseDown" is true, tooltip will be created but still hidden
+    // the reason why we cant just create the tooltip on mouse up is because transaction.userEvent is empty at that point
+
+    return { tooltip: buildTooltip(tr.state, isMouseDown), addCommentRanges }
   },
 
   provide: field => [
@@ -135,7 +151,7 @@ export const reviewTooltipStateField = StateField.define<{
   ],
 })
 
-function buildTooltip(state: EditorState): Tooltip | null {
+function buildTooltip(state: EditorState, hidden: boolean): Tooltip | null {
   const lineAtFrom = state.doc.lineAt(state.selection.main.from)
   const lineAtTo = state.doc.lineAt(state.selection.main.to)
   const multiLineSelection = lineAtFrom.number !== lineAtTo.number
@@ -151,19 +167,24 @@ function buildTooltip(state: EditorState): Tooltip | null {
   return {
     pos,
     above: state.selection.main.head !== state.selection.main.to,
-    create: createReviewTooltipView,
+    create: hidden
+      ? createHiddenReviewTooltipView
+      : createVisibleReviewTooltipView,
   }
 }
 
-const createReviewTooltipView = (): TooltipView => {
+const createReviewTooltipView = (hidden: boolean): TooltipView => {
   const dom = document.createElement('div')
   dom.className = 'review-tooltip-menu-container'
+  dom.style.display = hidden ? 'none' : 'block'
   return {
     dom,
     overlap: true,
     offset: { x: 0, y: 8 },
   }
 }
+const createHiddenReviewTooltipView = () => createReviewTooltipView(true)
+const createVisibleReviewTooltipView = () => createReviewTooltipView(false)
 
 /**
  * Styles for the tooltip