Kaynağa Gözat

trackDetachedComments as separate extension

GitOrigin-RevId: 8039de3f9766b072e9bb2170b50e683073105748
Domagoj Kriskovic 2 yıl önce
ebeveyn
işleme
dc70054caf

+ 2 - 0
services/web/frontend/js/features/source-editor/extensions/index.ts

@@ -51,6 +51,7 @@ import { fileTreeItemDrop } from './file-tree-item-drop'
 import { mathPreview } from './math-preview'
 import { isSplitTestEnabled } from '@/utils/splitTestUtils'
 import { ranges } from './ranges'
+import { trackDetachedComments } from './track-detached-comments'
 
 const moduleExtensions: Array<() => Extension> = importOverleafModules(
   'sourceEditorExtensions'
@@ -129,6 +130,7 @@ export const createExtensions = (options: Record<string, any>): Extension[] => [
   isSplitTestEnabled('review-panel-redesign')
     ? ranges(options.currentDoc, options.changeManager)
     : trackChanges(options.currentDoc, options.changeManager),
+  trackDetachedComments(options.currentDoc),
   visual(options.visual),
   mathPreview(options.settings.mathPreview),
   toolbarPanel(),

+ 1 - 88
services/web/frontend/js/features/source-editor/extensions/ranges.ts

@@ -1,11 +1,4 @@
-import {
-  EditorState,
-  RangeSet,
-  StateEffect,
-  StateField,
-  Transaction,
-  TransactionSpec,
-} from '@codemirror/state'
+import { EditorState, StateEffect, TransactionSpec } from '@codemirror/state'
 import {
   Decoration,
   type DecorationSet,
@@ -14,14 +7,6 @@ import {
   ViewPlugin,
   WidgetType,
 } from '@codemirror/view'
-import {
-  findCommentsInCut,
-  findDetachedCommentsInChanges,
-  restoreCommentsOnPaste,
-  restoreDetachedComments,
-  StoredComment,
-} from './changes/comments'
-import { invertedEffects } from '@codemirror/commands'
 import {
   Change,
   DeleteOperation,
@@ -58,17 +43,6 @@ export const updateRanges = (data: RangesData): TransactionSpec => {
 
 const clearChangesEffect = StateEffect.define()
 const buildChangesEffect = StateEffect.define()
-const restoreDetachedCommentsEffect = StateEffect.define<RangeSet<any>>({
-  map: (value, mapping) => {
-    return value
-      .update({
-        filter: (from, to) => {
-          return from <= mapping.length && to <= mapping.length
-        },
-      })
-      .map(mapping)
-  },
-})
 
 type Options = {
   currentDoc: DocumentContainer
@@ -85,68 +59,7 @@ export const ranges = (
   { currentDoc, loadingThreads, ranges, threads }: Options,
   changeManager?: ChangeManager
 ) => {
-  // A state field that stored any comments found within the ranges of a "cut" transaction,
-  // to be restored when pasting matching text.
-  const cutCommentsState = StateField.define<StoredComment[]>({
-    create: () => {
-      return []
-    },
-    update: (value, transaction) => {
-      if (transaction.annotation(Transaction.remote)) {
-        return value
-      }
-
-      if (!transaction.docChanged) {
-        return value
-      }
-
-      if (transaction.isUserEvent('delete.cut')) {
-        return findCommentsInCut(currentDoc, transaction)
-      }
-
-      if (transaction.isUserEvent('input.paste')) {
-        restoreCommentsOnPaste(currentDoc, transaction, value)
-        return []
-      }
-
-      return value
-    },
-  })
-
   return [
-    // attach any comments detached by the transaction as an inverted effect, to be applied on undo
-    invertedEffects.of(transaction => {
-      if (
-        transaction.docChanged &&
-        !transaction.annotation(Transaction.remote)
-      ) {
-        const detachedComments = findDetachedCommentsInChanges(
-          currentDoc,
-          transaction
-        )
-        if (detachedComments.size) {
-          return [restoreDetachedCommentsEffect.of(detachedComments)]
-        }
-      }
-      return []
-    }),
-
-    // restore any detached comments on undo
-    EditorState.transactionExtender.of(transaction => {
-      for (const effect of transaction.effects) {
-        if (effect.is(restoreDetachedCommentsEffect)) {
-          // send the comments to the ShareJS doc
-          restoreDetachedComments(currentDoc, transaction, effect.value)
-
-          // return a transaction spec to rebuild the change markers
-          return buildChangeMarkers()
-        }
-      }
-      return null
-    }),
-
-    cutCommentsState,
-
     // initialize/destroy the change manager, and handle any updates
     changeManager
       ? ViewPlugin.define(() => {

+ 1 - 87
services/web/frontend/js/features/source-editor/extensions/track-changes.ts

@@ -1,10 +1,4 @@
-import {
-  EditorState,
-  RangeSet,
-  StateEffect,
-  StateField,
-  Transaction,
-} from '@codemirror/state'
+import { StateEffect } from '@codemirror/state'
 import {
   Decoration,
   type DecorationSet,
@@ -13,14 +7,6 @@ import {
   ViewPlugin,
   WidgetType,
 } from '@codemirror/view'
-import {
-  findCommentsInCut,
-  findDetachedCommentsInChanges,
-  restoreCommentsOnPaste,
-  restoreDetachedComments,
-  StoredComment,
-} from './changes/comments'
-import { invertedEffects } from '@codemirror/commands'
 import { Change, DeleteOperation } from '../../../../../types/change'
 import { ChangeManager } from './changes/change-manager'
 import { debugConsole } from '@/utils/debugging'
@@ -32,17 +18,6 @@ import {
 
 const clearChangesEffect = StateEffect.define()
 const buildChangesEffect = StateEffect.define()
-const restoreDetachedCommentsEffect = StateEffect.define<RangeSet<any>>({
-  map: (value, mapping) => {
-    return value
-      .update({
-        filter: (from, to) => {
-          return from <= mapping.length && to <= mapping.length
-        },
-      })
-      .map(mapping)
-  },
-})
 
 type Options = {
   currentDoc: DocumentContainer
@@ -57,68 +32,7 @@ export const trackChanges = (
   { currentDoc, loadingThreads }: Options,
   changeManager: ChangeManager
 ) => {
-  // A state field that stored any comments found within the ranges of a "cut" transaction,
-  // to be restored when pasting matching text.
-  const cutCommentsState = StateField.define<StoredComment[]>({
-    create: () => {
-      return []
-    },
-    update: (value, transaction) => {
-      if (transaction.annotation(Transaction.remote)) {
-        return value
-      }
-
-      if (!transaction.docChanged) {
-        return value
-      }
-
-      if (transaction.isUserEvent('delete.cut')) {
-        return findCommentsInCut(currentDoc, transaction)
-      }
-
-      if (transaction.isUserEvent('input.paste')) {
-        restoreCommentsOnPaste(currentDoc, transaction, value)
-        return []
-      }
-
-      return value
-    },
-  })
-
   return [
-    // attach any comments detached by the transaction as an inverted effect, to be applied on undo
-    invertedEffects.of(transaction => {
-      if (
-        transaction.docChanged &&
-        !transaction.annotation(Transaction.remote)
-      ) {
-        const detachedComments = findDetachedCommentsInChanges(
-          currentDoc,
-          transaction
-        )
-        if (detachedComments.size) {
-          return [restoreDetachedCommentsEffect.of(detachedComments)]
-        }
-      }
-      return []
-    }),
-
-    // restore any detached comments on undo
-    EditorState.transactionExtender.of(transaction => {
-      for (const effect of transaction.effects) {
-        if (effect.is(restoreDetachedCommentsEffect)) {
-          // send the comments to the ShareJS doc
-          restoreDetachedComments(currentDoc, transaction, effect.value)
-
-          // return a transaction spec to rebuild the change markers
-          return buildChangeMarkers()
-        }
-      }
-      return null
-    }),
-
-    cutCommentsState,
-
     // initialize/destroy the change manager, and handle any updates
     ViewPlugin.define(() => {
       changeManager.initialize()

+ 105 - 0
services/web/frontend/js/features/source-editor/extensions/track-detached-comments.ts

@@ -0,0 +1,105 @@
+import {
+  EditorState,
+  RangeSet,
+  StateEffect,
+  StateField,
+  Transaction,
+} from '@codemirror/state'
+import {
+  findCommentsInCut,
+  findDetachedCommentsInChanges,
+  restoreCommentsOnPaste,
+  restoreDetachedComments,
+  StoredComment,
+} from './changes/comments'
+import { invertedEffects } from '@codemirror/commands'
+import { DocumentContainer } from '@/features/ide-react/editor/document-container'
+import { isSplitTestEnabled } from '@/utils/splitTestUtils'
+import { buildChangeMarkers } from './track-changes'
+
+const restoreDetachedCommentsEffect = StateEffect.define<RangeSet<any>>({
+  map: (value, mapping) => {
+    return value
+      .update({
+        filter: (from, to) => {
+          return from <= mapping.length && to <= mapping.length
+        },
+      })
+      .map(mapping)
+  },
+})
+
+/**
+ * A custom extension that detects detached comments when a comment is cut and pasted,
+ * or when a deleted comment is undone
+ */
+export const trackDetachedComments = ({
+  currentDoc,
+}: {
+  currentDoc: DocumentContainer
+}) => {
+  // A state field that stored any comments found within the ranges of a "cut" transaction,
+  // to be restored when pasting matching text.
+  const cutCommentsState = StateField.define<StoredComment[]>({
+    create: () => {
+      return []
+    },
+    update: (value, transaction) => {
+      if (transaction.annotation(Transaction.remote)) {
+        return value
+      }
+
+      if (!transaction.docChanged) {
+        return value
+      }
+
+      if (transaction.isUserEvent('delete.cut')) {
+        return findCommentsInCut(currentDoc, transaction)
+      }
+
+      if (transaction.isUserEvent('input.paste')) {
+        restoreCommentsOnPaste(currentDoc, transaction, value)
+        return []
+      }
+
+      return value
+    },
+  })
+
+  return [
+    // attach any comments detached by the transaction as an inverted effect, to be applied on undo
+    invertedEffects.of(transaction => {
+      if (
+        transaction.docChanged &&
+        !transaction.annotation(Transaction.remote)
+      ) {
+        const detachedComments = findDetachedCommentsInChanges(
+          currentDoc,
+          transaction
+        )
+        if (detachedComments.size) {
+          return [restoreDetachedCommentsEffect.of(detachedComments)]
+        }
+      }
+      return []
+    }),
+
+    // restore any detached comments on undo
+    EditorState.transactionExtender.of(transaction => {
+      for (const effect of transaction.effects) {
+        if (effect.is(restoreDetachedCommentsEffect)) {
+          // send the comments to the ShareJS doc
+          restoreDetachedComments(currentDoc, transaction, effect.value)
+
+          if (isSplitTestEnabled('review-panel-redesign')) {
+            // return a transaction spec to rebuild the change markers
+            return buildChangeMarkers()
+          }
+        }
+      }
+      return null
+    }),
+
+    cutCommentsState,
+  ]
+}