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

bannerbanner/src/ PageActionButton.js
80 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({
  28. visible = tab => true,
  29. icon = tab => null,
  30. onClicked = tab => {},
  31. }) {
  32. async function setIcon(tab) {
  33. let iconSetting = await icon(tab)
  34. if (typeof iconSetting === 'string' || iconSetting === null) {
  35. iconSetting = { path: iconSetting }
  36. }
  37. browser.pageAction.setIcon({
  38. ...iconSetting,
  39. tabId: tab.id,
  40. })
  41. }
  42. async function checkTab(tab) {
  43. if (await visible(tab)) {
  44. setIcon(tab)
  45. browser.pageAction.show(tab.id)
  46. } else {
  47. browser.pageAction.hide(tab.id)
  48. }
  49. }
  50. async function checkAllTabs() {
  51. const tabs = await browser.tabs.query({})
  52. for (const tab of tabs) {
  53. await checkTab(tab)
  54. }
  55. }
  56. // Show/hide the button on current tabs (XXX not awaiting it's completion)
  57. checkAllTabs()
  58. // Show/hide the button whenever a tab changes.
  59. browser.tabs.onUpdated.addListener((id, changeInfo, tab) => {
  60. checkTab(tab)
  61. });
  62. // Handle button clicks
  63. browser.pageAction.onClicked.addListener(async tab => {
  64. await onClicked(tab)
  65. await checkAllTabs(tab)
  66. })
  67. return {
  68. update: tab => tab ? checkTab(tab) : checkAllTabs()
  69. }
  70. }