observers.ts 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import { SelectorListenerOptions, SelectorObserver, SelectorObserverOptions } from "@sv443-network/userutils";
  2. import type { ObserverName } from "./types";
  3. import { emitInterface } from "./interface";
  4. import { error } from "./utils";
  5. /** Options that are applied to every SelectorObserver instance */
  6. const defaultObserverOptions: SelectorObserverOptions = {
  7. defaultDebounce: 100,
  8. };
  9. export const observers = {} as Record<ObserverName, SelectorObserver>;
  10. /** Call after DOM load to initialize all SelectorObserver instances */
  11. export function initObservers() {
  12. try {
  13. // #SECTION body = the entire <body> element - use sparingly due to performance impacts!
  14. observers.body = new SelectorObserver(document.body, {
  15. ...defaultObserverOptions,
  16. subtree: false,
  17. });
  18. observers.body.enable();
  19. // #SECTION playerBar = media controls bar at the bottom of the page
  20. const playerBarSelector = "ytmusic-app-layout ytmusic-player-bar.ytmusic-app";
  21. observers.playerBar = new SelectorObserver(playerBarSelector, {
  22. ...defaultObserverOptions,
  23. defaultDebounce: 200,
  24. });
  25. observers.body.addListener(playerBarSelector, {
  26. listener: () => {
  27. console.log("#DBG-UU enabling playerBar observer");
  28. observers.playerBar.enable();
  29. },
  30. });
  31. // #SECTION playerBarInfo = song title, artist, album, etc. inside the player bar
  32. const playerBarInfoSelector = `${playerBarSelector} .middle-controls .content-info-wrapper`;
  33. observers.playerBarInfo = new SelectorObserver(playerBarInfoSelector, {
  34. ...defaultObserverOptions,
  35. attributes: true,
  36. attributeFilter: ["title"],
  37. });
  38. observers.playerBarInfo.addListener(playerBarInfoSelector, {
  39. listener: () => {
  40. console.log("#DBG-UU enabling playerBarTitle observer");
  41. observers.playerBarInfo.enable();
  42. },
  43. });
  44. // #DEBUG example: listen for title change:
  45. observers.playerBarInfo.addListener("yt-formatted-string.title", {
  46. continuous: true,
  47. listener: (titleElem) => {
  48. console.log("#DBG-UU >>>>> title changed", titleElem.title);
  49. },
  50. });
  51. emitInterface("bytm:observersReady");
  52. }
  53. catch(err) {
  54. error("Failed to initialize observers:", err);
  55. }
  56. }
  57. /** Interface function for adding listeners to the already present observers */
  58. export function addSelectorListener<TElem extends Element>(observerName: ObserverName, selector: string, options: SelectorListenerOptions<TElem>) {
  59. observers[observerName].addListener(selector, options);
  60. }