mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-30 07:45:26 -05:00
1c5f5950fa
Add options to accept/reject all changes to review tooltip GitOrigin-RevId: 1cea76926d59d0354c8abaa6ba69b7e99c02fbe0
139 lines
3.3 KiB
TypeScript
139 lines
3.3 KiB
TypeScript
import {
|
|
Decoration,
|
|
DecorationSet,
|
|
EditorView,
|
|
showTooltip,
|
|
Tooltip,
|
|
} from '@codemirror/view'
|
|
import {
|
|
Extension,
|
|
StateField,
|
|
StateEffect,
|
|
Range,
|
|
SelectionRange,
|
|
} from '@codemirror/state'
|
|
import { isSplitTestEnabled } from '@/utils/splitTestUtils'
|
|
import { v4 as uuid } from 'uuid'
|
|
import { textSelected, textSelectedEffect } from './text-selected'
|
|
|
|
export const addNewCommentRangeEffect = StateEffect.define<Range<Decoration>>()
|
|
|
|
export const removeNewCommentRangeEffect = StateEffect.define<Decoration>()
|
|
|
|
export const buildAddNewCommentRangeEffect = (range: SelectionRange) => {
|
|
return addNewCommentRangeEffect.of(
|
|
Decoration.mark({
|
|
tagName: 'span',
|
|
class: `ol-cm-change ol-cm-change-c`,
|
|
opType: 'c',
|
|
id: uuid(),
|
|
}).range(range.from, range.to)
|
|
)
|
|
}
|
|
|
|
export const reviewTooltip = (): Extension => {
|
|
if (!isSplitTestEnabled('review-panel-redesign')) {
|
|
return []
|
|
}
|
|
|
|
return [reviewTooltipTheme, reviewTooltipStateField, textSelected]
|
|
}
|
|
|
|
export const reviewTooltipStateField = StateField.define<{
|
|
tooltip: Tooltip | null
|
|
addCommentRanges: DecorationSet
|
|
}>({
|
|
create() {
|
|
return { tooltip: null, addCommentRanges: Decoration.none }
|
|
},
|
|
|
|
update(field, tr) {
|
|
let { tooltip, addCommentRanges } = field
|
|
|
|
addCommentRanges = addCommentRanges.map(tr.changes)
|
|
|
|
for (const effect of tr.effects) {
|
|
if (effect.is(removeNewCommentRangeEffect)) {
|
|
const rangeToRemove = effect.value
|
|
addCommentRanges = addCommentRanges.update({
|
|
// eslint-disable-next-line no-unused-vars
|
|
filter: (from, to, value) => {
|
|
return value.spec.id !== rangeToRemove.spec.id
|
|
},
|
|
})
|
|
}
|
|
|
|
if (effect.is(addNewCommentRangeEffect)) {
|
|
const rangeToAdd = effect.value
|
|
addCommentRanges = addCommentRanges.update({
|
|
add: [rangeToAdd],
|
|
})
|
|
}
|
|
|
|
if (effect.is(textSelectedEffect)) {
|
|
tooltip = buildTooltip(effect.value)
|
|
}
|
|
|
|
if (tooltip && tr.state.selection.main.empty) {
|
|
tooltip = null
|
|
}
|
|
}
|
|
|
|
return { tooltip, addCommentRanges }
|
|
},
|
|
|
|
provide: field => [
|
|
EditorView.decorations.from(field, field => field.addCommentRanges),
|
|
showTooltip.compute([field], state => state.field(field).tooltip),
|
|
],
|
|
})
|
|
|
|
function buildTooltip(range: SelectionRange): Tooltip | null {
|
|
if (range.empty) {
|
|
return null
|
|
}
|
|
|
|
return {
|
|
pos: range.assoc < 0 ? range.to : range.from,
|
|
above: true,
|
|
strictSide: true,
|
|
arrow: false,
|
|
create() {
|
|
const dom = document.createElement('div')
|
|
dom.className = 'review-tooltip-menu-container'
|
|
return { dom, overlap: true, offset: { x: 0, y: 8 } }
|
|
},
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Styles for the tooltip
|
|
*/
|
|
const reviewTooltipTheme = EditorView.baseTheme({
|
|
'.review-tooltip-menu-container.cm-tooltip': {
|
|
backgroundColor: 'transparent',
|
|
border: 'none',
|
|
},
|
|
|
|
'&light': {
|
|
'& .review-tooltip-menu': {
|
|
backgroundColor: 'white',
|
|
},
|
|
'& .review-tooltip-menu-button': {
|
|
'&:hover': {
|
|
backgroundColor: '#2f3a4c14',
|
|
},
|
|
},
|
|
},
|
|
|
|
'&dark': {
|
|
'& .review-tooltip-menu': {
|
|
backgroundColor: '#1b222c',
|
|
},
|
|
'& .review-tooltip-menu-button': {
|
|
'&:hover': {
|
|
backgroundColor: '#2f3a4c',
|
|
},
|
|
},
|
|
},
|
|
})
|