Prerequisites
- I have searched for duplicate or closed issues
- I have read the contributing guidelines
Describe the issue
In a CodeView with edit: true, dragging a selection past the edge of the scroller doesn't work the way it does in a text editor. Click on a line and drag below the scroller and the view auto-scrolls as expected, but two things go wrong after that:
- The selection collapses to a caret at the anchor line on the next re-render, so you end up with nothing selected.
- With that fixed (patch below), the selection survives but stops growing at the row where the pointer left the scroller. The view keeps scrolling and the selection doesn't follow.
In VS Code, or in a plain textarea, the selection keeps its start at the anchor line and grows for as long as the button is held. For us this shows up when someone selects a block in a long file to copy it or comment on it: they either lose the selection or get a fraction of what they dragged over.
Seen on @pierre/diffs@1.5.2, Chromium (Electron 44)
Steps
- A
CodeViewwith onediffitem,edit: true, a few hundred lines long so it is taller than the scroller - Click near the top and drag below the scroller's bottom edge
- Watch the selection as the view scrolls: it collapses to a caret. With the patch below applied, it holds but stops at the row where the pointer left the scroller
Potential cause
From the source:
- The collapse. The tail of
__syncRenderViewrestores focus with#restoreReplacementFocus()orthis.focus({ preventScroll: true })without checking#isContentMouseDown. Both reach#focus(position), which writes a collapsed selection atpositionover the live drag selection. - The freeze. Past the scroller's edge the selection is the browser's native one. The browser doesn't extend a held drag into rows that are rendered or recycled while it auto-scrolls. If the anchor's row is virtualized out mid-drag, the browser drops that end too.
Suggested fix
For the collapse, we're carrying this local patch against 1.5.2 and would be glad to drop it:
- add
&& !this.#isContentMouseDownto bothelse ifconditions at the tail of__syncRenderView; - add
if (position !== void 0 && this.#isContentMouseDown) return;afterthis.#contentHasFocus = true;in#focus.
For the freeze, could the editor own the held drag's selection? It could keep the anchor from the press in its model, hit-test the edge row on each scroll while the button is held, and write the selection from the model, the way it already restores the selection after a render. That would also fix the dropped anchor.
Reproduction
https://github.com/eamodio/pierre-diffs-drag-repro
What browser(s) are you seeing the problem on?
Chrome
What version of @pierre/diffs are you using?
1.5.2
Activity
0No activity yet.