mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
trackDetachedComments as separate extension
GitOrigin-RevId: 8039de3f9766b072e9bb2170b50e683073105748
This commit is contained in:
parent
ec6b17eb01
commit
dc70054caf
4 changed files with 109 additions and 175 deletions
|
@ -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,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,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()
|
||||
|
|
|
@ -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,
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue