Refactor: pull out tab-manager and icon-manager
This commit is contained in:
parent
bef87f200e
commit
73f6e8a964
|
@ -1,7 +1,8 @@
|
|||
/* global download prefs openURL FIREFOX CHROME VIVALDI
|
||||
debounce URLS ignoreChromeError usercssHelper
|
||||
styleManager msg navigatorUtil iconUtil workerUtil contentScripts sync
|
||||
findExistingTab createTab activateTab isTabReplaceable getActiveTab */
|
||||
/* global download prefs openURL FIREFOX CHROME
|
||||
URLS ignoreChromeError usercssHelper
|
||||
styleManager msg navigatorUtil workerUtil contentScripts sync
|
||||
findExistingTab createTab activateTab isTabReplaceable getActiveTab
|
||||
iconManager */
|
||||
|
||||
'use strict';
|
||||
|
||||
|
@ -49,14 +50,7 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, {
|
|||
openEditor,
|
||||
|
||||
updateIconBadge(count) {
|
||||
// TODO: remove once our manifest's minimum_chrome_version is 50+
|
||||
// Chrome 49 doesn't report own extension pages in webNavigation apparently
|
||||
// so we do a force update which doesn't use the cache.
|
||||
if (CHROME && CHROME < 2661 && this.sender.tab.url.startsWith(URLS.ownOrigin)) {
|
||||
updateIconBadgeForce(this.sender.tab.id, count);
|
||||
} else {
|
||||
updateIconBadge(this.sender.tab.id, count);
|
||||
}
|
||||
iconManager.updateIconBadge(this.sender.tab.id, count);
|
||||
return true;
|
||||
},
|
||||
|
||||
|
@ -87,6 +81,14 @@ var browserCommands, contextMenus;
|
|||
// register all listeners
|
||||
msg.on(onRuntimeMessage);
|
||||
|
||||
// tell apply.js to refresh styles for non-committed navigation
|
||||
navigatorUtil.onUrlChange(({tabId, frameId}, type) => {
|
||||
if (type !== 'committed') {
|
||||
msg.sendTab(tabId, {method: 'urlChanged'}, {frameId})
|
||||
.catch(msg.ignoreError);
|
||||
}
|
||||
});
|
||||
|
||||
if (FIREFOX) {
|
||||
// FF misses some about:blank iframes so we inject our content script explicitly
|
||||
navigatorUtil.onDOMContentLoaded(webNavIframeHelperFF, {
|
||||
|
@ -106,55 +108,10 @@ if (chrome.commands) {
|
|||
chrome.commands.onCommand.addListener(command => browserCommands[command]());
|
||||
}
|
||||
|
||||
const tabData = new Map();
|
||||
const tabDataFor = tabId => {
|
||||
let data = tabData.get(tabId);
|
||||
if (!data) tabData.set(tabId, (data = {}));
|
||||
return data;
|
||||
};
|
||||
chrome.tabs.onRemoved.addListener(tabId => tabData.delete(tabId));
|
||||
chrome.tabs.onReplaced.addListener((added, removed) => tabData.delete(removed));
|
||||
|
||||
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();
|
||||
});
|
||||
|
||||
navigatorUtil.onUrlChange(({tabId, frameId, transitionQualifiers, url}, type) => {
|
||||
if (type !== 'committed') {
|
||||
msg.sendTab(tabId, {method: 'urlChanged'}, {frameId})
|
||||
.catch(msg.ignoreError);
|
||||
} else if (!frameId) {
|
||||
if (usercssHelper.testUrl(url) && !`${tabDataFor(tabId).url}`.startsWith(URLS.installUsercss)) {
|
||||
usercssHelper.openInstallerPage(tabId, url).then(newUrl => {
|
||||
tabDataFor(tabId).url = newUrl || url;
|
||||
});
|
||||
}
|
||||
// it seems that the tab icon would be reset by navigation. We
|
||||
// invalidate the cache here so it would be refreshed by `apply.js`.
|
||||
tabData.set(tabId, {url});
|
||||
// however, if the tab was swapped in by forward/backward buttons,
|
||||
// `apply.js` doesn't notify the background to update the icon,
|
||||
// so we have to refresh it manually.
|
||||
if (transitionQualifiers.includes('forward_back')) {
|
||||
msg.sendTab(tabId, {method: 'updateCount'}).catch(msg.ignoreError);
|
||||
}
|
||||
// detect usercss and open the installer page
|
||||
navigatorUtil.onCommitted(({tabId, frameId, url}) => {
|
||||
if (!frameId && usercssHelper.testUrl(url)) {
|
||||
usercssHelper.openInstallerPage(tabId, url);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -307,74 +264,6 @@ function webNavIframeHelperFF({tabId, frameId}) {
|
|||
});
|
||||
}
|
||||
|
||||
function updateIconBadge(tabId, count) {
|
||||
const tabIcon = tabDataFor(tabId);
|
||||
if (tabIcon.count === count) {
|
||||
return;
|
||||
}
|
||||
const oldCount = tabIcon.count;
|
||||
tabIcon.count = count;
|
||||
refreshIconBadgeText(tabId, tabIcon);
|
||||
if (Boolean(oldCount) !== Boolean(count)) {
|
||||
refreshIcon(tabId, tabIcon);
|
||||
}
|
||||
}
|
||||
|
||||
function updateIconBadgeForce(tabId, count) {
|
||||
refreshIconBadgeText(tabId, {count});
|
||||
refreshIcon(tabId, {count});
|
||||
}
|
||||
|
||||
function refreshIconBadgeText(tabId, icon) {
|
||||
iconUtil.setBadgeText({
|
||||
text: prefs.get('show-badge') && icon.count ? String(icon.count) : '',
|
||||
tabId
|
||||
});
|
||||
}
|
||||
|
||||
function refreshIcon(tabId, icon) {
|
||||
const disableAll = prefs.get('disableAll');
|
||||
const iconset = prefs.get('iconset') === 1 ? 'light/' : '';
|
||||
const postfix = disableAll ? 'x' : !icon.count ? 'w' : '';
|
||||
const iconType = iconset + postfix;
|
||||
|
||||
if (icon.iconType === iconType) {
|
||||
return;
|
||||
}
|
||||
icon.iconType = iconset + postfix;
|
||||
const sizes = FIREFOX || CHROME >= 2883 && !VIVALDI ? [16, 32] : [19, 38];
|
||||
iconUtil.setIcon({
|
||||
path: sizes.reduce(
|
||||
(obj, size) => {
|
||||
obj[size] = `/images/icon/${iconset}${size}${postfix}.png`;
|
||||
return obj;
|
||||
},
|
||||
{}
|
||||
),
|
||||
tabId
|
||||
});
|
||||
}
|
||||
|
||||
function refreshIconBadgeColor() {
|
||||
const color = prefs.get(prefs.get('disableAll') ? 'badgeDisabled' : 'badgeNormal');
|
||||
iconUtil.setBadgeBackgroundColor({
|
||||
color
|
||||
});
|
||||
}
|
||||
|
||||
function refreshAllIcons() {
|
||||
for (const [tabId, data] of tabData) {
|
||||
refreshIcon(tabId, data);
|
||||
}
|
||||
refreshIcon(null, {}); // default icon
|
||||
}
|
||||
|
||||
function refreshAllIconsBadgeText() {
|
||||
for (const [tabId, data] of tabData) {
|
||||
refreshIconBadgeText(tabId, data);
|
||||
}
|
||||
}
|
||||
|
||||
function onRuntimeMessage(msg, sender) {
|
||||
if (msg.method !== 'invokeAPI') {
|
||||
return;
|
||||
|
|
101
background/icon-manager.js
Normal file
101
background/icon-manager.js
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* global prefs debounce iconUtil FIREFOX CHROME VIVALDI tabManager */
|
||||
/* exported iconManager */
|
||||
'use strict';
|
||||
|
||||
const iconManager = (() => {
|
||||
const ICON_SIZES = FIREFOX || CHROME >= 2883 && !VIVALDI ? [16, 32] : [19, 38];
|
||||
|
||||
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();
|
||||
});
|
||||
|
||||
return {updateIconBadge};
|
||||
|
||||
// FIXME: in some cases, we only have to redraw the badge. is it worth a optimization?
|
||||
function updateIconBadge(tabId, count, force = true) {
|
||||
tabManager.setMeta(tabId, 'count', count);
|
||||
refreshIconBadgeText(tabId);
|
||||
refreshIcon(tabId, force);
|
||||
}
|
||||
|
||||
function refreshIconBadgeText(tabId) {
|
||||
const count = tabManager.getMeta(tabId, 'count');
|
||||
iconUtil.setBadgeText({
|
||||
text: prefs.get('show-badge') && count ? String(count) : '',
|
||||
tabId
|
||||
});
|
||||
}
|
||||
|
||||
function getIconName(count = 0) {
|
||||
const iconset = prefs.get('iconset') === 1 ? 'light/' : '';
|
||||
const postfix = prefs.get('disableAll') ? 'x' : !count ? 'w' : '';
|
||||
return `${iconset}$SIZE$${postfix}`;
|
||||
}
|
||||
|
||||
function refreshIcon(tabId, force = false) {
|
||||
const oldIcon = tabManager.getMeta(tabId, 'icon');
|
||||
const newIcon = getIconName(tabManager.getMeta(tabId, 'count'));
|
||||
|
||||
if (!force && oldIcon === newIcon) {
|
||||
return;
|
||||
}
|
||||
tabManager.setMeta(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;
|
||||
},
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
})();
|
48
background/tab-manager.js
Normal file
48
background/tab-manager.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* global navigatorUtil */
|
||||
/* exported tabManager */
|
||||
'use strict';
|
||||
|
||||
const tabManager = (() => {
|
||||
const listeners = [];
|
||||
const cache = new Map();
|
||||
chrome.tabs.onRemoved.addListener(tabId => cache.delete(tabId));
|
||||
chrome.tabs.onReplaced.addListener((added, removed) => cache.delete(removed));
|
||||
navigatorUtil.onUrlChange(({tabId, frameId, url}) => {
|
||||
if (frameId) return;
|
||||
setMeta(tabId, 'url', url);
|
||||
emitUpdate({tabId, url});
|
||||
});
|
||||
|
||||
return {onUpdate, setMeta, getMeta, list};
|
||||
|
||||
function list() {
|
||||
return cache.keys();
|
||||
}
|
||||
|
||||
function onUpdate(callback) {
|
||||
listeners.push(callback);
|
||||
}
|
||||
|
||||
function emitUpdate(e) {
|
||||
for (const callback of listeners) {
|
||||
try {
|
||||
callback(e);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setMeta(tabId, key, value) {
|
||||
let meta = cache.get(tabId);
|
||||
if (!meta) {
|
||||
meta = new Map();
|
||||
cache.set(tabId, meta);
|
||||
}
|
||||
meta.set(key, value);
|
||||
}
|
||||
|
||||
function getMeta(tabId, key) {
|
||||
return cache.get(tabId).get(key);
|
||||
}
|
||||
})();
|
|
@ -30,7 +30,8 @@ const usercssHelper = (() => {
|
|||
testUrl(url) {
|
||||
return url.includes('.user.') &&
|
||||
/^(https?|file|ftps?):/.test(url) &&
|
||||
/\.user\.(css|styl)$/.test(url.split(/[#?]/, 1)[0]);
|
||||
/\.user\.(css|styl)$/.test(url.split(/[#?]/, 1)[0]) &&
|
||||
!url.startsWith(URLS.installUsercss);
|
||||
},
|
||||
|
||||
openInstallerPage(tabId, url) {
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
"background/style-manager.js",
|
||||
"background/navigator-util.js",
|
||||
"background/icon-util.js",
|
||||
"background/tab-manager.js",
|
||||
"background/icon-manager.js",
|
||||
"background/background.js",
|
||||
"background/usercss-helper.js",
|
||||
"background/style-via-api.js",
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
"update-transifex": "tx push -s",
|
||||
"build-vendor": "shx rm -rf vendor/* && node tools/build-vendor",
|
||||
"zip": "node tools/zip.js",
|
||||
"start": "web-ext run --bc",
|
||||
"start-chrome": "web-ext run -t chromium --bc",
|
||||
"start": "web-ext run",
|
||||
"start-chrome": "web-ext run -t chromium",
|
||||
"preversion": "npm test",
|
||||
"version": "sync-version manifest.json && git add .",
|
||||
"postversion": "npm run zip && git push --follow-tags"
|
||||
|
|
Loading…
Reference in New Issue
Block a user