8192fab1b8
* account for iframes in popup list/write-style and badge * fix and simplify openURL + onTabReady + message from popup * fixup! resolve about:blank iframes to their parent URL * fixup! don't underline iframe links until hovered * fix width bug in popup only when needed (Chrome 66-69) * fixup! reset styleIds on main page navigation * fixup! call updateCount explicitly on extension pages * fixup! ensure frame url is present * fixup! frameResults entry may be empty * fixup! init main frame first * fixup! track iframes via ports * fixup! reduce badge update rate during page load * fixup! cosmetics * fixup! don't add frames with errors * fixup! cosmetics
137 lines
3.7 KiB
JavaScript
137 lines
3.7 KiB
JavaScript
/* global prefs debounce iconUtil FIREFOX CHROME VIVALDI tabManager navigatorUtil API_METHODS */
|
|
/* exported iconManager */
|
|
'use strict';
|
|
|
|
const iconManager = (() => {
|
|
const ICON_SIZES = FIREFOX || CHROME >= 2883 && !VIVALDI ? [16, 32] : [19, 38];
|
|
const staleBadges = new Set();
|
|
|
|
prefs.subscribe([
|
|
'disableAll',
|
|
'badgeDisabled',
|
|
'badgeNormal',
|
|
], () => debounce(refreshIconBadgeColor));
|
|
|
|
prefs.subscribe([
|
|
'show-badge'
|
|
], () => debounce(refreshAllIconsBadgeText));
|
|
|
|
prefs.subscribe([
|
|
'disableAll',
|
|
'iconset',
|
|
], () => debounce(refreshAllIcons));
|
|
|
|
prefs.initializing.then(() => {
|
|
refreshIconBadgeColor();
|
|
refreshAllIconsBadgeText();
|
|
refreshAllIcons();
|
|
});
|
|
|
|
Object.assign(API_METHODS, {
|
|
/** @param {(number|string)[]} styleIds
|
|
* @param {boolean} [lazyBadge=false] preventing flicker during page load */
|
|
updateIconBadge(styleIds, {lazyBadge} = {}) {
|
|
// FIXME: in some cases, we only have to redraw the badge. is it worth a optimization?
|
|
const {frameId, tab: {id: tabId}} = this.sender;
|
|
const value = styleIds.length ? styleIds.map(Number) : undefined;
|
|
tabManager.set(tabId, 'styleIds', frameId, value);
|
|
debounce(refreshStaleBadges, frameId && lazyBadge ? 250 : 0);
|
|
staleBadges.add(tabId);
|
|
if (!frameId) refreshIcon(tabId, true);
|
|
},
|
|
});
|
|
|
|
navigatorUtil.onCommitted(({tabId, frameId}) => {
|
|
if (!frameId) tabManager.set(tabId, 'styleIds', undefined);
|
|
});
|
|
|
|
chrome.runtime.onConnect.addListener(port => {
|
|
if (port.name === 'iframe') {
|
|
port.onDisconnect.addListener(onPortDisconnected);
|
|
}
|
|
});
|
|
|
|
function onPortDisconnected({sender}) {
|
|
if (tabManager.get(sender.tab.id, 'styleIds')) {
|
|
API_METHODS.updateIconBadge.call({sender}, [], {lazyBadge: true});
|
|
}
|
|
}
|
|
|
|
function refreshIconBadgeText(tabId) {
|
|
const text = prefs.get('show-badge') ? `${getStyleCount(tabId)}` : '';
|
|
iconUtil.setBadgeText({tabId, text});
|
|
}
|
|
|
|
function getIconName(hasStyles = false) {
|
|
const iconset = prefs.get('iconset') === 1 ? 'light/' : '';
|
|
const postfix = prefs.get('disableAll') ? 'x' : !hasStyles ? 'w' : '';
|
|
return `${iconset}$SIZE$${postfix}`;
|
|
}
|
|
|
|
function refreshIcon(tabId, force = false) {
|
|
const oldIcon = tabManager.get(tabId, 'icon');
|
|
const newIcon = getIconName(tabManager.get(tabId, 'styleIds', 0));
|
|
// (changing the icon only for the main page, frameId = 0)
|
|
|
|
if (!force && oldIcon === newIcon) {
|
|
return;
|
|
}
|
|
tabManager.set(tabId, 'icon', newIcon);
|
|
iconUtil.setIcon({
|
|
path: getIconPath(newIcon),
|
|
tabId
|
|
});
|
|
}
|
|
|
|
function getIconPath(icon) {
|
|
return ICON_SIZES.reduce(
|
|
(obj, size) => {
|
|
obj[size] = `/images/icon/${icon.replace('$SIZE$', size)}.png`;
|
|
return obj;
|
|
},
|
|
{}
|
|
);
|
|
}
|
|
|
|
/** @return {number | ''} */
|
|
function getStyleCount(tabId) {
|
|
const allIds = new Set();
|
|
const data = tabManager.get(tabId, 'styleIds') || {};
|
|
Object.values(data).forEach(frameIds => frameIds.forEach(id => allIds.add(id)));
|
|
return allIds.size || '';
|
|
}
|
|
|
|
function refreshGlobalIcon() {
|
|
iconUtil.setIcon({
|
|
path: getIconPath(getIconName())
|
|
});
|
|
}
|
|
|
|
function refreshIconBadgeColor() {
|
|
const color = prefs.get(prefs.get('disableAll') ? 'badgeDisabled' : 'badgeNormal');
|
|
iconUtil.setBadgeBackgroundColor({
|
|
color
|
|
});
|
|
}
|
|
|
|
function refreshAllIcons() {
|
|
for (const tabId of tabManager.list()) {
|
|
refreshIcon(tabId);
|
|
}
|
|
refreshGlobalIcon();
|
|
}
|
|
|
|
function refreshAllIconsBadgeText() {
|
|
for (const tabId of tabManager.list()) {
|
|
refreshIconBadgeText(tabId);
|
|
}
|
|
}
|
|
|
|
function refreshStaleBadges() {
|
|
for (const tabId of staleBadges) {
|
|
refreshIconBadgeText(tabId);
|
|
}
|
|
staleBadges.clear();
|
|
}
|
|
})();
|