Repository: manusa/electronim
Pull request #462 (2024-12-08 16:08:28)

🐛 don't close dialog(s) if find-in-page visible


Patch:
diff --git a/src/base-window/keyboard-shortcuts.js b/src/base-window/keyboard-shortcuts.js
index aeacbef..608d1b7 100644
--- a/src/base-window/keyboard-shortcuts.js
+++ b/src/base-window/keyboard-shortcuts.js
@@ -31,11 +31,8 @@ const eventAction = (func, {preventDefault = true} = {}) => {
 
 const EVENTS = new Map();
 
-EVENTS.set(eventKey({key: 'Escape'}), eventAction(() => {
-  eventBus.emit(APP_EVENTS.appMenuClose);
-  eventBus.emit(APP_EVENTS.closeDialog);
-  eventBus.emit(APP_EVENTS.findInPageClose);
-}, {preventDefault: false}));
+EVENTS.set(eventKey({key: 'Escape'}),
+  eventAction(() => eventBus.emit(APP_EVENTS.escape), {preventDefault: false}));
 
 EVENTS.set(eventKey({key: 'F11'}), eventAction(() => eventBus.emit(APP_EVENTS.fullscreenToggle)));
 
diff --git a/src/constants/index.js b/src/constants/index.js
index 63f18f1..5b51e5f 100644
--- a/src/constants/index.js
+++ b/src/constants/index.js
@@ -34,6 +34,7 @@ const APP_EVENTS = {
   canNotify: 'canNotify',
   closeDialog: 'closeDialog',
   desktopCapturerGetSources: 'desktopCapturerGetSources',
+  escape: 'escape',
   dictionaryGetAvailable: 'dictionaryGetAvailable',
   dictionaryGetAvailableNative: 'dictionaryGetAvailableNative',
   dictionaryGetEnabled: 'dictionaryGetEnabled',
diff --git a/src/main/index.js b/src/main/index.js
index be5c5ed..ea666dc 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -252,6 +252,14 @@ const initGlobalListeners = () => {
   eventBus.handle(APP_EVENTS.dictionaryGetAvailable, getAvailableDictionaries);
   eventBus.handle(APP_EVENTS.dictionaryGetAvailableNative, getAvailableNativeDictionaries);
   eventBus.handle(APP_EVENTS.dictionaryGetEnabled, getEnabledDictionaries);
+  eventBus.on(APP_EVENTS.escape, () => {
+    if (mainWindow.contentView.children.find(isFindInPage)) {
+      eventBus.emit(APP_EVENTS.findInPageClose);
+    } else {
+      eventBus.emit(APP_EVENTS.appMenuClose);
+      eventBus.emit(APP_EVENTS.closeDialog);
+    }
+  });
   eventBus.on(APP_EVENTS.findInPage, findInPage(mainWindow));
   eventBus.on(APP_EVENTS.findInPageOpen, findInPageOpen(mainWindow));
   eventBus.on(APP_EVENTS.findInPageClose, findInPageClose(mainWindow));


Test patch:
diff --git a/src/base-window/__tests__/keyboard-shortcuts.test.js b/src/base-window/__tests__/keyboard-shortcuts.test.js
index 73595ba..ff7e082 100644
--- a/src/base-window/__tests__/keyboard-shortcuts.test.js
+++ b/src/base-window/__tests__/keyboard-shortcuts.test.js
@@ -28,9 +28,7 @@ describe('Main :: Global Keyboard Shortcuts module test suite', () => {
     };
   });
   test.each([
-    {key: 'Escape', shift: false, control: false, meta: false, appEvent: 'appMenuClose'},
-    {key: 'Escape', shift: false, control: false, meta: false, appEvent: 'closeDialog'},
-    {key: 'Escape', shift: false, control: false, meta: false, appEvent: 'findInPageClose'},
+    {key: 'Escape', shift: false, control: false, meta: false, appEvent: 'escape'},
     {key: 'F11', shift: false, control: false, meta: false, appEvent: 'fullscreenToggle'},
     {key: 'Tab', shift: false, control: true, meta: false, appEvent: 'tabTraverseNext'},
     {key: 'Tab', shift: true, control: true, meta: false, appEvent: 'tabTraversePrevious'},
diff --git a/src/main/__tests__/global-listeners.test.js b/src/main/__tests__/global-listeners.test.js
index e5f8a33..85b619f 100644
--- a/src/main/__tests__/global-listeners.test.js
+++ b/src/main/__tests__/global-listeners.test.js
@@ -136,6 +136,45 @@ describe('Main :: Global listeners test suite', () => {
       expect(view.webContents.destroy).not.toHaveBeenCalled();
     });
   });
+  describe('escape', () => {
+    test('with dialog visible, should close dialog', () => {
+      // Given
+      const dialog = new electron.WebContentsView();
+      dialog.isDialog = true;
+      baseWindow.contentView.children = [dialog];
+      // When
+      eventBus.listeners.escape();
+      // Then
+      expect(dialog.webContents.destroy).toHaveBeenCalledTimes(1);
+    });
+    test('with app menu visible, should close app menu', () => {
+      // Given
+      eventBus.listeners.appMenuOpen();
+      // When
+      eventBus.listeners.escape();
+      // Then
+      expect(baseWindow.contentView.removeChildView).toHaveBeenCalledWith(
+        expect.objectContaining({isAppMenu: true})
+      );
+    });
+    test('with find-in-page visible, should close find-in-page dialog only', () => {
+      // Given
+      const dialog = new electron.WebContentsView();
+      dialog.isDialog = true;
+      eventBus.listeners.appMenuOpen();
+      const findInPageDialog = new electron.WebContentsView();
+      findInPageDialog.isFindInPage = true;
+      baseWindow.contentView.children = [dialog, findInPageDialog];
+      // When
+      eventBus.listeners.escape();
+      // Then
+      expect(dialog.webContents.destroy).not.toHaveBeenCalled();
+      expect(baseWindow.contentView.removeChildView).not.toHaveBeenCalledWith(
+        expect.objectContaining({isAppMenu: true})
+      );
+      expect(findInPageDialog.webContents.destroy).toHaveBeenCalledTimes(1);
+    });
+  });
   describe('fullscreenToggle', () => {
     test('when not fullscreen, should enter fullscreen', () => {
       // Given