icons are now in a menu
This commit is contained in:
parent
630938e30f
commit
6b37ba894b
1 changed files with 124 additions and 75 deletions
|
|
@ -16,6 +16,85 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function createThreeDotsMenu(isDark, menuItems, panelColors) {
|
||||||
|
const wrapper = document.createElement('div');
|
||||||
|
wrapper.style.cssText = 'position: relative; display: inline-block;';
|
||||||
|
|
||||||
|
const dotsBtn = document.createElement('span');
|
||||||
|
dotsBtn.textContent = '\u22EE';
|
||||||
|
dotsBtn.style.cssText = 'cursor: pointer; opacity: 0.7; font-size: 18px; padding: 2px 6px; line-height: 1; user-select: none; transition: opacity 0.2s;';
|
||||||
|
dotsBtn.onmouseover = () => dotsBtn.style.opacity = '1';
|
||||||
|
dotsBtn.onmouseout = () => dotsBtn.style.opacity = '0.7';
|
||||||
|
|
||||||
|
const dropdown = document.createElement('div');
|
||||||
|
const dropdownBg = panelColors.bg;
|
||||||
|
const dropdownBorder = panelColors.border;
|
||||||
|
const defaultTextColor = panelColors.text;
|
||||||
|
dropdown.style.cssText = `display: none; position: absolute; right: 0; top: 100%; z-index: 9999; min-width: 180px; background-color: ${dropdownBg}; border: 1px solid ${dropdownBorder}; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.15); overflow: hidden;`;
|
||||||
|
|
||||||
|
menuItems.forEach(item => {
|
||||||
|
const row = document.createElement('div');
|
||||||
|
row.style.cssText = `display: flex; align-items: center; gap: 8px; padding: 8px 12px; cursor: pointer; font-size: 13px; color: ${defaultTextColor}; transition: background-color 0.15s, color 0.15s;`;
|
||||||
|
|
||||||
|
const iconSpan = document.createElement('span');
|
||||||
|
iconSpan.textContent = item.icon;
|
||||||
|
iconSpan.style.cssText = 'font-size: 15px; width: 18px; text-align: center;';
|
||||||
|
|
||||||
|
const labelSpan = document.createElement('span');
|
||||||
|
labelSpan.textContent = item.label;
|
||||||
|
|
||||||
|
row.appendChild(iconSpan);
|
||||||
|
row.appendChild(labelSpan);
|
||||||
|
|
||||||
|
const hoverBg = item.hoverColor === '#cc0000'
|
||||||
|
? (isDark ? 'rgba(204,0,0,0.2)' : 'rgba(204,0,0,0.1)')
|
||||||
|
: (isDark ? 'rgba(77,157,224,0.2)' : 'rgba(26,95,168,0.1)');
|
||||||
|
|
||||||
|
row.onmouseover = () => {
|
||||||
|
row.style.backgroundColor = hoverBg;
|
||||||
|
row.style.color = item.hoverColor;
|
||||||
|
};
|
||||||
|
row.onmouseout = () => {
|
||||||
|
row.style.backgroundColor = '';
|
||||||
|
row.style.color = defaultTextColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
row.onclick = (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
dropdown.style.display = 'none';
|
||||||
|
if (item.disableAfterClick) {
|
||||||
|
row.onclick = null;
|
||||||
|
row.style.opacity = '0.5';
|
||||||
|
row.style.pointerEvents = 'none';
|
||||||
|
}
|
||||||
|
item.onClick();
|
||||||
|
};
|
||||||
|
|
||||||
|
dropdown.appendChild(row);
|
||||||
|
});
|
||||||
|
|
||||||
|
dotsBtn.onclick = (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
dropdown.style.display = dropdown.style.display === 'none' ? 'block' : 'none';
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
if (!wrapper.contains(e.target)) {
|
||||||
|
dropdown.style.display = 'none';
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'Escape' && dropdown.style.display !== 'none') {
|
||||||
|
dropdown.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.appendChild(dotsBtn);
|
||||||
|
wrapper.appendChild(dropdown);
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
browser.runtime.onMessage.addListener((message) => {
|
browser.runtime.onMessage.addListener((message) => {
|
||||||
switch (message.command) {
|
switch (message.command) {
|
||||||
case "getSelectedText": {
|
case "getSelectedText": {
|
||||||
|
|
@ -702,34 +781,31 @@ switch (message.command) {
|
||||||
branding.textContent = browser.i18n.getMessage("antispam_by") + " ThunderAI";
|
branding.textContent = browser.i18n.getMessage("antispam_by") + " ThunderAI";
|
||||||
branding.style.cssText = 'margin-left: auto; font-style: italic; font-size: 10px; opacity: 0.5;';
|
branding.style.cssText = 'margin-left: auto; font-style: italic; font-size: 10px; opacity: 0.5;';
|
||||||
|
|
||||||
const spamRefreshBtn = document.createElement('span');
|
const spamMenu = createThreeDotsMenu(isDark, [
|
||||||
spamRefreshBtn.textContent = '↻';
|
{
|
||||||
spamRefreshBtn.title = browser.i18n.getMessage("spamfilter_refresh") || 'Refresh spam report';
|
icon: '↻',
|
||||||
spamRefreshBtn.style.cssText = 'cursor: pointer; opacity: 0.6; font-size: 16px; padding: 0 5px; transition: opacity 0.2s, color 0.2s;';
|
label: browser.i18n.getMessage("spamfilter_refresh") || 'Refresh spam report',
|
||||||
spamRefreshBtn.onmouseover = () => { spamRefreshBtn.style.opacity = '1'; spamRefreshBtn.style.color = isDark ? '#4d9de0' : '#1a5fa8'; };
|
hoverColor: isDark ? '#4d9de0' : '#1a5fa8',
|
||||||
spamRefreshBtn.onmouseout = () => { spamRefreshBtn.style.opacity = '0.6'; spamRefreshBtn.style.color = ''; };
|
disableAfterClick: true,
|
||||||
spamRefreshBtn.onclick = function() {
|
onClick: () => {
|
||||||
spamRefreshBtn.onclick = null;
|
browser.runtime.sendMessage({ command: "refreshSpamReport", headerMessageId: data.headerMessageId });
|
||||||
spamRefreshBtn.style.opacity = '0.6';
|
}
|
||||||
browser.runtime.sendMessage({ command: "refreshSpamReport", headerMessageId: data.headerMessageId });
|
},
|
||||||
};
|
{
|
||||||
|
icon: '×',
|
||||||
const closeBtn = document.createElement('span');
|
label: browser.i18n.getMessage("spamfilter_delete") || 'Delete spam report',
|
||||||
closeBtn.textContent = '×';
|
hoverColor: '#cc0000',
|
||||||
closeBtn.style.cssText = 'cursor: pointer; opacity: 0.6; font-size: 16px; padding: 0 5px; transition: opacity 0.2s, color 0.2s;';
|
onClick: () => {
|
||||||
closeBtn.title = browser.i18n.getMessage("spamfilter_delete");
|
container.remove();
|
||||||
closeBtn.onmouseover = () => { closeBtn.style.opacity = '1'; closeBtn.style.color = '#cc0000'; };
|
browser.runtime.sendMessage({ command: "removeSpamReport", headerMessageId: data.headerMessageId });
|
||||||
closeBtn.onmouseout = () => { closeBtn.style.opacity = '0.6'; closeBtn.style.color = ''; };
|
}
|
||||||
closeBtn.onclick = function() {
|
}
|
||||||
container.remove();
|
], { bg: bgColor, border: borderColor, text: textColor });
|
||||||
browser.runtime.sendMessage({ command: "removeSpamReport", headerMessageId: data.headerMessageId });
|
|
||||||
};
|
|
||||||
|
|
||||||
container.appendChild(scoreText);
|
container.appendChild(scoreText);
|
||||||
container.appendChild(reasonText);
|
container.appendChild(reasonText);
|
||||||
container.appendChild(branding);
|
container.appendChild(branding);
|
||||||
container.appendChild(spamRefreshBtn);
|
container.appendChild(spamMenu);
|
||||||
container.appendChild(closeBtn);
|
|
||||||
|
|
||||||
document.body.insertBefore(container, document.body.firstChild);
|
document.body.insertBefore(container, document.body.firstChild);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
|
|
@ -773,47 +849,32 @@ switch (message.command) {
|
||||||
summaryTitle.textContent = browser.i18n.getMessage("summarize_title");
|
summaryTitle.textContent = browser.i18n.getMessage("summarize_title");
|
||||||
summaryTitle.style.cssText = `font-weight: bold; font-size: 14px; color: ${titleColor};`;
|
summaryTitle.style.cssText = `font-weight: bold; font-size: 14px; color: ${titleColor};`;
|
||||||
|
|
||||||
const refreshBtn = document.createElement('span');
|
const summaryMenu = createThreeDotsMenu(isDarkSummary, [
|
||||||
refreshBtn.textContent = '↻';
|
{
|
||||||
refreshBtn.title = browser.i18n.getMessage("summarize_refresh") || 'Refresh summary';
|
icon: '↻',
|
||||||
refreshBtn.style.cssText = `cursor: pointer; opacity: 0.6; font-size: 16px; transition: opacity 0.2s, color 0.2s;`;
|
label: browser.i18n.getMessage("summarize_refresh") || 'Refresh summary',
|
||||||
refreshBtn.onmouseover = () => { refreshBtn.style.opacity = '1'; refreshBtn.style.color = isDarkSummary ? '#4d9de0' : '#1a5fa8'; };
|
hoverColor: isDarkSummary ? '#4d9de0' : '#1a5fa8',
|
||||||
refreshBtn.onmouseout = () => { refreshBtn.style.opacity = '0.6'; refreshBtn.style.color = ''; };
|
disableAfterClick: true,
|
||||||
refreshBtn.onclick = async () => {
|
onClick: () => {
|
||||||
refreshBtn.onclick = null;
|
browser.runtime.sendMessage({
|
||||||
refreshBtn.style.opacity = '0.6';
|
command: "refreshSummary",
|
||||||
browser.runtime.sendMessage({
|
headerMessageId: summaryData.headerMessageId
|
||||||
command: "refreshSummary",
|
});
|
||||||
headerMessageId: summaryData.headerMessageId
|
}
|
||||||
});
|
},
|
||||||
};
|
{
|
||||||
|
icon: '×',
|
||||||
const summaryCloseBtn = document.createElement('span');
|
label: browser.i18n.getMessage("summarize_delete") || 'Delete summary',
|
||||||
summaryCloseBtn.textContent = '×';
|
hoverColor: '#cc0000',
|
||||||
summaryCloseBtn.style.cssText = 'cursor: pointer; opacity: 0.6; font-size: 16px; padding: 0 5px; transition: opacity 0.2s, color 0.2s;';
|
onClick: () => {
|
||||||
summaryCloseBtn.title = browser.i18n.getMessage("summarize_delete");
|
summaryContainer.remove();
|
||||||
summaryCloseBtn.onmouseover = () => { summaryCloseBtn.style.opacity = '1'; summaryCloseBtn.style.color = '#cc0000'; };
|
browser.runtime.sendMessage({ command: "removeSummary", headerMessageId: summaryData.headerMessageId });
|
||||||
summaryCloseBtn.onmouseout = () => { summaryCloseBtn.style.opacity = '0.6'; summaryCloseBtn.style.color = ''; };
|
}
|
||||||
summaryCloseBtn.onclick = function() {
|
}
|
||||||
summaryContainer.remove();
|
], { bg: bgColorSummary, border: borderColorSummary, text: textColorSummary });
|
||||||
browser.runtime.sendMessage({ command: "removeSummary", headerMessageId: summaryData.headerMessageId });
|
|
||||||
};
|
|
||||||
|
|
||||||
const collapseBtn = document.createElement('span');
|
|
||||||
collapseBtn.textContent = '∧';
|
|
||||||
collapseBtn.title = browser.i18n.getMessage("summarize_collapse") || 'Collapse summary';
|
|
||||||
collapseBtn.style.cssText = `cursor: pointer; opacity: 0.6; font-size: 16px; transition: opacity 0.2s;`;
|
|
||||||
collapseBtn.onmouseover = () => collapseBtn.style.opacity = '1';
|
|
||||||
collapseBtn.onmouseout = () => collapseBtn.style.opacity = '0.6';
|
|
||||||
|
|
||||||
const summaryBtnGroup = document.createElement('span');
|
|
||||||
summaryBtnGroup.style.cssText = 'display: flex; align-items: center; gap: 5px;';
|
|
||||||
summaryBtnGroup.appendChild(refreshBtn);
|
|
||||||
summaryBtnGroup.appendChild(summaryCloseBtn);
|
|
||||||
summaryBtnGroup.appendChild(collapseBtn);
|
|
||||||
|
|
||||||
summaryHeader.appendChild(summaryTitle);
|
summaryHeader.appendChild(summaryTitle);
|
||||||
summaryHeader.appendChild(summaryBtnGroup);
|
summaryHeader.appendChild(summaryMenu);
|
||||||
summaryContainer.appendChild(summaryHeader);
|
summaryContainer.appendChild(summaryHeader);
|
||||||
|
|
||||||
const summaryText = document.createElement('div');
|
const summaryText = document.createElement('div');
|
||||||
|
|
@ -825,18 +886,6 @@ switch (message.command) {
|
||||||
}
|
}
|
||||||
summaryText.style.cssText = `font-size: 14px; line-height: 1.4;`;
|
summaryText.style.cssText = `font-size: 14px; line-height: 1.4;`;
|
||||||
|
|
||||||
collapseBtn.onclick = () => {
|
|
||||||
if (summaryText.style.display === 'none') {
|
|
||||||
summaryText.style.display = '';
|
|
||||||
summaryHeader.style.marginBottom = '0.5rem';
|
|
||||||
collapseBtn.textContent = '∧';
|
|
||||||
} else {
|
|
||||||
summaryText.style.display = 'none';
|
|
||||||
summaryHeader.style.marginBottom = '0';
|
|
||||||
collapseBtn.textContent = '∨';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
summaryContainer.appendChild(summaryText);
|
summaryContainer.appendChild(summaryText);
|
||||||
|
|
||||||
document.body.insertBefore(summaryContainer, document.body.firstChild);
|
document.body.insertBefore(summaryContainer, document.body.firstChild);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue