overlays: Avoid closing when dragging resizers.

Fixes most of #35663.
This commit is contained in:
Tim Abbott
2025-08-12 17:22:09 -07:00
parent 1001c0d60a
commit 4e94324b9a
5 changed files with 37 additions and 2 deletions

View File

@@ -169,6 +169,7 @@ EXEMPT_FILES = make_set(
"web/src/message_viewport.ts",
"web/src/messages_overlay_ui.ts",
"web/src/modals.ts",
"web/src/mouse_drag.ts",
"web/src/muted_users_ui.ts",
"web/src/narrow_history.ts",
"web/src/narrow_title.ts",

View File

@@ -3,6 +3,7 @@ import Micromodal from "micromodal";
import assert from "minimalistic-assert";
import * as blueslip from "./blueslip.ts";
import * as mouse_drag from "./mouse_drag.ts";
import * as overlay_util from "./overlay_util.ts";
import * as overlays from "./overlays.ts";
@@ -157,7 +158,7 @@ export function open(
input inside the modal too far will weirdly close the modal.
See https://github.com/ghosh/Micromodal/issues/505.
Work around this with our own implementation. */
if (document.getSelection()?.type === "Range") {
if (mouse_drag.is_drag(e)) {
return;
}
close(modal_id);

30
web/src/mouse_drag.ts Normal file
View File

@@ -0,0 +1,30 @@
import $ from "jquery";
let start_x = 0;
let start_y = 0;
export function initialize(): void {
$(document).on("mousedown", (e) => {
start_x = e.pageX;
start_y = e.pageY;
});
}
export function is_drag(e: JQuery.ClickEvent): boolean {
// Used to prevent click handlers from firing when dragging a
// region, even if not actually selecting something.
// Total distance the mouse has moved since the mouse went down.
const drag_distance = Math.abs(e.pageX - start_x) + Math.abs(e.pageY - start_y);
const sel = window.getSelection();
const has_selection = Boolean(sel?.type === "Range" && sel.toString().length > 0);
// A very low drag_distance cutoff (2) can prevent a click after
// moving the mouse rapidly from registering.
//
// So we only use that low cutoff when the drag resulted in
// actually selecting something, and use a larger distance for
// non-selection drags, like resizing textareas.
return drag_distance > 20 || (drag_distance > 2 && has_selection);
}

View File

@@ -1,6 +1,7 @@
import $ from "jquery";
import * as blueslip from "./blueslip.ts";
import * as mouse_drag from "./mouse_drag.ts";
import * as overlay_util from "./overlay_util.ts";
type Hook = () => void;
@@ -177,7 +178,7 @@ export function initialize(): void {
$("body").on("click", "div.overlay, div.overlay .exit", (e) => {
let $target = $(e.target);
if (document.getSelection()?.type === "Range") {
if (mouse_drag.is_drag(e)) {
return;
}

View File

@@ -80,6 +80,7 @@ import * as message_view from "./message_view.ts";
import * as message_view_header from "./message_view_header.ts";
import * as message_viewport from "./message_viewport.ts";
import * as modals from "./modals.ts";
import * as mouse_drag from "./mouse_drag.ts";
import * as muted_users from "./muted_users.ts";
import * as narrow_history from "./narrow_history.ts";
import * as narrow_state from "./narrow_state.ts";
@@ -441,6 +442,7 @@ export async function initialize_everything(state_data) {
user_settings before setting the theme. Because information
density is so fundamental, we initialize that first, however. */
initialize_user_settings(state_data.user_settings);
mouse_drag.initialize();
sidebar_ui.restore_sidebar_toggle_status();
i18n.initialize({language_list: page_params.language_list});
timerender.initialize();