Skip to content

Commit e86e97f

Browse files
committed
feat(mdviewer): add drag auto-scroll near edges in edit mode
Auto-scroll the viewer when dragging content near the top or bottom 5% of the frame. Scroll speed increases closer to the edge. Clear image selection on drag start. All drag listeners cleaned up on exit edit mode.
1 parent 3260362 commit e86e97f

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

src-mdviewer/src/components/editor.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ let pasteHandler = null;
2222
let checkboxHandler = null;
2323
let selectionHandler = null;
2424
let selectionFallbackMouseUp = null;
25+
let _dragScrollInterval = null;
26+
let _dragOverHandler = null;
27+
let _dragEndHandler = null;
28+
let _dragStartHandler = null;
2529
let selectionFallbackKeyUp = null;
2630

2731
// Platform detection
@@ -2190,6 +2194,43 @@ function enterEditMode(content) {
21902194
content.addEventListener("mouseup", selectionFallbackMouseUp);
21912195
content.addEventListener("keyup", selectionFallbackKeyUp);
21922196

2197+
// Drag auto-scroll: scroll when dragging near top/bottom 5% of viewer
2198+
const appViewer = document.getElementById("app-viewer");
2199+
_dragStartHandler = (e) => {
2200+
// Clear image selection on drag start
2201+
content.querySelectorAll("img.image-selected").forEach(
2202+
el => el.classList.remove("image-selected"));
2203+
};
2204+
_dragOverHandler = (e) => {
2205+
if (!appViewer) return;
2206+
const rect = appViewer.getBoundingClientRect();
2207+
const threshold = rect.height * 0.05;
2208+
const y = e.clientY - rect.top;
2209+
2210+
clearInterval(_dragScrollInterval);
2211+
if (y < threshold) {
2212+
// Near top — scroll up
2213+
const speed = Math.max(2, Math.round((threshold - y) / threshold * 12));
2214+
_dragScrollInterval = setInterval(() => {
2215+
appViewer.scrollTop -= speed;
2216+
}, 16);
2217+
} else if (y > rect.height - threshold) {
2218+
// Near bottom — scroll down
2219+
const speed = Math.max(2, Math.round((y - (rect.height - threshold)) / threshold * 12));
2220+
_dragScrollInterval = setInterval(() => {
2221+
appViewer.scrollTop += speed;
2222+
}, 16);
2223+
}
2224+
};
2225+
_dragEndHandler = () => {
2226+
clearInterval(_dragScrollInterval);
2227+
_dragScrollInterval = null;
2228+
};
2229+
content.addEventListener("dragstart", _dragStartHandler);
2230+
content.addEventListener("dragover", _dragOverHandler);
2231+
content.addEventListener("dragend", _dragEndHandler);
2232+
content.addEventListener("drop", _dragEndHandler);
2233+
21932234
initFormatBar(content);
21942235
initLinkPopover(content);
21952236
initImagePopover(content);
@@ -2208,6 +2249,23 @@ function cleanupEditMode(content) {
22082249
clearTimeout(contentChangeTimer);
22092250
contentChangeTimer = null;
22102251

2252+
// Clean up drag auto-scroll
2253+
clearInterval(_dragScrollInterval);
2254+
_dragScrollInterval = null;
2255+
if (_dragStartHandler) {
2256+
content.removeEventListener("dragstart", _dragStartHandler);
2257+
_dragStartHandler = null;
2258+
}
2259+
if (_dragOverHandler) {
2260+
content.removeEventListener("dragover", _dragOverHandler);
2261+
_dragOverHandler = null;
2262+
}
2263+
if (_dragEndHandler) {
2264+
content.removeEventListener("dragend", _dragEndHandler);
2265+
content.removeEventListener("drop", _dragEndHandler);
2266+
_dragEndHandler = null;
2267+
}
2268+
22112269
destroyFormatBar();
22122270
destroyLinkPopover();
22132271
destroyImagePopover();

0 commit comments

Comments
 (0)