]*>((.|[\n\r])*)<\/title>/i)[0];
$('main').replaceWith(main);
+ document.title = title.replace(/<[^>]*>/g, '');
window.location.next = url;
diff --git a/modules/core/navigation/utils.js b/modules/core/navigation/utils.js
index 30781d63b3..fb15f57418 100644
--- a/modules/core/navigation/utils.js
+++ b/modules/core/navigation/utils.js
@@ -1,23 +1,9 @@
-const toastHTML = `
-
-`
-document.body.insertAdjacentHTML('beforeend', toastHTML)
-
function showRoutingToast() {
- bootstrap.Toast.getOrCreateInstance(document.getElementById('routing-toast')).show()
+ window.routingToast = showLoaderToast('Redirecting...');
}
function hideRoutingToast() {
- bootstrap.Toast.getOrCreateInstance(document.getElementById('routing-toast')).hide()
+ window.routingToast.hide();
}
function getListPathParam() {
diff --git a/modules/core/site.css b/modules/core/site.css
index 9cd5d27de7..1eba77fca2 100644
--- a/modules/core/site.css
+++ b/modules/core/site.css
@@ -10,7 +10,6 @@ body {
.compose_page,
.message_list,
.msg_text,
-.selected_part,
.server_content,
.profile_content,
.user_settings,
diff --git a/modules/core/site.js b/modules/core/site.js
index e3be6dc3dc..e914aff6de 100644
--- a/modules/core/site.js
+++ b/modules/core/site.js
@@ -917,27 +917,27 @@ function Message_List() {
};
/* TODO: remove module specific refs */
- this.update_title = function() {
+ this.update_title = function(list_path = getListPathParam()) {
var count = 0;
var rows = Hm_Utils.rows();
var tbody = Hm_Utils.tbody();
- if (getListPathParam() == 'unread') {
+ if (list_path == 'unread') {
count = rows.length;
document.title = count+' '+hm_trans('Unread');
}
- else if (getListPathParam() == 'flagged') {
+ else if (list_path == 'flagged') {
count = rows.length;
document.title = count+' '+hm_trans('Flagged');
}
- else if (getListPathParam() == 'combined_inbox') {
+ else if (list_path == 'combined_inbox') {
count = $('tr .unseen', tbody).length;
document.title = count+' '+hm_trans('Unread in Everything');
}
- else if (getListPathParam() == 'email') {
+ else if (list_path == 'email') {
count = $('tr .unseen', tbody).length;
document.title = count+' '+hm_trans('Unread in Email');
}
- else if (getListPathParam() == 'feeds') {
+ else if (list_path == 'feeds') {
count = $('tr .unseen', tbody).length;
document.title = count+' '+hm_trans('Unread in Feeds');
}
diff --git a/modules/imap/functions.php b/modules/imap/functions.php
index e68c0156a0..13bef44782 100644
--- a/modules/imap/functions.php
+++ b/modules/imap/functions.php
@@ -468,7 +468,7 @@ function format_msg_part_row($id, $vals, $output_mod, $level, $part, $dl_args, $
if ($mobile) {
$res .= ''.$output_mod->html_safe($size);
$res .= '
'.$output_mod->html_safe(decode_fld($desc)).'
';
- $res .= '';
+ $res .= '';
}
else {
$res .= ''.$output_mod->html_safe($size);
@@ -477,10 +477,10 @@ function format_msg_part_row($id, $vals, $output_mod, $level, $part, $dl_args, $
' | '.(isset($vals['attributes']['charset']) && trim($vals['attributes']['charset']) ? $output_mod->html_safe(mb_strtolower($vals['attributes']['charset'])) : '');
}
$res .= ' | '.$output_mod->html_safe(decode_fld($desc)).' | ';
- $res .= ''.$output_mod->trans('Download').' | ';
+ $res .= ''.$output_mod->trans('Download').' | ';
}
if ($output_mod->get('allow_delete_attachment') && isset($vals['file_attributes']['attachment'])) {
- $res .= ''.$output_mod->trans('Remove').' | ';
+ $res .= ''.$output_mod->trans('Remove').' | ';
}
$res .= '';
return $res;
@@ -641,7 +641,7 @@ function format_attachment($struct, $output_mod, $part, $dl_args, $at_args) {
$res .= ''.$output_mod->html_safe(decode_fld($desc)).' | ';
$res .= ''.$output_mod->html_safe($size).' | ';
- $res .= ''.$output_mod->trans('Download').' | ';
+ $res .= ''.$output_mod->trans('Download').' | ';
if ($output_mod->get('allow_delete_attachment') && isset($vals['file_attributes']['attachment'])) {
$res .= ''.$output_mod->trans('Remove').' |
';
}
diff --git a/modules/imap/js_modules/route_handlers.js b/modules/imap/js_modules/route_handlers.js
index a449a53e66..3908bc9b89 100644
--- a/modules/imap/js_modules/route_handlers.js
+++ b/modules/imap/js_modules/route_handlers.js
@@ -6,6 +6,17 @@ function applyImapMessageListPageHandlers(routeParams) {
imap_setup_snooze();
imap_setup_tags();
+ Hm_Message_List.set_row_events();
+
+ $('.core_msg_control').on("click", function(e) {
+ e.preventDefault();
+ Hm_Message_List.message_action($(this).data('action'));
+ });
+ $('.toggle_link').on("click", function(e) {
+ e.preventDefault();
+ Hm_Message_List.toggle_rows();
+ });
+
if (window.githubMessageListPageHandler) githubMessageListPageHandler(routeParams);
if (window.inlineMessageMessageListAndSearchPageHandler) inlineMessageMessageListAndSearchPageHandler(routeParams);
if (window.wpMessageListPageHandler) wpMessageListPageHandler(routeParams);
diff --git a/modules/imap/js_modules/utils/attachements.js b/modules/imap/js_modules/utils/attachements.js
new file mode 100644
index 0000000000..bfa99d1a19
--- /dev/null
+++ b/modules/imap/js_modules/utils/attachements.js
@@ -0,0 +1,21 @@
+function handleAttachementDownload() {
+ $('.download_link a').on("click", async function(e) {
+ e.preventDefault();
+ const loaderInstance = showLoaderToast("Downloading attachment...");
+ const href = $(this).data('src');
+ try {
+ await fetch(href).then(res => res.blob()).then(blob => {
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = 'attachment';
+ a.click();
+ URL.revokeObjectURL(url);
+ });
+ } catch (error) {
+ Hm_Notices.show([`ERR${error.message}`]);
+ } finally {
+ loaderInstance.hide();
+ }
+ });
+}
\ No newline at end of file
diff --git a/modules/imap/js_modules/utils/messageParts.js b/modules/imap/js_modules/utils/messageParts.js
new file mode 100644
index 0000000000..1e8578a151
--- /dev/null
+++ b/modules/imap/js_modules/utils/messageParts.js
@@ -0,0 +1,7 @@
+function handleViewMessagePart() {
+ $('.msg_part_link').on("click", function(e) {
+ e.preventDefault();
+ const messagePart = $(this).data('messagePart');
+ get_message_content(messagePart, getMessageUidParam() ?? inline_msg_uid, getListPathParam());
+ });
+}
\ No newline at end of file
diff --git a/modules/imap/site.js b/modules/imap/site.js
index b6d888f091..5d0ce57b28 100644
--- a/modules/imap/site.js
+++ b/modules/imap/site.js
@@ -467,6 +467,9 @@ var setup_imap_folder_page = async function(listPath) {
await select_imap_folder(listPath, true, true)
}
+ // Update browser title
+ Hm_Message_List.update_title(listPath);
+
// Refresh in the background each 30 seconds and abort any pending request when the page unmounts
const backgroundAbortController = new AbortController();
const interval = setInterval(async () => {
@@ -684,7 +687,7 @@ var get_message_content = function(msg_part, uid, list_path, detail, callback, n
{'name': 'folder', 'value': detail.folder}],
function(res) {
onSuccess(res);
- if (!noupdate) {
+ if (!noupdate && !msg_part) {
Hm_Utils.save_to_local_storage(getMessageStorageKey(uid), JSON.stringify(res));
}
},
@@ -846,6 +849,9 @@ var imap_message_view_finished = function(msg_uid, detail, skip_links) {
return block_unblock_sender(msg_uid, detail, $(this).data('target'), 'unblock', sender);
});
fixLtrInRtl();
+
+ handleAttachementDownload();
+ handleViewMessagePart();
};
var get_local_message_content = function(msg_uid, path) {
diff --git a/modules/inline_message/site.js b/modules/inline_message/site.js
index 682034816f..a412581c22 100644
--- a/modules/inline_message/site.js
+++ b/modules/inline_message/site.js
@@ -94,7 +94,6 @@ var get_inline_msg_details = function(link) {
};
var msg_inline_close = function() {
- $('.refresh_link').trigger('click');
if (inline_msg_style() == 'right') {
$('.msg_text').remove();
$('.message_table').css('width', '100%');
@@ -126,7 +125,6 @@ var capture_subject_click = function() {
var inline_msg_loaded_callback = function() {
$('.header_subject th').append('');
$('.close_inline_msg').on("click", function() { msg_inline_close(); });
- $('.msg_part_link').on("click", function() { return get_message_content($(this).data('messagePart'), uid, list_path, details, inline_msg_loaded_callback, false, $(this).data('allowImages')); });
update_imap_links(uid, details);
};
diff --git a/scripts/config_gen.php b/scripts/config_gen.php
index 1fb595ad7b..b4c98770cc 100644
--- a/scripts/config_gen.php
+++ b/scripts/config_gen.php
@@ -188,7 +188,8 @@ function get_module_assignments($settings) {
$js .= file_get_contents($js_module);
}
}
- foreach (glob('modules' . DIRECTORY_SEPARATOR . $mod . DIRECTORY_SEPARATOR . 'js_modules' . DIRECTORY_SEPARATOR . '*.js') as $js_module) {
+ $directoriesPattern = str_replace('/', DIRECTORY_SEPARATOR, "{*,*/*}");
+ foreach (glob('modules' . DIRECTORY_SEPARATOR . $mod . DIRECTORY_SEPARATOR . 'js_modules' . DIRECTORY_SEPARATOR . $directoriesPattern . '*.js', GLOB_BRACE) as $js_module) {
$js .= file_get_contents($js_module);
}
if (is_readable(sprintf("modules/%s/site.js", $mod))) {
diff --git a/tests/selenium/folder_list.py b/tests/selenium/folder_list.py
index ccd03a63fc..e020a6d30d 100644
--- a/tests/selenium/folder_list.py
+++ b/tests/selenium/folder_list.py
@@ -53,7 +53,7 @@ def hide_folders(self):
self.driver.execute_script("arguments[0].click();", hide_button)
assert self.by_class('folder_toggle').text.startswith('Show folders')
list_item = self.by_class('menu_home')
- link = list_item.find_element(By.TAG_NAME, 'a');
+ link = list_item.find_element(By.TAG_NAME, 'a')
assert link.is_displayed() == False
def show_folders(self):
diff --git a/tests/selenium/pages.py b/tests/selenium/pages.py
index b42fc5061d..a5663315a1 100644
--- a/tests/selenium/pages.py
+++ b/tests/selenium/pages.py
@@ -126,7 +126,7 @@ def folders(self):
list_item.find_element(By.TAG_NAME, 'a').click()
self.wait_with_folder_list()
self.safari_workaround()
- self.wait(By.CLASS_NAME, 'content_title')
+ self.wait_for_navigation_to_complete()
assert self.by_class('content_title').text == 'Folders'
def save(self):
@@ -156,6 +156,7 @@ def profiles(self):
list_item.find_element(By.TAG_NAME, 'a').click()
self.wait_with_folder_list()
self.safari_workaround()
+ self.wait_for_navigation_to_complete()
assert self.by_class('profile_content_title').text == 'Profiles'
if __name__ == '__main__':
diff --git a/tests/selenium/settings.py b/tests/selenium/settings.py
index 4029b72eff..0a8f20c008 100644
--- a/tests/selenium/settings.py
+++ b/tests/selenium/settings.py
@@ -84,6 +84,7 @@ def __init__(self):
self.wait()
def load_settings_page(self):
+ self.wait_on_class('main_menu')
self.by_css('[data-source=".settings"]').click()
list_item = self.by_class('menu_settings')
list_item.find_element(By.TAG_NAME, 'a').click()