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

Merge pull request #16065 from overleaf/ii-ide-page-prototype-review-panel-add-comment

[web] React ide page add comment

GitOrigin-RevId: 4c2442ccc77760d4a27268551c9dd2d73fcdba84
ilkin-overleaf 2 лет назад
Родитель
Сommit
8035241cc0

+ 70 - 2
services/web/frontend/js/features/ide-react/context/review-panel/hooks/use-review-panel-state.ts

@@ -6,6 +6,7 @@ import useScopeValue from '../../../../../shared/hooks/use-scope-value'
 import useSocketListener from '@/features/ide-react/hooks/use-socket-listener'
 import useAsync from '@/shared/hooks/use-async'
 import useAbortController from '@/shared/hooks/use-abort-controller'
+import useScopeEventEmitter from '@/shared/hooks/use-scope-event-emitter'
 import { sendMB } from '../../../../../infrastructure/event-tracking'
 import {
   dispatchReviewPanelLayout as handleLayoutChange,
@@ -130,6 +131,7 @@ function useReviewPanelState(): ReviewPanelStateReactIde {
   // TODO permissions to be removed from the review panel context. It currently acts just as a proxy.
   const { permissions } = usePermissionsContext()
   const { showGenericMessageModal } = useModalsContext()
+  const addCommentEmitter = useScopeEventEmitter('comment:start_adding')
 
   // TODO `currentDocument` and `currentDocumentId` should be get from `useEditorManagerContext()` but that makes tests fail
   const [currentDocument] = useScopeValue<Document>('editor.sharejs_doc')
@@ -834,8 +836,6 @@ function useReviewPanelState(): ReviewPanelStateReactIde {
     applyTrackChangesStateToClient
   )
 
-  const [submitNewComment] =
-    useScopeValue<ReviewPanel.UpdaterFn<'submitNewComment'>>('submitNewComment')
   const [gotoEntry] =
     useScopeValue<ReviewPanel.UpdaterFn<'gotoEntry'>>('gotoEntry')
 
@@ -1097,6 +1097,53 @@ function useReviewPanelState(): ReviewPanelStateReactIde {
     [getThread, projectId, showGenericMessageModal, t, view]
   )
 
+  // TODO `submitNewComment` is partially localized in the `add-comment-entry` component.
+  const submitNewComment = useCallback(
+    (content: string) => {
+      if (!content) {
+        return
+      }
+
+      const entries = getDocEntries(currentDocumentId)
+      const addCommentEntry = entries['add-comment'] as
+        | ReviewPanelAddCommentEntry
+        | undefined
+
+      if (!addCommentEntry) {
+        return
+      }
+
+      const { offset, length } = addCommentEntry
+      const threadId = RangesTracker.generateId()
+      setCommentThreads(prevState => ({
+        ...prevState,
+        [threadId]: { ...getThread(threadId), submitting: true },
+      }))
+
+      const url = `/project/${projectId}/thread/${threadId}/messages`
+      postJSON(url, { body: { content } })
+        .then(() => {
+          dispatchReviewPanelEvent('comment:add', { threadId, offset, length })
+          handleLayoutChange({ async: true })
+          sendMB('rp-new-comment', { size: content.length })
+        })
+        .catch(() => {
+          showGenericMessageModal(
+            t('error_submitting_comment'),
+            t('comment_submit_error')
+          )
+        })
+    },
+    [
+      currentDocumentId,
+      getDocEntries,
+      getThread,
+      projectId,
+      showGenericMessageModal,
+      t,
+    ]
+  )
+
   const [entryHover, setEntryHover] = useState(false)
   const [isAddingComment, setIsAddingComment] = useState(false)
   const [navHeight, setNavHeight] = useState(0)
@@ -1250,6 +1297,19 @@ function useReviewPanelState(): ReviewPanelStateReactIde {
       handleLayoutChange()
     }
 
+    const addNewCommentFromKbdShortcut = () => {
+      if (!trackChangesVisible) {
+        return
+      }
+      dispatchReviewPanelEvent('comment:select_line')
+
+      if (!reviewPanelOpen) {
+        toggleReviewPanel()
+      }
+      handleLayoutChange({ async: true })
+      addCommentEmitter()
+    }
+
     const handleEditorEvents = (e: Event) => {
       const event = e as CustomEvent
       const { type, payload } = event.detail
@@ -1266,6 +1326,11 @@ function useReviewPanelState(): ReviewPanelStateReactIde {
           break
         }
 
+        case 'add-new-comment': {
+          addNewCommentFromKbdShortcut()
+          break
+        }
+
         case 'toggle-track-changes': {
           toggleTrackChangesFromKbdShortcut()
           break
@@ -1279,9 +1344,12 @@ function useReviewPanelState(): ReviewPanelStateReactIde {
       window.removeEventListener('editor:event', handleEditorEvents)
     }
   }, [
+    addCommentEmitter,
     currentDocumentId,
     getDocEntries,
     resolvedThreadIds,
+    reviewPanelOpen,
+    toggleReviewPanel,
     toggleTrackChangesForUser,
     trackChanges,
     trackChangesState,

+ 0 - 2
services/web/frontend/js/features/ide-react/scope-adapters/review-panel-context-adapter.ts

@@ -6,8 +6,6 @@ export default function populateReviewPanelScope(store: ReactScopeValueStore) {
   store.set('users', {})
   store.set('reviewPanel.layoutToLeft', false)
   store.set('reviewPanel.rendererData.lineHeight', 0)
-  store.set('submitNewComment', async () => {})
   store.set('gotoEntry', () => {})
-  store.set('saveEdit', () => {})
   store.set('addNewComment', () => {})
 }

+ 10 - 0
services/web/frontend/js/features/source-editor/components/review-panel/editor-widgets/editor-widgets.tsx

@@ -8,6 +8,7 @@ import {
   useReviewPanelUpdaterFnsContext,
   useReviewPanelValueContext,
 } from '../../../context/review-panel/review-panel-context'
+import { useIdeContext } from '@/shared/context/ide-context'
 import { useCodeMirrorViewContext } from '../../codemirror-editor'
 import Modal, { useBulkActionsModal } from '../entries/bulk-actions-entry/modal'
 import getMeta from '../../../../../utils/meta'
@@ -27,6 +28,8 @@ function EditorWidgets() {
   } = useBulkActionsModal()
   const { setIsAddingComment, handleSetSubview } =
     useReviewPanelUpdaterFnsContext()
+  const { isReactIde } = useIdeContext()
+  const { toggleReviewPanel } = useReviewPanelUpdaterFnsContext()
   const [addNewComment] =
     useScopeValue<(e: React.MouseEvent<HTMLButtonElement>) => void>(
       'addNewComment'
@@ -47,6 +50,13 @@ function EditorWidgets() {
     openDocId && openDocId in entries ? entries[openDocId] : undefined
 
   const handleAddNewCommentClick = (e: React.MouseEvent<HTMLButtonElement>) => {
+    if (isReactIde) {
+      e.preventDefault()
+      setIsAddingComment(true)
+      toggleReviewPanel()
+      return
+    }
+
     addNewComment(e)
     setTimeout(() => {
       // Re-render the comment box in order to add autofocus every time

+ 2 - 2
services/web/frontend/js/features/source-editor/components/review-panel/entries/add-comment-entry.tsx

@@ -30,10 +30,10 @@ function AddCommentEntry() {
     handleLayoutChange({ async: true })
   }
 
-  const handleSubmitNewComment = async () => {
+  const handleSubmitNewComment = () => {
     setIsSubmitting(true)
     try {
-      await submitNewComment(content)
+      submitNewComment(content)
       setIsSubmitting(false)
       setIsAddingComment(false)
       setContent('')

+ 1 - 0
services/web/frontend/js/features/source-editor/components/review-panel/review-panel.tsx

@@ -33,6 +33,7 @@ function ReviewPanelView({ parentDomNode }: ReviewPanelViewProps) {
     </>
   )
 
+  // TODO fix DOM structure
   return ReactDOM.createPortal(
     isReactIde ? (
       <div

+ 1 - 1
services/web/frontend/js/features/source-editor/context/review-panel/types/review-panel-state.ts

@@ -76,7 +76,7 @@ export interface ReviewPanelState {
     refreshResolvedCommentsDropdown: () => Promise<
       void | ReviewPanelDocEntries[]
     >
-    submitNewComment: (content: string) => Promise<void>
+    submitNewComment: (content: string) => void
     setEntryHover: React.Dispatch<React.SetStateAction<Value<'entryHover'>>>
     setIsAddingComment: React.Dispatch<
       React.SetStateAction<Value<'isAddingComment'>>