Browser extension to hide view-reducing screen junk from websites.

bannerbanner/src/ PageActionButton.js
76 lines
2.3 KiB

  1. /* Helper to manage the visibility and icon of a pageAction button.
  2. * Each callback is evaluated whenever the tab has changed.
  3. * Callbacks may be async (i.e. return a Promise).
  4. *
  5. * Arguments:
  6. * - options.visible: Tab => boolean; whether to show the pageAction button
  7. * - options.icon: Tab => either a string (the icon path), or null (to get the
  8. * default icon from the manifest), or an object (with path or imageData, see
  9. * docs of browser.pageAction.setIcon).
  10. * - options.onClicked: Tab => void (or Promise of void); run on click, after
  11. * which the button state is automatically updated on all tabs.
  12. *
  13. * Returns an object with the following methods:
  14. * - update(tab?): update visibility, icons, etcetera of a given tab, or of
  15. * all tabs if the tab argument is omitted.
  16. *
  17. * Example usage:
  18. * const pageActionButton = PageActionButton({
  19. * visible: tab => tab.url.startsWith('https'),
  20. * icon: tab => isEnabled(tab.url) ? '/icon_enabled.svg' : '/icon_disabled.svg',
  21. * onClicked: tab => toggleEnabled(tab.url),
  22. * })
  23. * // Manually trigger an update of a tab.
  24. * pageActionButton.update(tab)
  25. */
  26. import browser from 'webextension-polyfill'
  27. export default function PageActionButton({ visible, icon, onClicked }) {
  28. async function setIcon(tab) {
  29. let iconSetting = await icon(tab)
  30. if (typeof iconSetting === 'string' || iconSetting === null) {
  31. iconSetting = { path: iconSetting }
  32. }
  33. browser.pageAction.setIcon({
  34. ...iconSetting,
  35. tabId: tab.id,
  36. })
  37. }
  38. async function checkTab(tab) {
  39. if (await visible(tab)) {
  40. setIcon(tab)
  41. browser.pageAction.show(tab.id)
  42. } else {
  43. browser.pageAction.hide(tab.id)
  44. }
  45. }
  46. async function checkAllTabs() {
  47. const tabs = await browser.tabs.query({})
  48. for (const tab of tabs) {
  49. await checkTab(tab)
  50. }
  51. }
  52. // Show/hide the button on current tabs (XXX not awaiting it's completion)
  53. checkAllTabs()
  54. // Show/hide the button whenever a tab changes.
  55. browser.tabs.onUpdated.addListener((id, changeInfo, tab) => {
  56. checkTab(tab)
  57. });
  58. // Handle button clicks
  59. browser.pageAction.onClicked.addListener(async tab => {
  60. await onClicked(tab)
  61. await checkAllTabs(tab)
  62. })
  63. return {
  64. update: tab => tab ? checkTab(tab) : checkAllTabs()
  65. }
  66. }