From 2b4184f7b5ecb7c30871a07de744389558b14a4e Mon Sep 17 00:00:00 2001 From: Victor Emanouilov Date: Fri, 22 Aug 2025 15:49:21 +0300 Subject: [PATCH 1/3] fix(frontend,backend): more unread count fixes --- modules/desktop_notifications/site.js | 1 - modules/imap/handler_modules.php | 16 +++++++++++----- modules/imap/site.js | 6 ++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/modules/desktop_notifications/site.js b/modules/desktop_notifications/site.js index 54403d81c3..a958a049c8 100644 --- a/modules/desktop_notifications/site.js +++ b/modules/desktop_notifications/site.js @@ -23,7 +23,6 @@ $(function() { setInterval(() => { // undefined_undefined: load with no filter and no keyword new Hm_MessagesStore('unread', 1, 'undefined_undefined').load(true, true).then((store) => { - $('.total_unread_count').html(' '+store.count+' '); store.newMessages.forEach((messageRow) => { triggerNewMessageEvent($(messageRow).data('uid'), $(messageRow)[0]); }); diff --git a/modules/imap/handler_modules.php b/modules/imap/handler_modules.php index 3da9ee37ab..2cb71424a5 100644 --- a/modules/imap/handler_modules.php +++ b/modules/imap/handler_modules.php @@ -1282,7 +1282,13 @@ public function process() { list($sort, $reverse) = process_sort_arg($this->request->get['sort'], $this->user_config->get('default_sort_order_setting', 'arrival')); - switch ($this->get('list_path')) { + if (isset($this->request->post['list_path'])) { + $list_path = $this->request->post['list_path']; + } else { + $list_path = $this->get('list_path'); + } + + switch ($list_path) { case 'email': $filter = 'ALL'; $limit = $this->user_config->get('all_email_per_source_setting', DEFAULT_ALL_EMAIL_PER_SOURCE); @@ -1295,14 +1301,14 @@ public function process() { break; case 'flagged': case 'unread': - $filter = $this->get('list_path') == 'unread' ? 'UNSEEN' : mb_strtoupper($this->get('list_path')); + $filter = $list_path == 'unread' ? 'UNSEEN' : mb_strtoupper($list_path); default: if (empty($filter)) { $filter = 'ALL'; } - if ($this->get('list_path')) { - $limit = $this->user_config->get($this->get('list_path').'_per_source_setting', DEFAULT_PER_SOURCE); - $date = process_since_argument($this->user_config->get($this->get('list_path').'_since_setting', DEFAULT_SINCE)); + if ($list_path) { + $limit = $this->user_config->get($list_path.'_per_source_setting', DEFAULT_PER_SOURCE); + $date = process_since_argument($this->user_config->get($list_path.'_since_setting', DEFAULT_SINCE)); } else { $limit = $this->user_config->get('all_per_source_setting', DEFAULT_ALL_PER_SOURCE); $date = process_since_argument($this->user_config->get('all_since_setting', DEFAULT_SINCE)); diff --git a/modules/imap/site.js b/modules/imap/site.js index 2bff119f16..84d7cc04f8 100644 --- a/modules/imap/site.js +++ b/modules/imap/site.js @@ -479,12 +479,10 @@ var setup_imap_folder_page = async function(listPath, listPage = 1) { await select_imap_folder(listPath, listPage, true) } - new Hm_MessagesStore('unread', 1, 'undefined_undefined').load(true, true); - - // Refresh in the background each 30 seconds and abort any pending request when the page unmounts + // Refresh in the background each 60 seconds const interval = setInterval(async () => { select_imap_folder(listPath, 1, true, true); - }, 30000); + }, 60000); // Return cleanup function to clear interval when page unmounts return () => { From c8023e7a7716a632e0dd8fa4b815de11b20b9f8b Mon Sep 17 00:00:00 2001 From: camilevahviraki Date: Tue, 14 Oct 2025 12:31:52 +0200 Subject: [PATCH 2/3] enhance(imap): message actions dropdown close when opening another --- modules/imap/site.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules/imap/site.js b/modules/imap/site.js index e8ead7afa8..cea845c9b9 100644 --- a/modules/imap/site.js +++ b/modules/imap/site.js @@ -1553,3 +1553,13 @@ $(document).on('submit', '#shareForm', function(e) { } ); }); + +document.addEventListener("show.bs.dropdown", function (event) { + // When one dropdown opens, close all others + document.querySelectorAll(".dropdown-toggle.show").forEach((openBtn) => { + if (openBtn !== event.target) { + const dropdownInstance = bootstrap.Dropdown.getInstance(openBtn); + if (dropdownInstance) dropdownInstance.hide(); + } + }); +}); From f8aff181e909364158fb0495d792fc53ab5ad77f Mon Sep 17 00:00:00 2001 From: camilevahviraki Date: Tue, 14 Oct 2025 15:17:47 +0200 Subject: [PATCH 3/3] Ensure only one top-level dropdown is open at a time --- modules/core/site.js | 18 ++++++++++++++++++ modules/imap/site.js | 10 ---------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/modules/core/site.js b/modules/core/site.js index 848a323447..592958d9be 100644 --- a/modules/core/site.js +++ b/modules/core/site.js @@ -2587,3 +2587,21 @@ function setupActionSnooze(callback) { }); $(document).on('change', '.nexter_input_snooze', callback); } + +document.addEventListener("show.bs.dropdown", function (event) { + const currentToggle = event.target; + + // If it's nested inside a dropdown menu, skip + if (currentToggle.closest(".dropdown-menu")) { + return; + } + + // Close other top-level dropdowns + document.querySelectorAll(".dropdown-toggle.show").forEach((openBtn) => { + if (openBtn !== currentToggle && !openBtn.closest(".dropdown-menu")) { + const dropdownInstance = bootstrap.Dropdown.getInstance(openBtn); + if (dropdownInstance) dropdownInstance.hide(); + } + }); +}); + diff --git a/modules/imap/site.js b/modules/imap/site.js index cea845c9b9..e8ead7afa8 100644 --- a/modules/imap/site.js +++ b/modules/imap/site.js @@ -1553,13 +1553,3 @@ $(document).on('submit', '#shareForm', function(e) { } ); }); - -document.addEventListener("show.bs.dropdown", function (event) { - // When one dropdown opens, close all others - document.querySelectorAll(".dropdown-toggle.show").forEach((openBtn) => { - if (openBtn !== event.target) { - const dropdownInstance = bootstrap.Dropdown.getInstance(openBtn); - if (dropdownInstance) dropdownInstance.hide(); - } - }); -});