@@ -0,0 +1,12 @@ | |||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1" viewBox="0 0 20 20"> | |||||
<defs> | |||||
<clipPath id="b"> | |||||
<use width="100%" height="100%" xlink:href="#a"/> | |||||
</clipPath> | |||||
</defs> | |||||
<g color="#000" transform="translate(-12 -11)"> | |||||
<rect style="marker:none" width="17" height="4" x="13" y="25" fill="#cccccc" clip-path="url(#b)" overflow="visible" ry="0" transform="matrix(1.00048 0 0 1.3584 0 -10)"/> | |||||
<rect style="marker:none" width="17" height="4" x="13" y="12" fill="#cccccc" clip-path="url(#b)" overflow="visible" ry="0" transform="matrix(.99987 0 0 1.57087 0 -7)"/> | |||||
<rect style="marker:none" id="a" width="18" height="18" x="13" y="12" fill="none" stroke="#999" stroke-width="2" overflow="visible" ry="3"/> | |||||
</g> | |||||
</svg> |
@@ -5,7 +5,7 @@ | |||||
"page_action": { | "page_action": { | ||||
"browser_style": true, | "browser_style": true, | ||||
"default_title": "Ban banners", | "default_title": "Ban banners", | ||||
"default_icon": "/icon.svg" | |||||
"default_icon": "/icon_enabled.svg" | |||||
}, | }, | ||||
"background": { | "background": { | ||||
"scripts": ["background_script.js"] | "scripts": ["background_script.js"] | ||||
@@ -0,0 +1,75 @@ | |||||
/* Helper to manage the visibility and icon of a pageAction button. | |||||
* Each callback is evaluated whenever the tab has changed. | |||||
* Callbacks may be async (i.e. return a Promise). | |||||
* | |||||
* Arguments: | |||||
* - options.visible: Tab => boolean; whether to show the pageAction button | |||||
* - options.icon: Tab => either a string (the icon path), or null (to get the | |||||
* default icon from the manifest), or an object (with path or imageData, see | |||||
* docs of browser.pageAction.setIcon). | |||||
* - options.onClicked: Tab => void (or Promise of void); run on click, after | |||||
* which the button state is automatically updated on all tabs. | |||||
* | |||||
* Returns an object with the following methods: | |||||
* - update(tab?): update visibility, icons, etcetera of a given tab, or of | |||||
* all tabs if the tab argument is omitted. | |||||
* | |||||
* Example usage: | |||||
* const pageActionButton = PageActionButton({ | |||||
* visible: tab => tab.url.startsWith('https'), | |||||
* icon: tab => isEnabled(tab.url) ? '/icon_enabled.svg' : '/icon_disabled.svg', | |||||
* onClicked: tab => toggleEnabled(tab.url), | |||||
* }) | |||||
* // Manually trigger an update of a tab. | |||||
* pageActionButton.update(tab) | |||||
*/ | |||||
import browser from 'webextension-polyfill' | |||||
export default function PageActionButton({ visible, icon, onClicked }) { | |||||
async function setIcon(tab) { | |||||
let iconSetting = await icon(tab) | |||||
if (typeof iconSetting === 'string' || iconSetting === null) { | |||||
iconSetting = { path: iconSetting } | |||||
} | |||||
browser.pageAction.setIcon({ | |||||
...iconSetting, | |||||
tabId: tab.id, | |||||
}) | |||||
} | |||||
async function checkTab(tab) { | |||||
if (await visible(tab)) { | |||||
setIcon(tab) | |||||
browser.pageAction.show(tab.id) | |||||
} else { | |||||
browser.pageAction.hide(tab.id) | |||||
} | |||||
} | |||||
async function checkAllTabs() { | |||||
const tabs = await browser.tabs.query({}) | |||||
for (const tab of tabs) { | |||||
await checkTab(tab) | |||||
} | |||||
} | |||||
// Show/hide the button on current tabs (XXX not awaiting it's completion) | |||||
checkAllTabs() | |||||
// Show/hide the button whenever a tab changes. | |||||
browser.tabs.onUpdated.addListener((id, changeInfo, tab) => { | |||||
checkTab(tab) | |||||
}); | |||||
// Handle button clicks | |||||
browser.pageAction.onClicked.addListener(async tab => { | |||||
await onClicked(tab) | |||||
await checkAllTabs(tab) | |||||
}) | |||||
return { | |||||
update: tab => tab ? checkTab(tab) : checkAllTabs() | |||||
} | |||||
} |
@@ -1,8 +1,10 @@ | |||||
import browser from 'webextension-polyfill' | import browser from 'webextension-polyfill' | ||||
import pageActionButton from './pageActionButton' | |||||
import { toggleEnabled, isEnabled } from './perOrigin' | |||||
import PageActionButton from './PageActionButton' | |||||
import { toggleEnabled, isEnabled, onEnabledChange } from './perOrigin' | |||||
pageActionButton({ predicate: tab => true }) | |||||
browser.pageAction.onClicked.addListener(tab => toggleEnabled(tab.url)) | |||||
const pageActionButton = PageActionButton({ | |||||
visible: tab => true, | |||||
icon: async tab => (await isEnabled(tab.url)) ? '/icon_enabled.svg' : '/icon_disabled.svg', | |||||
onClicked: async tab => toggleEnabled(tab.url) | |||||
}) |
@@ -1,31 +0,0 @@ | |||||
/* Show a page action button on a tab whenever the given predicate is true. | |||||
* The predicate is passed a Tab object, and is evaluated whenever the tab has | |||||
* changed. | |||||
* | |||||
* Example usage: | |||||
* pageAction({ predicate: tab => tab.url.startsWith('https') }) | |||||
*/ | |||||
import browser from 'webextension-polyfill' | |||||
export default async function pageActionButton({ predicate }) { | |||||
async function maybeShowButton(tab) { | |||||
if (await predicate(tab)) { | |||||
browser.pageAction.show(tab.id) | |||||
} else { | |||||
browser.pageAction.hide(tab.id) | |||||
} | |||||
} | |||||
// Show/hide the button on current tabs. | |||||
const tabs = await browser.tabs.query({}) | |||||
for (const tab of tabs) { | |||||
maybeShowButton(tab) | |||||
} | |||||
// Show/hide the button whenever a tab changes. | |||||
browser.tabs.onUpdated.addListener((id, changeInfo, tab) => { | |||||
maybeShowButton(tab) | |||||
}); | |||||
} |