// ==UserScript==
// @name Gmail Enhanced Toolbar
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Adds custom buttons to Gmail toolbar with toggleable features.
// @author Antigravity
// @match https://mail.google.com/*
// @updateURL https://raw.githubusercontent.com/nguyenhuy158/tampermonkey-script/main/gmail-enhanced.user.js
// @downloadURL https://raw.githubusercontent.com/nguyenhuy158/tampermonkey-script/main/gmail-enhanced.user.js
// @grant GM_registerMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// @run-at document-end
// ==/UserScript==
(function () {
'use strict';
// --- Configuration & State Management ---
const FEATURES = {
FILTER_NEAR_ARCHIVE: {
id: 'filterNearArchive',
name: 'Filter Button (Left of Archive)',
default: true
},
FILTER_NEAR_SELECT: {
id: 'filterNearSelect',
name: 'Filter Button (Right of Select)',
default: true
}
};
const config = {};
Object.keys(FEATURES).forEach(key => {
const feature = FEATURES[key];
config[feature.id] = GM_getValue(feature.id, feature.default);
GM_registerMenuCommand(`${config[feature.id] ? '✅' : '❌'} ${feature.name}`, () => {
GM_setValue(feature.id, !config[feature.id]);
location.reload();
});
});
// --- Utility Functions ---
function waitForElement(selector, callback, interval = 500, timeout = 10000) {
const startTime = Date.now();
const check = () => {
const el = document.querySelector(selector);
if (el) {
callback(el);
} else if (Date.now() - startTime < timeout) {
setTimeout(check, interval);
}
};
check();
}
function createGmailButton(label, iconHtml, title, onClick) {
const btn = document.createElement('div');
btn.className = 'T-I J-J5-Ji T-I-ax7 T-I-Js-IF mA custom-gmail-btn';
btn.setAttribute('role', 'button');
btn.setAttribute('tabindex', '0');
btn.setAttribute('data-tooltip', title);
btn.setAttribute('aria-label', title);
btn.style.userSelect = 'none';
btn.style.marginRight = '4px';
btn.style.marginLeft = '4px';
btn.style.display = 'inline-flex';
btn.style.alignItems = 'center';
btn.style.justifyContent = 'center';
btn.title = title;
const iconContainer = document.createElement('div');
iconContainer.className = 'asa';
iconContainer.innerHTML = iconHtml || `filter_list`;
btn.appendChild(iconContainer);
btn.addEventListener('click', (e) => {
e.stopPropagation();
onClick();
});
// Hover effect
btn.addEventListener('mouseenter', () => btn.classList.add('T-I-JW'));
btn.addEventListener('mouseleave', () => btn.classList.remove('T-I-JW'));
return btn;
}
function triggerFilterAction() {
// Try to trigger the "Filter messages like these" action
// 1. Find the 'More' button
const moreBtn = document.querySelector('div[aria-label="More email options"], div[data-tooltip="More"]');
if (moreBtn) {
moreBtn.click();
// Wait for menu to appear and click "Filter messages like these"
setTimeout(() => {
const menuItems = document.querySelectorAll('div[role="menuitem"]');
for (let item of menuItems) {
if (item.textContent.includes('Filter messages like these')) {
item.click();
break;
}
}
}, 50);
} else {
console.warn('More button not found');
}
}
// SVG for the Filter icon (similar to Gmail's style)
const FILTER_ICON_SVG = ``;
// --- Main Logic ---
function injectButtons() {
// 1. Feature: Filter Button Near Archive
if (config.filterNearArchive) {
const archiveBtn = document.querySelector('div[aria-label="Archive"]');
if (archiveBtn && !document.getElementById('custom-filter-archive')) {
const filterBtn = createGmailButton('Filter', FILTER_ICON_SVG, 'Filter messages like these', triggerFilterAction);
filterBtn.id = 'custom-filter-archive';
archiveBtn.parentNode.insertBefore(filterBtn, archiveBtn);
}
}
// 2. Feature: Filter Button Near Select
if (config.filterNearSelect) {
const selectGroup = document.querySelector('div.G-as3') || document.querySelector('div[aria-label="Select"]');
if (selectGroup && !document.getElementById('custom-filter-select')) {
const filterBtn = createGmailButton('Filter', FILTER_ICON_SVG, 'Filter messages like these', triggerFilterAction);
filterBtn.id = 'custom-filter-select';
// Insert after the select group
selectGroup.insertAdjacentElement('afterend', filterBtn);
}
}
}
// Watch for toolbar changes
const observer = new MutationObserver(() => {
injectButtons();
});
observer.observe(document.body, {
childList: true,
subtree: true
});
// Initial injection
injectButtons();
})();