Skip to content

Commit f405f35

Browse files
#6154 Fix: 3 dot menu action button not appear issue (#6162)
* fix: 3 dot menu action button not appear issue * feat: added test * fix: message select issue
1 parent cb15d50 commit f405f35

File tree

2 files changed

+71
-8
lines changed

2 files changed

+71
-8
lines changed

extension/js/content_scripts/webmail/gmail/gmail-element-replacer.ts

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export class GmailElementReplacer extends WebmailElementReplacer {
5757
msgInnerText: 'table.cf.An',
5858
msgInnerContainingPgp: "div.a3s:not(.undefined):contains('" + PgpArmor.headers('null').begin + "')",
5959
msgActionsBtn: '.Wsq5Cf',
60+
msgActionsBtnExpanded: '.Wsq5Cf[aria-expanded="true"]',
6061
msgActionsMenu: '.tB5Jxf-M-S5Cmsd, ul.aqdrmf-Kf[role="menu"]',
6162
attachmentsContainerOuter: 'div.hq.gt',
6263
attachmentsContainerInner: 'div.aQH',
@@ -298,12 +299,18 @@ export class GmailElementReplacer extends WebmailElementReplacer {
298299
};
299300

300301
private addMenuButton = (replyOption: ReplyOption, gmailContextMenuBtn: Element | null) => {
301-
if (gmailContextMenuBtn && $(gmailContextMenuBtn).is(':visible') && !document.querySelector(`.action_${replyOption.replace('a_', '')}_message_button`)) {
302-
const button = $(this.factory.btnSecureMenuBtn(replyOption)).insertAfter(gmailContextMenuBtn); // xss-safe-factory
303-
button.on(
304-
'click',
305-
Ui.event.handle((el, ev: JQuery.Event) => this.actionActivateSecureReplyHandler(el, ev))
306-
);
302+
if (gmailContextMenuBtn && $(gmailContextMenuBtn).is(':visible')) {
303+
const btnClass = `action_${replyOption.replace('a_', '')}_message_button`;
304+
// Check if button already exists in this specific menu (sibling of the target button)
305+
const alreadyExists = $(gmailContextMenuBtn).parent().find(`.${btnClass}`).length > 0;
306+
307+
if (!alreadyExists) {
308+
const button = $(this.factory.btnSecureMenuBtn(replyOption)).insertAfter(gmailContextMenuBtn); // xss-safe-factory
309+
button.on(
310+
'click',
311+
Ui.event.handle((el, ev: JQuery.Event) => this.actionActivateSecureReplyHandler(el, ev))
312+
);
313+
}
307314
}
308315
};
309316

@@ -402,7 +409,7 @@ export class GmailElementReplacer extends WebmailElementReplacer {
402409
this.insertEncryptedReplyBox(messageContainer, replyOption);
403410
}
404411
if (secureReplyInvokedFromMenu) {
405-
$(this.sel.msgActionsBtn).trigger('click');
412+
$(this.sel.msgActionsBtnExpanded).trigger('click');
406413
}
407414
};
408415

@@ -970,7 +977,25 @@ export class GmailElementReplacer extends WebmailElementReplacer {
970977
}
971978

972979
// Find the message container from the menu's position or context
973-
const messageContainer = $('div.h7:visible').last(); // Get the last visible message container
980+
let messageContainer;
981+
982+
// Try to find the trigger button that opened this menu (it should have aria-expanded="true")
983+
const messageContainerSelector = 'div.h7:visible';
984+
const menuTrigger = document.querySelector(this.sel.msgActionsBtnExpanded);
985+
986+
if (menuTrigger) {
987+
if (this.debug) {
988+
console.debug('addSecureActionsToMessageMenu found menu trigger:', menuTrigger);
989+
}
990+
messageContainer = $(menuTrigger).closest(this.sel.msgOuter).closest(messageContainerSelector);
991+
if (!messageContainer.length) {
992+
// Fallback
993+
messageContainer = $(messageContainerSelector).last();
994+
}
995+
} else {
996+
messageContainer = $(messageContainerSelector).last(); // Get the last visible message container
997+
}
998+
974999
const msgIdElement = messageContainer.find('[data-legacy-message-id], [data-message-id]');
9751000
const msgId = msgIdElement.attr('data-legacy-message-id') || msgIdElement.attr('data-message-id');
9761001

test/source/tests/gmail.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,44 @@ export const defineGmailTests = (testVariant: TestVariant, testWithBrowser: Test
719719
// expect(content).to.contain('Fingerprint: 7A2E 4FFD 34BC 4AED 0F54 4199 D652 7AD6 65C3 B0DD');
720720
// }));
721721

722+
test(
723+
'mail.google.com - verify secure reply buttons on expanded older message',
724+
testWithBrowser(async (t, browser) => {
725+
await BrowserRecipe.setUpCommonAcct(t, browser, 'ci.tests.gmail');
726+
const gmailPage = await openGmailPage(t, browser);
727+
// Use a known thread with multiple messages.
728+
await gotoGmailPage(gmailPage, '/FMfcgzGqRGfPBbNLWvfPvDbxnHBwkdGf');
729+
730+
// 1. Verify buttons on the newest message (usually expanded by default)
731+
await Util.sleep(3);
732+
let messages = await gmailPage.target.$$('[role="listitem"] .adn.ads');
733+
const newestMessage = messages[messages.length - 1];
734+
const newestMenuBtn = await newestMessage.$('[aria-label="More message options"]');
735+
await newestMenuBtn?.click();
736+
await Util.sleep(1);
737+
738+
await gmailPage.waitAll('.action_reply_message_button');
739+
const collapsedMessage = await gmailPage.target.$('[role="listitem"] .adf.ads');
740+
if (collapsedMessage) {
741+
await collapsedMessage.click();
742+
await Util.sleep(2);
743+
}
744+
745+
// Now find the 3-dot menu on this expanded older message.
746+
// After expansion, it should have .adn.ads class active/visible.
747+
748+
messages = await gmailPage.target.$$('[role="listitem"] .adn.ads');
749+
const olderExpandedMessage = messages[0];
750+
const olderMenuBtn = await olderExpandedMessage.$('[aria-label="More message options"]');
751+
expect(olderMenuBtn).to.be.ok;
752+
await olderMenuBtn?.click();
753+
await Util.sleep(1);
754+
755+
// Verify secure buttons exist in the open menu for the older message
756+
await gmailPage.waitAll('.action_reply_message_button');
757+
})
758+
);
759+
722760
const testMinimumElementHeight = async (page: ControllablePage, selector: string, min: number) => {
723761
// testing https://github.com/FlowCrypt/flowcrypt-browser/issues/3519
724762
const elStyle = await page.target.$eval(selector, el => el.getAttribute('style')); // 'height: 289.162px;'

0 commit comments

Comments
 (0)