From 2feb3fd891482f1049ea395bb7a32c2046a083d5 Mon Sep 17 00:00:00 2001 From: PathGao <42336971+PathGao@users.noreply.github.com> Date: Sat, 25 Jul 2026 05:25:06 +0900 Subject: [PATCH] fix: dismiss menus around modal dialogs --- scripts/menuModalGuards.test.ts | 23 +++++++++++++++++++++++ src/lib/MarkdownViewer.svelte | 1 + src/lib/components/Modal.svelte | 7 ++++++- src/lib/components/TitleBar.svelte | 19 ++++++++++++------- 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 scripts/menuModalGuards.test.ts diff --git a/scripts/menuModalGuards.test.ts b/scripts/menuModalGuards.test.ts new file mode 100644 index 00000000..b6dbb38e --- /dev/null +++ b/scripts/menuModalGuards.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; +import test from 'node:test'; + +const viewer = readFileSync(new URL('../src/lib/MarkdownViewer.svelte', import.meta.url), 'utf8'); +const titleBar = readFileSync(new URL('../src/lib/components/TitleBar.svelte', import.meta.url), 'utf8'); +const modal = readFileSync(new URL('../src/lib/components/Modal.svelte', import.meta.url), 'utf8'); + +test('document context menus do not open while a modal is active', () => { + assert.match( + viewer, + /function handleContextMenu\(e: MouseEvent\) \{\n\t\tif \(modalState\.show\) return;/, + ); +}); + +test('titlebar menus close before a document context menu opens', () => { + assert.match(titleBar, /window\.addEventListener\('contextmenu', handleGlobalDismiss\)/); + assert.match(titleBar, /window\.addEventListener\('blur', handleGlobalDismiss\)/); +}); + +test('modal backdrop consumes context-menu events', () => { + assert.match(modal, /oncontextmenu=\{\(e\) => \{ e\.preventDefault\(\); e\.stopPropagation\(\); \}\}/); +}); diff --git a/src/lib/MarkdownViewer.svelte b/src/lib/MarkdownViewer.svelte index df723ec7..103f5e25 100644 --- a/src/lib/MarkdownViewer.svelte +++ b/src/lib/MarkdownViewer.svelte @@ -2093,6 +2093,7 @@ import { t } from './utils/i18n.js'; } function handleContextMenu(e: MouseEvent) { + if (modalState.show) return; if (mode !== 'app') return; e.preventDefault(); diff --git a/src/lib/components/Modal.svelte b/src/lib/components/Modal.svelte index a4c45ceb..279d2fca 100644 --- a/src/lib/components/Modal.svelte +++ b/src/lib/components/Modal.svelte @@ -97,7 +97,12 @@ {#if show} -