mirror of
https://github.com/overleaf/overleaf.git
synced 2025-02-20 03:54:02 +00:00
Merge pull request #20411 from overleaf/dk-highlight-focus-ranges
Highlight and focus ranges in editor for new review panel GitOrigin-RevId: 4fef31a8c9e6dc974519d925c7478665e0c8cc29
This commit is contained in:
parent
8a0bed71e1
commit
22e4c2de2c
2 changed files with 130 additions and 2 deletions
|
@ -8,6 +8,7 @@ import { isSelectionWithinOp } from '../utils/is-selection-within-op'
|
|||
import { EditorSelection } from '@codemirror/state'
|
||||
import { EditorView } from '@codemirror/view'
|
||||
import classNames from 'classnames'
|
||||
import { highlightRanges } from '@/features/source-editor/extensions/ranges'
|
||||
|
||||
export const ReviewPanelEntry: FC<{
|
||||
position: number
|
||||
|
@ -40,6 +41,8 @@ export const ReviewPanelEntry: FC<{
|
|||
<div
|
||||
onFocus={focusHandler}
|
||||
onBlur={() => setFocused(false)}
|
||||
onMouseEnter={() => view.dispatch(highlightRanges(op))}
|
||||
onMouseLeave={() => view.dispatch(highlightRanges())}
|
||||
role="button"
|
||||
tabIndex={position + 1}
|
||||
className={classNames(
|
||||
|
|
|
@ -7,12 +7,21 @@ import {
|
|||
ViewPlugin,
|
||||
WidgetType,
|
||||
} from '@codemirror/view'
|
||||
import { Change, DeleteOperation } from '../../../../../types/change'
|
||||
import {
|
||||
AnyOperation,
|
||||
Change,
|
||||
DeleteOperation,
|
||||
} from '../../../../../types/change'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { isCommentOperation, isDeleteOperation } from '@/utils/operations'
|
||||
import {
|
||||
isCommentOperation,
|
||||
isDeleteOperation,
|
||||
isInsertOperation,
|
||||
} from '@/utils/operations'
|
||||
import { DocumentContainer } from '@/features/ide-react/editor/document-container'
|
||||
import { Ranges } from '@/features/review-panel-new/context/ranges-context'
|
||||
import { Threads } from '@/features/review-panel-new/context/threads-context'
|
||||
import { isSelectionWithinOp } from '@/features/review-panel-new/utils/is-selection-within-op'
|
||||
|
||||
type RangesData = {
|
||||
ranges: Ranges
|
||||
|
@ -20,6 +29,7 @@ type RangesData = {
|
|||
}
|
||||
|
||||
const updateRangesEffect = StateEffect.define<RangesData>()
|
||||
const highlightRangesEffect = StateEffect.define<AnyOperation | undefined>()
|
||||
|
||||
export const updateRanges = (data: RangesData): TransactionSpec => {
|
||||
return {
|
||||
|
@ -27,6 +37,12 @@ export const updateRanges = (data: RangesData): TransactionSpec => {
|
|||
}
|
||||
}
|
||||
|
||||
export const highlightRanges = (op?: AnyOperation): TransactionSpec => {
|
||||
return {
|
||||
effects: highlightRangesEffect.of(op),
|
||||
}
|
||||
}
|
||||
|
||||
type Options = {
|
||||
currentDoc: DocumentContainer
|
||||
loadingThreads?: boolean
|
||||
|
@ -89,6 +105,68 @@ export const ranges = ({ ranges, threads }: Options) => {
|
|||
}
|
||||
),
|
||||
|
||||
// draw highlight decorations
|
||||
ViewPlugin.define<
|
||||
PluginValue & {
|
||||
decorations: DecorationSet
|
||||
}
|
||||
>(
|
||||
() => {
|
||||
return {
|
||||
decorations: Decoration.none,
|
||||
update(update) {
|
||||
for (const transaction of update.transactions) {
|
||||
this.decorations = this.decorations.map(transaction.changes)
|
||||
|
||||
for (const effect of transaction.effects) {
|
||||
if (effect.is(highlightRangesEffect)) {
|
||||
this.decorations = buildHighlightDecorations(
|
||||
'ol-cm-change-highlight',
|
||||
effect.value
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
decorations: value => value.decorations,
|
||||
}
|
||||
),
|
||||
|
||||
// draw focus decorations
|
||||
ViewPlugin.define<
|
||||
PluginValue & {
|
||||
decorations: DecorationSet
|
||||
}
|
||||
>(
|
||||
() => {
|
||||
return {
|
||||
decorations: Decoration.none,
|
||||
update(update) {
|
||||
this.decorations = Decoration.none
|
||||
|
||||
if (!ranges) {
|
||||
return
|
||||
}
|
||||
|
||||
for (const range of [...ranges.changes, ...ranges.comments]) {
|
||||
if (isSelectionWithinOp(range.op, update.state.selection.main)) {
|
||||
this.decorations = buildHighlightDecorations(
|
||||
'ol-cm-change-focus',
|
||||
range.op
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
decorations: value => value.decorations,
|
||||
}
|
||||
),
|
||||
|
||||
// styles for change decorations
|
||||
trackChangesTheme,
|
||||
]
|
||||
|
@ -115,6 +193,29 @@ const buildChangeDecorations = (data: RangesData) => {
|
|||
return Decoration.set(decorations, true)
|
||||
}
|
||||
|
||||
const buildHighlightDecorations = (className: string, op?: AnyOperation) => {
|
||||
if (!op) {
|
||||
return Decoration.none
|
||||
}
|
||||
|
||||
if (isDeleteOperation(op)) {
|
||||
// nothing to highlight for deletions (for now)
|
||||
// TODO: add highlight when delete indicator is done
|
||||
return Decoration.none
|
||||
}
|
||||
|
||||
const opFrom = op.p
|
||||
const opLength = isInsertOperation(op) ? op.i.length : op.c.length
|
||||
const opType = isInsertOperation(op) ? 'i' : 'c'
|
||||
|
||||
return Decoration.set(
|
||||
Decoration.mark({
|
||||
class: `${className} ${className}-${opType}`,
|
||||
}).range(opFrom, opFrom + opLength),
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
class ChangeDeletedWidget extends WidgetType {
|
||||
constructor(public change: Change<DeleteOperation>) {
|
||||
super()
|
||||
|
@ -202,4 +303,28 @@ const trackChangesTheme = EditorView.baseTheme({
|
|||
borderLeft: '2px dotted #c5060b',
|
||||
marginLeft: '-1px',
|
||||
},
|
||||
'&light .ol-cm-change-highlight-i': {
|
||||
backgroundColor: '#b8dbc899',
|
||||
},
|
||||
'&dark .ol-cm-change-highlight-i': {
|
||||
backgroundColor: '#b8dbc899',
|
||||
},
|
||||
'&light .ol-cm-change-highlight-c': {
|
||||
backgroundColor: '#fcc4837d',
|
||||
},
|
||||
'&dark .ol-cm-change-highlight-c': {
|
||||
backgroundColor: '#fcc4837d',
|
||||
},
|
||||
'&light .ol-cm-change-focus-i': {
|
||||
backgroundColor: '#B8DBC8',
|
||||
},
|
||||
'&dark .ol-cm-change-focus-i': {
|
||||
backgroundColor: '#B8DBC8',
|
||||
},
|
||||
'&light .ol-cm-change-focus-c': {
|
||||
backgroundColor: '#FCC483',
|
||||
},
|
||||
'&dark .ol-cm-change-focus-c': {
|
||||
backgroundColor: '#FCC483',
|
||||
},
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue