diff --git a/services/web/frontend/js/features/source-editor/extensions/add-comment.ts b/services/web/frontend/js/features/source-editor/extensions/add-comment.ts index 8da9c876bd..ad789f0a56 100644 --- a/services/web/frontend/js/features/source-editor/extensions/add-comment.ts +++ b/services/web/frontend/js/features/source-editor/extensions/add-comment.ts @@ -6,7 +6,6 @@ import { Tooltip, } from '@codemirror/view' import { - EditorState, Extension, StateField, StateEffect, @@ -15,6 +14,7 @@ import { } 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>() @@ -36,7 +36,7 @@ export const addComment = (): Extension => { return [] } - return [addCommentTheme, addCommentStateField] + return [addCommentTheme, addCommentStateField, textSelected] } export const addCommentStateField = StateField.define<{ @@ -69,10 +69,14 @@ export const addCommentStateField = StateField.define<{ add: [rangeToAdd], }) } - } - if (tr.docChanged || tr.selection) { - tooltip = buildTooltip(tr.state) + if (effect.is(textSelectedEffect)) { + tooltip = buildTooltip(effect.value) + } + + if (tooltip && tr.state.selection.main.empty) { + tooltip = null + } } return { tooltip, ranges } @@ -84,8 +88,7 @@ export const addCommentStateField = StateField.define<{ ], }) -function buildTooltip(state: EditorState): Tooltip | null { - const range = state.selection.main +function buildTooltip(range: SelectionRange): Tooltip | null { if (range.empty) { return null } diff --git a/services/web/frontend/js/features/source-editor/extensions/text-selected.ts b/services/web/frontend/js/features/source-editor/extensions/text-selected.ts new file mode 100644 index 0000000000..371aafe04b --- /dev/null +++ b/services/web/frontend/js/features/source-editor/extensions/text-selected.ts @@ -0,0 +1,34 @@ +import { SelectionRange, StateEffect } from '@codemirror/state' +import { ViewPlugin } from '@codemirror/view' + +export const textSelectedEffect = StateEffect.define() + +export const textSelected = ViewPlugin.define(view => { + function mouseUpListener() { + if (!view.state.selection.main.empty) { + view.dispatch({ + effects: textSelectedEffect.of(view.state.selection.main), + }) + } + } + function keyUpListener(event: KeyboardEvent) { + if ( + (event.shiftKey || event.key === 'Meta') && + !view.state.selection.main.empty + ) { + view.dispatch({ + effects: textSelectedEffect.of(view.state.selection.main), + }) + } + } + + view.dom.addEventListener('mouseup', mouseUpListener) + view.dom.addEventListener('keyup', keyUpListener) + + return { + destroy() { + view.dom.removeEventListener('mouseup', mouseUpListener) + view.dom.removeEventListener('keyup', keyUpListener) + }, + } +})