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

bannerbanner/src/ PageActionButton.js
92 lines
2.7 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.title: Tab => string (to use as button tooltip), or null (to use
  11. * default title from the manifest)
  12. * - options.onClicked: Tab => void; executed on click, after which the button
  13. * state is automatically updated on all tabs.
  14. *
  15. * Returns an object with the following methods:
  16. * - update(tab?): update visibility, icons, etcetera of a given tab, or of
  17. * all tabs if the tab argument is omitted.
  18. *
  19. * Example usage:
  20. * const pageActionButton = PageActionButton({
  21. * visible: tab => tab.url.startsWith('https'),
  22. * icon: tab => isEnabled(tab.url) ? '/icon_enabled.svg' : '/icon_disabled.svg',
  23. * title: tab => isEnabled(tab.url) ? 'Disable' : 'Enable',
  24. * onClicked: tab => toggleEnabled(tab.url),
  25. * })
  26. * // Manually trigger an update of a tab.
  27. * pageActionButton.update(tab)
  28. */
  29. import browser from 'webextension-polyfill'
  30. export default function PageActionButton({
  31. visible = tab => true,
  32. icon = tab => null,
  33. title = tab => null,
  34. onClicked = tab => {},
  35. }) {
  36. async function setIcon(tab) {
  37. let iconSetting = await icon(tab)
  38. if (typeof iconSetting === 'string' || iconSetting === null) {
  39. iconSetting = { path: iconSetting }
  40. }
  41. browser.pageAction.setIcon({
  42. ...iconSetting,
  43. tabId: tab.id,
  44. })
  45. }
  46. async function setTitle(tab) {
  47. browser.pageAction.setTitle({
  48. title: await title(tab),
  49. tabId: tab.id,
  50. })
  51. }
  52. async function checkTab(tab) {
  53. if (await visible(tab)) {
  54. setIcon(tab)
  55. setTitle(tab)
  56. browser.pageAction.show(tab.id)
  57. } else {
  58. browser.pageAction.hide(tab.id)
  59. }
  60. }
  61. async function checkAllTabs() {
  62. const tabs = await browser.tabs.query({})
  63. for (const tab of tabs) {
  64. await checkTab(tab)
  65. }
  66. }
  67. // Show/hide the button on current tabs (XXX not awaiting it's completion)
  68. checkAllTabs()
  69. // Show/hide the button whenever a tab changes.
  70. browser.tabs.onUpdated.addListener((id, changeInfo, tab) => {
  71. checkTab(tab)
  72. });
  73. // Handle button clicks
  74. browser.pageAction.onClicked.addListener(async tab => {
  75. await onClicked(tab)
  76. await checkAllTabs(tab)
  77. })
  78. return {
  79. update: tab => tab ? checkTab(tab) : checkAllTabs()
  80. }
  81. }